1use std::cell::{Cell, RefCell};
2use std::collections::{HashSet, VecDeque};
3use std::rc::Rc;
4
5use rustc_hash::{FxHashMap, FxHashSet};
6
7pub type SignalId = usize;
8pub type ObserverId = usize;
9
10thread_local! {
11 static CURRENT_OBSERVER: RefCell<Option<ObserverId>> = const { RefCell::new(None) };
12 static GRAPH: RefCell<DepGraph> = RefCell::new(DepGraph::default());
13 static SIGNAL_DEPTH: Cell<u32> = const { Cell::new(0) };
14 static PENDING_OBSERVERS: RefCell<VecDeque<ObserverId>> = const { RefCell::new(VecDeque::new()) };
15}
16
17#[derive(Default)]
18struct DepGraph {
19 next_observer: ObserverId,
20 edges: FxHashMap<SignalId, FxHashSet<ObserverId>>,
22 back: FxHashMap<ObserverId, FxHashSet<SignalId>>,
24 observers: FxHashMap<ObserverId, Rc<dyn Fn()>>,
26 running: FxHashSet<ObserverId>,
27}
28
29impl DepGraph {
30 fn remove_all_edges_for(&mut self, obs: ObserverId) {
31 if let Some(signals) = self.back.remove(&obs) {
32 for s in signals {
33 if let Some(set) = self.edges.get_mut(&s) {
34 set.remove(&obs);
35 }
36 }
37 }
38 }
39 fn remove_observer(&mut self, obs: ObserverId) {
40 self.observers.remove(&obs);
41 self.remove_all_edges_for(obs);
42 for set in self.edges.values_mut() {
44 set.remove(&obs);
45 }
46 self.running.remove(&obs);
47 }
48}
49
50pub fn register_signal_read(sig: SignalId) {
51 CURRENT_OBSERVER.with(|co| {
52 if let Some(obs) = *co.borrow() {
53 GRAPH.with(|g| {
54 let mut g = g.borrow_mut();
55 g.edges.entry(sig).or_default().insert(obs);
56 g.back.entry(obs).or_default().insert(sig);
57 });
58 }
59 });
60 crate::scope_cache::record_scope_signal_dep(sig);
62}
63
64pub fn signal_changed(sig: SignalId) {
65 crate::scope_cache::mark_scope_deps_dirty(sig);
67
68 let is_outer = SIGNAL_DEPTH.with(|depth| {
69 let prev = depth.get();
70 depth.set(prev + 1);
71 if prev > 0 {
72 GRAPH.with(|gcell| {
74 let g = gcell.borrow();
75 if let Some(obs_set) = g.edges.get(&sig) {
76 PENDING_OBSERVERS.with(|q| {
77 let mut queue = q.borrow_mut();
78 for &obs in obs_set {
79 if !g.running.contains(&obs) && !queue.contains(&obs) {
80 queue.push_back(obs);
81 }
82 }
83 });
84 }
85 });
86 false
87 } else {
88 true
89 }
90 });
91
92 if !is_outer {
93 SIGNAL_DEPTH.with(|d| d.set(d.get() - 1));
94 return;
95 }
96
97 GRAPH.with(|gcell| {
98 let mut g = gcell.borrow_mut();
99 let mut queue: VecDeque<ObserverId> = g
100 .edges
101 .get(&sig)
102 .cloned()
103 .unwrap_or_default()
104 .into_iter()
105 .collect();
106 while let Some(obs) = queue.pop_front() {
107 if g.running.contains(&obs) {
108 continue;
109 }
110 g.running.insert(obs);
111 g.remove_all_edges_for(obs);
112 let f = g.observers.get(&obs).cloned();
113 drop(g);
114 if let Some(f) = f {
115 CURRENT_OBSERVER.with(|co| {
116 let prev = *co.borrow();
117 *co.borrow_mut() = Some(obs);
118 f();
119 *co.borrow_mut() = prev;
120 });
121 }
122 g = gcell.borrow_mut();
123 g.running.remove(&obs);
124 }
125 });
126
127 SIGNAL_DEPTH.with(|depth| depth.set(0));
129 loop {
130 let obs = PENDING_OBSERVERS.with(|q| q.borrow_mut().pop_front());
131 match obs {
132 None => break,
133 Some(obs) => {
134 GRAPH.with(|gcell| {
135 let mut g = gcell.borrow_mut();
136 if g.running.contains(&obs) {
137 return;
138 }
139 g.running.insert(obs);
140 g.remove_all_edges_for(obs);
141 let f = g.observers.get(&obs).cloned();
142 drop(g);
143 if let Some(f) = f {
144 CURRENT_OBSERVER.with(|co| {
145 let prev = *co.borrow();
146 *co.borrow_mut() = Some(obs);
147 f();
148 *co.borrow_mut() = prev;
149 });
150 }
151 g = gcell.borrow_mut();
152 g.running.remove(&obs);
153 });
154 }
155 }
156 }
157}
158
159pub fn new_observer(f: impl Fn() + 'static) -> ObserverId {
160 GRAPH.with(|g| {
161 let mut g = g.borrow_mut();
162 let id = g.next_observer;
163 g.next_observer += 1;
164 g.observers.insert(id, Rc::new(f));
165 id
166 })
167}
168
169pub fn remove_observer(id: ObserverId) {
171 let _ = GRAPH.try_with(|g| {
172 let mut g = g.borrow_mut();
173 g.remove_observer(id);
174 });
175}
176
177pub fn without_observer<R>(f: impl FnOnce() -> R) -> R {
179 CURRENT_OBSERVER.with(|co| {
180 let prev = *co.borrow();
181 *co.borrow_mut() = None;
182 let result = f();
183 *co.borrow_mut() = prev;
184 result
185 })
186}
187
188pub fn run_observer_now(id: ObserverId) {
189 let f = GRAPH.with(|gcell| {
190 let mut g = gcell.borrow_mut();
191 if !g.running.insert(id) {
192 return None;
193 }
194 g.remove_all_edges_for(id);
195 let f = g.observers.get(&id).cloned();
196 drop(g);
197 if let Some(f) = f {
198 CURRENT_OBSERVER.with(|co| {
199 let prev = *co.borrow();
200 *co.borrow_mut() = Some(id);
201 f();
202 *co.borrow_mut() = prev;
203 });
204 }
205 GRAPH.with(|gcell| {
206 let mut g = gcell.borrow_mut();
207 g.running.remove(&id);
208 });
209 Some(())
210 });
211 let _ = f;
212}