gol_core/board/
board_callback.rs1use crate::IndexedDataOwned;
2use rayon::prelude::*;
3use std::sync::{Arc, Mutex};
4use std::thread::{self, JoinHandle};
5
6pub trait BoardCallbackWithoutStates<T, CI>: Send + Sync
7where
8 T: Send + Sync,
9 CI: Send + Sync,
10{
11 fn setup(&mut self) {}
12 fn execute(&mut self);
13 fn cleanup(&mut self) {}
14}
15
16pub trait BoardCallbackWithStates<T, CI, I>: Send + Sync
17where
18 T: Send + Sync,
19 CI: Send + Sync,
20 I: ParallelIterator<Item = IndexedDataOwned<CI, T>>,
21{
22 fn setup(&mut self) {}
23 fn execute(&mut self, states: I);
24 fn cleanup(&mut self) {}
25}
26
27pub enum BoardCallback<T, CI, I> {
28 WithoutStates(Box<dyn BoardCallbackWithoutStates<T, CI>>),
29 WithStates(Box<dyn BoardCallbackWithStates<T, CI, I>>),
30}
31
32pub struct BoardCallbackManager<T, CI, I>
33where
34 T: Send + Sync,
35 CI: Send + Sync,
36 I: ParallelIterator<Item = IndexedDataOwned<CI, T>>,
37{
38 callbacks: Arc<Mutex<Vec<BoardCallback<T, CI, I>>>>,
39 callback_handle: Arc<Mutex<Option<JoinHandle<()>>>>,
40}
41
42impl<T, CI> BoardCallbackManager<T, CI, rayon::vec::IntoIter<IndexedDataOwned<CI, T>>>
43where
44 T: 'static + Send + Sync + Clone,
45 CI: 'static + Send + Sync + Clone,
46{
47 pub fn new(
48 callbacks: Vec<BoardCallback<T, CI, rayon::vec::IntoIter<IndexedDataOwned<CI, T>>>>,
49 ) -> Self {
50 Self {
51 callbacks: Arc::new(Mutex::new(callbacks)),
52 callback_handle: Arc::new(Mutex::new(None)),
53 }
54 }
55
56 pub fn setup_all(&mut self) {
57 self.callbacks
58 .lock()
59 .unwrap()
60 .iter_mut()
61 .for_each(|ele| match ele {
62 BoardCallback::WithoutStates(val) => val.setup(),
63 BoardCallback::WithStates(val) => val.setup(),
64 });
65 }
66
67 pub fn call(&self, next_states: Vec<IndexedDataOwned<CI, T>>) {
68 self.block_until_finish();
69 debug_assert!(self.callback_handle.lock().unwrap().is_none());
70
71 let mut handle = self.callback_handle.lock().unwrap();
72 let callbacks = Arc::clone(&self.callbacks);
73 *handle = Some(thread::spawn(move || {
74 Arc::clone(&callbacks)
75 .lock()
76 .unwrap()
77 .par_iter_mut()
78 .for_each(|ele| match ele {
79 BoardCallback::WithoutStates(val) => val.execute(),
80 BoardCallback::WithStates(val) => {
81 val.execute(next_states.clone().into_par_iter())
82 }
83 });
84 }));
85 }
86
87 pub fn cleanup_all(&mut self) {
88 self.block_until_finish();
89 self.callbacks
90 .lock()
91 .unwrap()
92 .iter_mut()
93 .for_each(|ele| match ele {
94 BoardCallback::WithoutStates(val) => val.cleanup(),
95 BoardCallback::WithStates(val) => val.cleanup(),
96 });
97 }
98
99 fn block_until_finish(&self) {
100 if let Some(handle) = self.callback_handle.lock().unwrap().take() {
101 handle.join().unwrap();
102 }
103 let mut handle = self.callback_handle.lock().unwrap();
104 *handle = None;
105 }
106}