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}