sodium_rust/impl_/
node.rs

1use 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            // deconstructor
200            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            // trace
273            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}