sodium_rust/impl_/
node.rs1use std::collections::HashMap;
2use std::collections::HashSet;
3use std::fmt;
4use std::sync::Arc;
5use std::sync::RwLock;
6use std::sync::Weak;
7
8use crate::impl_::dep::Dep;
9use crate::impl_::gc_node::{GcNode, Tracer};
10use crate::impl_::sodium_ctx::SodiumCtx;
11
12pub trait IsNode: Send + Sync {
13 fn node(&self) -> &Node;
14
15 fn box_clone(&self) -> Box<dyn IsNode + Send + Sync>;
16
17 fn downgrade(&self) -> Box<dyn IsWeakNode + Send + Sync>;
18
19 fn gc_node(&self) -> &GcNode {
20 &self.node().gc_node
21 }
22
23 fn data(&self) -> &Arc<NodeData> {
24 &self.node().data
25 }
26}
27
28impl dyn IsNode {
29 pub fn add_update_dependencies(&self, update_dependencies: Vec<Dep>) {
30 let mut update_dependencies2 = self.data().update_dependencies.write().unwrap();
31 for dep in update_dependencies {
32 update_dependencies2.push(dep);
33 }
34 }
35
36 pub fn add_dependency<NODE: IsNode + Sync + Sync>(&self, dependency: NODE) {
37 {
38 let mut dependencies = self.data().dependencies.write().unwrap();
39 dependencies.push(dependency.box_clone());
40 }
41 {
42 let mut dependency_dependents = dependency.data().dependents.write().unwrap();
43 dependency_dependents.push(self.downgrade());
44 }
45 }
46
47 pub fn remove_dependency<NODE: IsNode + Sync + Sync>(&self, dependency: &NODE) {
48 {
49 let mut dependencies = self.data().dependencies.write().unwrap();
50 dependencies.retain(|n: &Box<dyn IsNode + Send + Sync>| {
51 !Arc::ptr_eq(n.data(), dependency.data())
52 });
53 }
54 {
55 let mut dependency_dependents = dependency.data().dependents.write().unwrap();
56 dependency_dependents.retain(|n: &Box<dyn IsWeakNode + Send + Sync>| {
57 if let Some(n_data) = n.data().upgrade() {
58 !Arc::ptr_eq(&n_data, self.data())
59 } else {
60 false
61 }
62 });
63 }
64 }
65
66 pub fn add_keep_alive(&self, gc_node: &GcNode) {
67 gc_node.inc_ref();
68 let mut keep_alive = self.data().keep_alive.write().unwrap();
69 keep_alive.push(gc_node.clone());
70 }
71}
72
73pub trait IsWeakNode: Send + Sync {
74 fn node(&self) -> &WeakNode;
75
76 fn box_clone(&self) -> Box<dyn IsWeakNode + Send + Sync>;
77
78 fn upgrade(&self) -> Option<Box<dyn IsNode + Send + Sync>>;
79
80 fn gc_node(&self) -> &GcNode {
81 &self.node().gc_node
82 }
83
84 fn data(&self) -> &Weak<NodeData> {
85 &self.node().data
86 }
87}
88
89pub fn box_clone_vec_is_node(
90 xs: &[Box<dyn IsNode + Send + Sync>],
91) -> Vec<Box<dyn IsNode + Send + Sync>> {
92 let mut result = Vec::with_capacity(xs.len());
93 for x in xs {
94 result.push(x.box_clone());
95 }
96 result
97}
98
99pub fn box_clone_vec_is_weak_node(
100 xs: &[Box<dyn IsWeakNode + Send + Sync>],
101) -> Vec<Box<dyn IsWeakNode + Send + Sync>> {
102 let mut result = Vec::with_capacity(xs.len());
103 for x in xs {
104 result.push(x.box_clone());
105 }
106 result
107}
108
109impl IsNode for Node {
110 fn node(&self) -> &Node {
111 self
112 }
113
114 fn box_clone(&self) -> Box<dyn IsNode + Send + Sync> {
115 Box::new(self.clone())
116 }
117
118 fn downgrade(&self) -> Box<dyn IsWeakNode + Send + Sync> {
119 Box::new(Node::downgrade2(self))
120 }
121}
122
123impl IsWeakNode for WeakNode {
124 fn node(&self) -> &WeakNode {
125 self
126 }
127
128 fn box_clone(&self) -> Box<dyn IsWeakNode + Send + Sync> {
129 Box::new(self.clone())
130 }
131
132 fn upgrade(&self) -> Option<Box<dyn IsNode + Send + Sync>> {
133 self.upgrade2()
134 .map(|x| Box::new(x) as Box<dyn IsNode + Send + Sync>)
135 }
136}
137
138pub struct Node {
139 pub data: Arc<NodeData>,
140 pub gc_node: GcNode,
141 pub sodium_ctx: SodiumCtx,
142}
143
144pub struct NodeData {
145 pub visited: RwLock<bool>,
146 pub changed: RwLock<bool>,
147 pub update: RwLock<Box<dyn FnMut() + Send + Sync>>,
148 pub update_dependencies: RwLock<Vec<Dep>>,
149 pub dependencies: RwLock<Vec<Box<dyn IsNode + Send + Sync>>>,
150 pub dependents: RwLock<Vec<Box<dyn IsWeakNode + Send + Sync>>>,
151 pub keep_alive: RwLock<Vec<GcNode>>,
152 pub cleanups: RwLock<Vec<Box<dyn FnMut() + Send + Sync>>>,
153 pub sodium_ctx: SodiumCtx,
154}
155
156#[derive(Clone)]
157pub struct WeakNode {
158 pub data: Weak<NodeData>,
159 pub gc_node: GcNode,
160 pub sodium_ctx: SodiumCtx,
161}
162
163impl Clone for Node {
164 fn clone(&self) -> Self {
165 self.sodium_ctx.inc_node_ref_count();
166 self.gc_node.inc_ref();
167 Node {
168 data: self.data.clone(),
169 gc_node: self.gc_node.clone(),
170 sodium_ctx: self.sodium_ctx.clone(),
171 }
172 }
173}
174
175impl Drop for Node {
176 fn drop(&mut self) {
177 self.sodium_ctx.dec_node_ref_count();
178 self.gc_node.dec_ref();
179 }
180}
181
182impl Drop for NodeData {
183 fn drop(&mut self) {
184 self.sodium_ctx.dec_node_count();
185 }
186}
187
188impl Node {
189 pub fn new<NAME: ToString, UPDATE: FnMut() + Send + Sync + 'static>(
190 sodium_ctx: &SodiumCtx,
191 name: NAME,
192 update: UPDATE,
193 dependencies: Vec<Box<dyn IsNode + Send + Sync>>,
194 ) -> Self {
195 let result_forward_ref: Arc<RwLock<Option<Weak<NodeData>>>> = Arc::new(RwLock::new(None));
196 let deconstructor;
197 let trace;
198 {
199 let result_forward_ref = result_forward_ref.clone();
201 deconstructor = move || {
202 let node_data;
203 {
204 let node1 = result_forward_ref.read().unwrap();
205 let node2: &Option<Weak<NodeData>> = &*node1;
206 let node3: Option<Weak<NodeData>> = node2.clone();
207 let node_data_op = node3.unwrap().upgrade();
208 if node_data_op.is_none() {
209 return;
210 }
211 node_data = node_data_op.unwrap();
212 }
213 let mut dependencies = Vec::new();
214 {
215 let mut dependencies2 = node_data.dependencies.write().unwrap();
216 std::mem::swap(&mut *dependencies2, &mut dependencies);
217 }
218 let mut dependents = Vec::new();
219 {
220 let mut dependents2 = node_data.dependents.write().unwrap();
221 std::mem::swap(&mut *dependents2, &mut dependents);
222 }
223 let mut keep_alive = Vec::new();
224 {
225 let mut keep_alive2 = node_data.keep_alive.write().unwrap();
226 std::mem::swap(&mut *keep_alive2, &mut keep_alive);
227 }
228 {
229 let mut update_dependencies = node_data.update_dependencies.write().unwrap();
230 update_dependencies.clear();
231 }
232 {
233 let mut update = node_data.update.write().unwrap();
234 *update = Box::new(|| {});
235 }
236 let mut cleanups = Vec::new();
237 {
238 let mut cleanups2 = node_data.cleanups.write().unwrap();
239 std::mem::swap(&mut *cleanups2, &mut cleanups);
240 }
241 for dependency in dependencies {
242 let mut dependency_dependents = dependency.data().dependents.write().unwrap();
243 dependency_dependents.retain(|dependent| {
244 if let Some(dependent_data) = dependent.data().upgrade() {
245 !Arc::ptr_eq(&dependent_data, &node_data)
246 } else {
247 false
248 }
249 });
250 }
251 for dependent in dependents {
252 if let Some(dependent_data) = dependent.data().upgrade() {
253 let mut dependent_dependencies =
254 dependent_data.dependencies.write().unwrap();
255 dependent_dependencies
256 .retain(|dependency| !Arc::ptr_eq(dependency.data(), &node_data));
257 }
258 }
259 for gc_node in keep_alive {
260 gc_node.dec_ref();
261 }
262 for mut cleanup in cleanups {
263 cleanup();
264 }
265 {
266 let mut node = result_forward_ref.write().unwrap();
267 *node = None;
268 }
269 };
270 }
271 {
272 let result_forward_ref = result_forward_ref.clone();
274 trace = move |tracer: &mut Tracer| {
275 let node_data_op;
276 {
277 let node1 = result_forward_ref.read().unwrap();
278 let node2: &Option<Weak<NodeData>> = &*node1;
279 let node3: Option<Weak<NodeData>> = node2.clone();
280 node_data_op = node3.unwrap().upgrade();
281 }
282 if let Some(node_data) = node_data_op {
283 {
284 let dependencies = node_data.dependencies.read().unwrap();
285 for dependency in &*dependencies {
286 tracer(dependency.gc_node());
287 }
288 }
289 {
290 let update_dependencies = node_data.update_dependencies.read().unwrap();
291 for update_dependency in &*update_dependencies {
292 tracer(update_dependency.gc_node());
293 }
294 }
295 {
296 let keep_alive = node_data.keep_alive.read().unwrap();
297 for gc_node in &*keep_alive {
298 tracer(gc_node);
299 }
300 }
301 }
302 };
303 }
304 let result = Node {
305 data: Arc::new(NodeData {
306 visited: RwLock::new(false),
307 changed: RwLock::new(false),
308 update: RwLock::new(Box::new(update)),
309 update_dependencies: RwLock::new(Vec::new()),
310 dependencies: RwLock::new(box_clone_vec_is_node(&dependencies)),
311 dependents: RwLock::new(Vec::new()),
312 keep_alive: RwLock::new(Vec::new()),
313 cleanups: RwLock::new(Vec::new()),
314 sodium_ctx: sodium_ctx.clone(),
315 }),
316 gc_node: GcNode::new(&sodium_ctx.gc_ctx(), name.to_string(), deconstructor, trace),
317 sodium_ctx: sodium_ctx.clone(),
318 };
319 {
320 let mut result_forward_ref = result_forward_ref.write().unwrap();
321 *result_forward_ref = Some(Arc::downgrade(&result.data));
322 }
323 for dependency in dependencies {
324 let mut dependency_dependents = dependency.data().dependents.write().unwrap();
325 dependency_dependents.push(result.downgrade());
326 }
327 sodium_ctx.inc_node_ref_count();
328 sodium_ctx.inc_node_count();
329 result
330 }
331
332 pub fn downgrade2(this: &Self) -> WeakNode {
333 WeakNode {
334 data: Arc::downgrade(&this.data),
335 gc_node: this.gc_node.clone(),
336 sodium_ctx: this.sodium_ctx.clone(),
337 }
338 }
339}
340
341impl WeakNode {
342 pub fn upgrade2(&self) -> Option<Node> {
343 if let Some(data) = self.data.upgrade() {
344 self.gc_node.inc_ref();
345 self.sodium_ctx.inc_node_ref_count();
346 Some(Node {
347 data,
348 gc_node: self.gc_node.clone(),
349 sodium_ctx: self.sodium_ctx.clone(),
350 })
351 } else {
352 None
353 }
354 }
355}
356
357impl fmt::Debug for dyn IsNode + Sync + Sync {
358 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
359 let mut node_to_id;
360 {
361 let mut next_id: usize = 1;
362 let mut node_id_map: HashMap<*const NodeData, usize> = HashMap::new();
363 node_to_id = move |node: &Box<dyn IsNode + Send + Sync>| {
364 let node_data: &NodeData = node.data();
365 let node_data: *const NodeData = node_data;
366 let existing_op = node_id_map.get(&node_data).copied();
367 let node_id;
368 if let Some(existing) = existing_op {
369 node_id = existing;
370 } else {
371 node_id = next_id;
372 next_id += 1;
373 node_id_map.insert(node_data, node_id);
374 }
375 format!("N{}", node_id)
376 };
377 }
378 struct Util {
379 visited: HashSet<*const NodeData>,
380 }
381 impl Util {
382 pub fn new() -> Util {
383 Util {
384 visited: HashSet::new(),
385 }
386 }
387 pub fn is_visited(&self, node: &Box<dyn IsNode + Send + Sync>) -> bool {
388 let node_data: &NodeData = node.data();
389 let node_data: *const NodeData = node_data;
390 self.visited.contains(&node_data)
391 }
392 pub fn mark_visitied(&mut self, node: &Box<dyn IsNode + Send + Sync>) {
393 let node_data: &NodeData = node.data();
394 let node_data: *const NodeData = node_data;
395 self.visited.insert(node_data);
396 }
397 }
398 let mut util = Util::new();
399 let mut stack = vec![self.box_clone()];
400 loop {
401 let node_op = stack.pop();
402 if node_op.is_none() {
403 break;
404 }
405 let node = node_op.unwrap();
406 let node = &node;
407 if util.is_visited(node) {
408 continue;
409 }
410 util.mark_visitied(node);
411 write!(f, "(Node {} (dependencies [", node_to_id(node))?;
412 let dependencies = node.data().dependencies.read().unwrap();
413 {
414 let mut first: bool = true;
415 for dependency in &*dependencies {
416 if !first {
417 write!(f, ", ")?;
418 } else {
419 first = false;
420 }
421 write!(f, "{}", node_to_id(dependency))?;
422 stack.push(dependency.box_clone());
423 }
424 }
425 write!(f, "]) (dependents [")?;
426 let dependents = node.data().dependents.read().unwrap();
427 {
428 let mut first: bool = true;
429 for dependent in &*dependents {
430 if !first {
431 write!(f, ", ")?;
432 } else {
433 first = false;
434 }
435 let dependent = dependent.upgrade();
436 if let Some(dependent2) = dependent {
437 write!(f, "{}", node_to_id(&dependent2))?;
438 }
439 }
440 }
441 writeln!(f, "])")?;
442 }
443 fmt::Result::Ok(())
444 }
445}