use super::{LaneSlot, epoch::Epoch, lane_loop};
use crate::{RateModel, WorkerLane};
use std::{
sync::{Arc, Mutex},
thread,
time::Duration,
};
const FEED_WAIT: Duration = Duration::from_millis(50);
pub trait LaneFeed: Sync {
fn next(&self, first_index: usize, wait: Duration) -> Vec<(Arc<dyn WorkerLane>, RateModel)>;
}
pub(super) fn spawn_lane<'scope, 'env>(
scope: &'scope thread::Scope<'scope, 'env>,
epoch: &'env Epoch<'env>,
index: usize,
slot: Arc<LaneSlot>,
) {
scope.spawn(move || {
let left = lane_loop::run_lane(epoch, index, &*slot.lane, &slot.rate);
if !left {
epoch.roster.leave();
}
});
}
pub(super) fn feed_lanes<'scope, 'env>(
scope: &'scope thread::Scope<'scope, 'env>,
epoch: &'env Epoch<'env>,
feed: &'env dyn LaneFeed,
) {
while !epoch.roster.is_closed() && !epoch.cancel.is_cancelled() {
let late = feed.next(epoch.lane_count(), FEED_WAIT);
for (lane, rate) in late {
if !epoch.roster.try_join() {
return;
}
let slot = Arc::new(LaneSlot {
lane,
rate: Mutex::new(rate),
});
let index = epoch.push_lane(Arc::clone(&slot));
spawn_lane(scope, epoch, index, slot);
}
}
}