1use std::sync::{Arc, Condvar, Mutex};
2use std::thread;
3
4use rs_store::{DispatchOp, Dispatcher, StoreImpl};
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 vec![],
42 )
43 }
44 CalcAction::Subtract(i) => {
45 println!("CalcReducer::reduce: - {}", i);
46 DispatchOp::Dispatch(
47 CalcState {
48 count: state.count - i,
49 },
50 vec![],
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
71impl 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
107fn 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 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 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 = StoreImpl::new_with(
132 CalcState::default(),
133 vec![Box::new(CalcReducer::default())],
134 "store-thunk".into(),
135 rs_store::DEFAULT_CAPACITY,
136 rs_store::BackpressurePolicy::default(),
137 vec![],
138 )
139 .unwrap();
140
141 store.add_subscriber(Arc::new(CalcSubscriber::default())).unwrap();
142 store.dispatch(CalcAction::Add(1)).expect("no dispatch failed");
143
144 store.dispatch_thunk(subtract_thunk);
146
147 drop(cond_done.wait(lock_done.lock().unwrap()).unwrap());
149
150 match store.stop() {
151 Ok(_) => println!("store stopped"),
152 Err(e) => {
153 panic!("store stop failed : {:?}", e);
154 }
155 }
156}