use concinnity_core::ecs::ScheduleMode;
use concinnity_core::physics::PhysicsFanout;
use concinnity_core::physics::{Fanout, Simulation};
use concinnity_host::thread::jobs::{self, JobPool};
#[derive(Debug)]
pub(crate) struct PoolFanout;
fn pool_for(mode: ScheduleMode) -> &'static JobPool {
match mode {
ScheduleMode::Parallel => jobs::pool(),
ScheduleMode::Serial => jobs::serial_pool(),
}
}
impl PhysicsFanout for PoolFanout {
fn worker_count(&self, mode: ScheduleMode) -> usize {
pool_for(mode).thread_count()
}
fn step(&self, sim: &mut Simulation, dt: f32, mode: ScheduleMode) {
sim.step_with(dt, &PoolLease(pool_for(mode)));
}
}
struct PoolLease(&'static JobPool);
impl Fanout for PoolLease {
fn workers(&self) -> usize {
self.0.thread_count()
}
fn scope<R, F>(&self, work: F) -> R
where
F: FnOnce() -> R + Send,
R: Send,
{
self.0.install(work)
}
fn for_each<T, F>(&self, items: &mut [T], body: F)
where
T: Send,
F: Fn(&mut T) + Send + Sync,
{
self.0.parallel_for(items, body);
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn a_serial_schedule_lends_one_worker() {
assert_eq!(PoolFanout.worker_count(ScheduleMode::Serial), 1);
assert!(PoolFanout.worker_count(ScheduleMode::Parallel) >= 1);
}
}