gol_core/callback/
model_states.rs

1use 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}