1use std::sync::mpsc;
4use std::thread;
5
6use snafu::Snafu;
7
8mod cell;
9mod fitness;
10mod parameters;
11mod sim_result;
12mod simulation;
13
14pub use fitness::FitnessEvaluator;
15pub use parameters::Parameters;
16pub use sim_result::SimResult;
17use simulation::Simulation;
18
19#[derive(Debug, Snafu)]
21pub enum SimulationError {
22 JoinError,
24}
25
26struct Handle {
27 pub thread_handle: thread::JoinHandle<()>,
28 pub stop_tx: mpsc::Sender<bool>,
29}
30
31pub struct ThreadSim {
33 handle: Handle,
34 rx: mpsc::Receiver<SimResult>,
35}
36
37impl ThreadSim {
38 pub fn start<T>(params: Parameters<T>) -> ThreadSim
42 where
43 T: 'static + FitnessEvaluator + Send + Sync,
44 {
45 let (result_tx, result_rx) = mpsc::channel();
46 let (stop_tx, stop_rx) = mpsc::channel();
47
48 let sim = Simulation::new(params);
49 let thread_handle =
50 thread::spawn(move || ThreadSim::internal_sim_loop(sim, stop_rx, result_tx));
51
52 ThreadSim {
53 handle: Handle {
54 stop_tx,
55 thread_handle,
56 },
57 rx: result_rx,
58 }
59 }
60
61 pub fn results(&self) -> &mpsc::Receiver<SimResult> {
63 &self.rx
64 }
65
66 pub fn stop(self) -> Result<(), SimulationError> {
68 self.handle
69 .stop_tx
70 .send(true)
71 .map_err(|_e| SimulationError::JoinError)?;
72 self.handle
73 .thread_handle
74 .join()
75 .map_err(|_e| SimulationError::JoinError)?;
76 Ok(())
77 }
78
79 fn internal_sim_loop<T: FitnessEvaluator + Send + Sync>(
80 mut sim: Simulation<T>,
81 stop_rx: mpsc::Receiver<bool>,
82 result_tx: mpsc::Sender<SimResult>,
83 ) {
84 sim.run(result_tx, stop_rx)
85 }
86}