pub mod instance;
use crate::context::ExecutorStatus;
use crate::execution::SimulationResult;
use crate::execution::engine::Engine;
use crate::execution::strategy::ContinueStrategy;
use crate::modeling::model::Model;
use crate::primitive::time::{TickStatus, TimeTick};
pub trait Runner<E, M: Model<E>, CS: ContinueStrategy<E, M, Self::Err>> {
type Err: std::fmt::Debug;
fn run<F>(
&mut self,
engine: Engine<E, M>,
model: M,
should_stop: F,
) -> SimulationResult<M, CS::Err>
where
F: FnMut(&M, ExecutorStatus, TickStatus) -> bool;
fn run_playback<F>(
&mut self,
engine: Engine<E, M>,
model: M,
duration: std::time::Duration,
mut should_stop: F,
) -> SimulationResult<M, CS::Err>
where
F: FnMut(&M, ExecutorStatus, TickStatus) -> bool,
{
self.run(engine, model, |model, exec_status, tick_status| {
if should_stop(model, exec_status, tick_status) {
return true;
}
std::thread::sleep(duration);
false
})
}
fn run_do_ticks(
&mut self,
engine: Engine<E, M>,
model: M,
tick_count: TimeTick,
include_zero_tick: bool,
) -> SimulationResult<M, CS::Err> {
self.run(
engine,
model,
|_, _, next_handle_tick_status: TickStatus| {
next_handle_tick_status.is_done_ticks(include_zero_tick, tick_count)
},
)
}
fn run_until_idle(&mut self, engine: Engine<E, M>, model: M) -> SimulationResult<M, CS::Err> {
self.run(engine, model, |_, executor_status: ExecutorStatus, _| {
executor_status == ExecutorStatus::NoMoreEvent
})
}
fn run_until_model_condition<F>(
&mut self,
engine: Engine<E, M>,
model: M,
mut should_stop_model_condition: F,
) -> SimulationResult<M, CS::Err>
where
F: FnMut(&M) -> bool,
{
self.run(engine, model, |model: &M, _, _| {
should_stop_model_condition(model)
})
}
fn run_batch_parallel<MF, EF, F>(
&self,
count: usize,
engine_builder: EF,
model_builder: MF,
should_stop: F,
) -> Vec<SimulationResult<M, CS::Err>>
where
Self: Clone + Sync,
EF: Fn(usize) -> Engine<E, M> + Sync,
M: Send,
MF: Fn(usize) -> M + Sync,
F: FnMut(&M, ExecutorStatus, TickStatus) -> bool + Clone + Sync,
CS::Err: Send,
{
use rayon::prelude::*;
(0..count)
.into_par_iter()
.map(|index| {
let mut local_runner = self.clone();
let local_engine = engine_builder(index);
let local_model = model_builder(index);
local_runner.run(local_engine, local_model, should_stop.clone())
})
.collect()
}
}