lazy_observer/
dirty_marker.rs

1use std::cell::{Cell, RefCell};
2use std::collections::HashSet;
3use std::hash::*;
4use std::pin::Pin;
5use std::rc::Rc;
6
7pub(crate) struct DirtyMarker {
8    dirty: Cell<bool>,
9    send: RefCell<HashSet<Pin<Rc<Self>>>>,
10    listen: RefCell<HashSet<Pin<Rc<Self>>>>,
11}
12
13impl DirtyMarker {
14    pub(crate) fn new(dirty: bool) -> Self {
15        Self {
16            dirty: Cell::new(dirty),
17            send: RefCell::new(HashSet::new()),
18            listen: RefCell::new(HashSet::new()),
19        }
20    }
21    pub(crate) fn destroy(&self) {
22        self.send.borrow_mut().clear();
23    }
24    pub(crate) fn mark_dirty(&self) {
25        if !self.dirty.replace(true) {
26            for c in self.send.borrow().iter() {
27                c.mark_dirty();
28            }
29        }
30    }
31    pub(crate) fn mark_connected_dirty(&self) {
32        for c in self.send.borrow().iter() {
33            c.mark_dirty();
34        }
35    }
36    pub(crate) fn clear_dirty(&self) -> bool {
37        self.dirty.replace(false)
38    }
39    pub(crate) fn update_listen_targets(s: &Pin<Rc<Self>>, targets: HashSet<Pin<Rc<Self>>>) {
40        let mut old = s.listen.borrow_mut();
41        let remove = old.difference(&targets);
42        for target in remove {
43            target.send.borrow_mut().remove(s);
44        }
45        let add = targets.difference(&old);
46        for target in add {
47            target.send.borrow_mut().insert(s.clone());
48        }
49        *old = targets;
50    }
51}
52
53impl PartialEq for DirtyMarker {
54    fn eq(&self, other: &Self) -> bool {
55        self as *const _ == other as *const _
56    }
57}
58
59impl Eq for DirtyMarker {}
60
61impl Hash for DirtyMarker {
62    fn hash<H: Hasher>(&self, state: &mut H) {
63        (self as *const _ as usize).hash(state);
64    }
65}