calc_thunk/
calc_thunk.rs

1use std::sync::{Arc, Condvar, Mutex};
2use std::thread;
3
4use rs_store::{DispatchOp, Dispatcher, StoreBuilder};
5use rs_store::{Reducer, Subscriber};
6
7#[derive(Debug, Clone)]
8enum CalcAction {
9    Add(i32),
10    Subtract(i32),
11}
12
13struct CalcReducer {}
14
15impl Default for CalcReducer {
16    fn default() -> CalcReducer {
17        CalcReducer {}
18    }
19}
20
21#[derive(Debug, Clone)]
22struct CalcState {
23    count: i32,
24}
25
26impl Default for CalcState {
27    fn default() -> CalcState {
28        CalcState { count: 0 }
29    }
30}
31
32impl Reducer<CalcState, CalcAction> for CalcReducer {
33    fn reduce(&self, state: &CalcState, action: &CalcAction) -> DispatchOp<CalcState, CalcAction> {
34        match action {
35            CalcAction::Add(i) => {
36                println!("CalcReducer::reduce: + {}", i);
37                DispatchOp::Dispatch(
38                    CalcState {
39                        count: state.count + i,
40                    },
41                    None,
42                )
43            }
44            CalcAction::Subtract(i) => {
45                println!("CalcReducer::reduce: - {}", i);
46                DispatchOp::Dispatch(
47                    CalcState {
48                        count: state.count - i,
49                    },
50                    None,
51                )
52            }
53        }
54    }
55}
56
57struct CalcSubscriber {
58    id: i32,
59    last: Mutex<CalcState>,
60}
61
62impl Default for CalcSubscriber {
63    fn default() -> Self {
64        Self {
65            id: 0,
66            last: Mutex::new(CalcState::default()),
67        }
68    }
69}
70
71// impl CalcSubscriber {
72//     fn new(id: i32) -> Self {
73//         Self {
74//             id,
75//             last: Mutex::new(CalcState::default()),
76//         }
77//     }
78// }
79
80impl Subscriber<CalcState, CalcAction> for CalcSubscriber {
81    fn on_notify(&self, state: &CalcState, action: &CalcAction) {
82        match action {
83            CalcAction::Add(_i) => {
84                println!(
85                    "CalcSubscriber::on_notify: id:{}, state: {:?} <- last: {:?} + action: {:?}",
86                    self.id,
87                    state,
88                    self.last.lock().unwrap(),
89                    action,
90                );
91            }
92            CalcAction::Subtract(_i) => {
93                println!(
94                    "CalcSubscriber::on_notify: id:{}, state: {:?} <- last: {:?} + action: {:?}",
95                    self.id,
96                    state,
97                    self.last.lock().unwrap(),
98                    action,
99                );
100            }
101        }
102
103        *self.last.lock().unwrap() = state.clone();
104    }
105}
106
107// now we can have a thunk before create the store
108fn get_subtract_thunk(
109    cond: Arc<Condvar>,
110    i: i32,
111) -> Box<dyn FnOnce(Box<dyn Dispatcher<CalcAction>>) + Send> {
112    Box::new(move |dispatcher| {
113        println!("thunk: working on long running task....");
114        thread::sleep(std::time::Duration::from_secs(1));
115
116        println!("thunk: dispatching action...");
117        // set done signal
118        cond.notify_all();
119        dispatcher.dispatch(CalcAction::Subtract(i)).expect("no dispatch failed");
120    })
121}
122
123pub fn main() {
124    println!("Hello, Thunk!");
125
126    // create a thunk somewhere else
127    let lock_done = Arc::new(Mutex::new(false));
128    let cond_done: Arc<Condvar> = Arc::new(Condvar::new());
129    let subtract_thunk = get_subtract_thunk(cond_done.clone(), 1);
130
131    let store =
132        StoreBuilder::new_with_reducer(CalcState::default(), Box::new(CalcReducer::default()))
133            .with_name("store-thunk".into())
134            .build()
135            .unwrap();
136
137    store.add_subscriber(Arc::new(CalcSubscriber::default()));
138    store.dispatch(CalcAction::Add(1)).expect("no dispatch failed");
139
140    // send thunk to store
141    store.dispatch_thunk(subtract_thunk);
142
143    // wait for thunk to finish
144    drop(cond_done.wait(lock_done.lock().unwrap()).unwrap());
145
146    store.stop();
147}