1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
use std::sync::Arc;
pub use spin::Mutex;

pub struct Store<T,A> where T:Default+Reduceable<A>+Sync+Send,A:Sync+Send{
    pub state:Arc<Mutex<T>>,
    watchers:Arc<Mutex<Vec<Box<dyn Fn(Arc<Mutex<T>>)->()+Sync+Send>>>>,
    phantom: std::marker::PhantomData<A>
}

impl<T,A> Store<T,A> where T:Default+Reduceable<A>+Sync+Send,A:Sync+Send{
    pub fn get() -> &'static Mutex<Self>{
        globals::get()
    }
    
    pub fn reduce(&self,a:&A) -> Arc<Mutex<T>>{
        let s = T::reduce(self.state.clone(),a);
        for w in self.watchers.lock().iter() {
            w(s.clone())
        }
        s
    }

    pub fn watch<F>(&mut self, watcher:F) where F:'static+Fn(Arc<Mutex<T>>)->()+Sync+Send{
        self.watchers.lock().push(Box::new(watcher))
    }
}

impl<T,A> Default for  Store<T,A> where T:Default+Reduceable<A>+Sync+Send,A:Sync+Send{
    fn default() -> Self {
        Store::<T,A>{
            state:Arc::new(Mutex::new(T::default())),
            watchers: Arc::new(Mutex::new(Vec::new())),
            phantom: std::marker::PhantomData
        }
    }
}

pub trait Reduceable<A> where A:Sync+Send {
    fn reduce(state:Arc<Mutex<Self>>,action:&A) -> Arc<Mutex<Self>>;
}