lazy_observer/
lib.rs

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}