arena_voxel_tree/
naive_tree.rs

1use std::{
2    fmt::Display,
3    ops::Deref,
4    sync::{Arc, RwLock, Weak},
5};
6
7use smallvec::smallvec;
8
9use crate::naive_node as node;
10/// This struct is used to own a [`NodeData`] inside an [`Arc`]. The [`Arc`]
11/// can be shared, so that it can have multiple owners. It does not have
12/// getter methods for [`NodeData`]'s properties, instead it implements the
13/// `Deref` trait to allow it to be used as a [`NodeData`].
14/// * This library is inspired by [r3bl-org work](https://github.com/r3bl-org/)
15///
16/// # Shared ownership
17///
18/// After an instance of this struct is created and it's internal reference is
19/// cloned (and given to another) dropping this instance will not drop the cloned
20/// internal reference.
21///
22/// ```text
23/// VoxelTree { arc_ref: Arc<NodeData> }
24///    ▲                 ▲
25///    │                 │
26///    │      This atomic ref owns the
27///    │      `NodeData` & is shared
28///    │
29///    1. Has methods to manipulate nodes and their children.
30///
31///    2. When it is dropped, if there are other `Arc`s (shared via
32///       `get_copy_of_internal_arc()`) pointing to the same underlying
33///       `NodeData`, then the `NodeData` will not be dropped.
34///
35///    3. This struct is necessary in order for `add_child_and_update_its_parent`
36///       to work. Some pointers need to be swapped between 2 nodes for this work
37///       (and one of these pointers is a weak one). It is not possible to do this
38///       using two `NodeData` objects, without wrapping them in `Arc`s.
39/// ```
40
41pub struct VoxelTree<T: Display> {
42    arc_ref: node::NodeDataRef<T>,
43}
44
45impl<T> Deref for VoxelTree<T>
46where
47    T: Display,
48{
49    type Target = node::NodeData<T>;
50
51    fn deref(&self) -> &Self::Target {
52        &self.arc_ref
53    }
54}
55
56impl<T> VoxelTree<T>
57where
58    T: Display,
59{
60    pub fn new(value: T) -> VoxelTree<T> {
61        let new_node = node::NodeData {
62            value,
63            parent: RwLock::new(Weak::new()),
64            children: RwLock::new(smallvec![]),
65        };
66        let arc_ref = Arc::new(new_node);
67        Self { arc_ref }
68    }
69
70    pub fn get_copy_of_internal_arc(&self) -> node::NodeDataRef<T> {
71        Arc::clone(&self.arc_ref)
72    }
73
74    pub fn create_and_add_child(&self, value: T) -> node::NodeDataRef<T> {
75        let new_child = Self::new(value);
76        self.add_child_and_update_its_parent(&new_child);
77        new_child.get_copy_of_internal_arc()
78    }
79
80    /// 🔏 Write locks used.
81    pub fn add_child_and_update_its_parent(&self, child: &VoxelTree<T>) {
82        {
83            let mut my_children = self.arc_ref.children.write().unwrap();
84            my_children.push(child.get_copy_of_internal_arc());
85        } // `my_children` guard dropped.
86
87        {
88            let mut childs_parent = child.arc_ref.parent.write().unwrap();
89            *childs_parent = Arc::downgrade(&self.get_copy_of_internal_arc());
90        } // `my_parent` guard dropped.
91    }
92
93    pub fn has_parent(&self) -> bool {
94        self.get_parent().is_some()
95    }
96
97    /// 🔒 Read lock used.
98    pub fn get_parent(&self) -> Option<node::NodeDataRef<T>> {
99        let my_parent_weak = self.arc_ref.parent.read().unwrap();
100        my_parent_weak.upgrade()
101    }
102}