1use std::cell::RefCell;
2use std::collections::HashSet;
3use std::pin::Pin;
4use std::rc::Rc;
5
6mod observable;
7pub use observable::Observable;
8mod lazy;
9pub use lazy::Lazy;
10mod lazy_field;
11pub use lazy_field::LazyField;
12mod dirty_marker;
13use dirty_marker::DirtyMarker;
14
15thread_local! {
16 static DIRTY_REF_STACK: RefCell<Vec<HashSet<Pin<Rc<DirtyMarker>>>>> = RefCell::new(vec![]);
17}
18
19fn notify_updater(dirty: &Pin<Rc<DirtyMarker>>) {
20 DIRTY_REF_STACK.with(|stack| {
21 let mut stack = stack.borrow_mut();
22 if stack.is_empty() {
23 return;
24 }
25 let pos = stack.len() - 1;
26 let hs = &mut stack[pos];
27 hs.insert(dirty.clone());
28 })
29}
30
31fn exec_updater<T>(dirty: &Pin<Rc<DirtyMarker>>, f: &Rc<dyn Fn() -> T>) -> T {
32 DIRTY_REF_STACK.with(|stack| {
33 stack.borrow_mut().push(HashSet::new());
34 let ret = f();
35 let targets = stack.borrow_mut().pop().unwrap();
36 DirtyMarker::update_listen_targets(dirty, targets);
37 ret
38 })
39}
40
41fn exec_field_updater<S, T>(
42 dirty: &Pin<Rc<DirtyMarker>>,
43 arg: &S,
44 f: &Rc<dyn for<'r> Fn(&'r S) -> T>,
45) -> T {
46 DIRTY_REF_STACK.with(|stack| {
47 stack.borrow_mut().push(HashSet::new());
48 let ret = f(arg);
49 let targets = stack.borrow_mut().pop().unwrap();
50 DirtyMarker::update_listen_targets(dirty, targets);
51 ret
52 })
53}