gol_core/callback/
model_states.rs1use crate::util::sync_util::ReadOnlyLock;
2use crate::{BoardCallbackWithStates, IndexedDataOwned};
3use rayon::prelude::*;
4use std::collections::HashMap;
5use std::hash::Hash;
6use std::sync::{Arc, RwLock, RwLockReadGuard, TryLockResult};
7
8pub struct StatesReadOnly<CI, T>
9where
10 CI: Hash,
11{
12 trivial_state: T,
13 lookup: ReadOnlyLock<(usize, HashMap<CI, T>)>,
14}
15
16impl<CI, T> Clone for StatesReadOnly<CI, T>
17where
18 CI: Hash,
19 T: Clone,
20{
21 fn clone(&self) -> Self {
22 Self::new(self.trivial_state.clone(), self.lookup.clone())
23 }
24}
25
26impl<CI, T> StatesReadOnly<CI, T>
27where
28 CI: Hash,
29{
30 pub fn new(trivial_state: T, lock: ReadOnlyLock<(usize, HashMap<CI, T>)>) -> Self {
31 Self {
32 trivial_state,
33 lookup: lock,
34 }
35 }
36
37 pub fn trivial_state(&self) -> &T {
38 &self.trivial_state
39 }
40
41 pub fn try_read(&self) -> TryLockResult<RwLockReadGuard<(usize, HashMap<CI, T>)>> {
42 self.lookup.try_read()
43 }
44}
45
46pub struct StatesCallback<CI, T>
47where
48 CI: Hash,
49{
50 trivial_state: T,
51 non_trivial_lookup: Arc<RwLock<(usize, HashMap<CI, T>)>>,
52}
53
54impl<CI, T> StatesCallback<CI, T>
55where
56 CI: Hash,
57{
58 pub fn new(trivial_state: T) -> Self {
59 Self {
60 trivial_state,
61 non_trivial_lookup: Arc::new(RwLock::new((0, HashMap::new()))),
62 }
63 }
64
65 pub fn set_non_trivial_lookup(&mut self, lookup: HashMap<CI, T>) {
66 let mut lookup_unlocked = self.non_trivial_lookup.write().unwrap();
67 let iter_count = lookup_unlocked.0 + 1;
68 *lookup_unlocked = (iter_count, lookup);
69 }
70
71 pub fn clone_read_only(&self) -> StatesReadOnly<CI, T>
72 where
73 T: Clone,
74 {
75 StatesReadOnly::new(
76 self.trivial_state.clone(),
77 ReadOnlyLock::from(Arc::clone(&self.non_trivial_lookup)),
78 )
79 }
80}
81
82impl<T, CI, I> BoardCallbackWithStates<T, CI, I> for StatesCallback<CI, T>
83where
84 T: Send + Sync + Clone + Eq,
85 CI: Send + Sync + Clone + Eq + Hash,
86 I: ParallelIterator<Item = IndexedDataOwned<CI, T>>,
87{
88 fn execute(&mut self, states: I) {
89 let new_lookup: HashMap<CI, T> = states
90 .filter(|ele| &ele.1 != &self.trivial_state)
91 .map(|ele| (ele.0, ele.1))
92 .collect();
93 self.set_non_trivial_lookup(new_lookup);
94 }
95
96 fn cleanup(&mut self) {
97 self.set_non_trivial_lookup(HashMap::new());
98 }
99}