heredity/
lib.rs

1//! General library for genetic algorithm implementations.
2
3use 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/// Enumeration of possible errors returned by the simulation.
20#[derive(Debug, Snafu)]
21pub enum SimulationError {
22    /// Returned when the simulation thread failed to stop.
23    JoinError,
24}
25
26struct Handle {
27    pub thread_handle: thread::JoinHandle<()>,
28    pub stop_tx: mpsc::Sender<bool>,
29}
30
31/// Main simulation runner.
32pub struct ThreadSim {
33    handle: Handle,
34    rx: mpsc::Receiver<SimResult>,
35}
36
37impl ThreadSim {
38    /// Starts a simulation thread using the provided parameters.
39    ///
40    /// `start` returns a result receiver that can be used to read result snapshots.
41    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    /// Returns a reference to the simulation result receiver.
62    pub fn results(&self) -> &mpsc::Receiver<SimResult> {
63        &self.rx
64    }
65
66    /// Stops the simulation.
67    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}