once/multiindexed/
node.rs

1use std::mem::ManuallyDrop;
2
3use crate::grove::TwoEndedGrove;
4
5/// A node in the K-dimensional trie structure.
6///
7/// This is an internal implementation detail of `KdTrie`. It uses a union to represent either an
8/// inner node, which contains child nodes, or a leaf node, which contains values. This allows us to
9/// store values in contiguous memory instead of creating a separate node for each value.
10///
11/// # Node Types
12///
13/// There are two types of nodes in the trie:
14///
15/// 1. **Inner Nodes**: These nodes contain child nodes and are used for all dimensions except the
16///    last one. Each inner node is a [`TwoEndedGrove`] of other `Node` instances, allowing for
17///    efficient storage of sparse child nodes.
18///
19/// 2. **Leaf Nodes**: These nodes contain the actual values and are used for the last dimension.
20///    Each leaf node is a [`TwoEndedGrove`] of values of type `V`.
21///
22/// # Thread Safety
23///
24/// The `Node` struct is designed to be thread-safe and wait-free, allowing concurrent insertions
25/// and retrievals from multiple threads. This is achieved through the use of atomic operations in
26/// the underlying [`TwoEndedGrove`] data structure.
27///
28/// # Memory Management
29///
30/// The `Node` struct uses a Rust union to efficiently represent either an inner node or a leaf node
31/// without the overhead of an enum discriminant. This approach saves memory but requires careful
32/// manual memory management.
33///
34/// # Safety
35///
36/// It is the responsibility of the caller to know which variant is contained in the union. We only
37/// use this in `KdTrie`, where we know which variant is contained based on the number of
38/// dimensions.
39///
40/// The `inner` and `leaf` variants are wrapped in `ManuallyDrop`, because union fields can't have
41/// drop glue. Unions don't know what they contain, and so can't know which drop implementation to
42/// run. We delegate the responsibility of dropping the node to the `KdTrie`, using `drop_level`.
43pub(super) union Node<V> {
44    inner: ManuallyDrop<TwoEndedGrove<Self>>,
45    leaf: ManuallyDrop<TwoEndedGrove<V>>,
46}
47
48impl<V> Node<V> {
49    /// Creates a new inner node.
50    ///
51    /// An inner node contains child nodes and is used for all dimensions except the last one.
52    pub(super) fn new_inner() -> Self {
53        Self {
54            inner: ManuallyDrop::new(TwoEndedGrove::new()),
55        }
56    }
57
58    /// Creates a new leaf node.
59    ///
60    /// A leaf node contains values and is used for the last dimension.
61    pub(super) fn new_leaf() -> Self {
62        Self {
63            leaf: ManuallyDrop::new(TwoEndedGrove::new()),
64        }
65    }
66
67    /// Ensures that a child node exists at the specified index, creating it if necessary.
68    ///
69    /// # Parameters
70    ///
71    /// * `idx`: The index at which to ensure a child node exists
72    /// * `to_insert`: The node to insert if no child exists at the specified index
73    ///
74    /// # Returns
75    ///
76    /// A reference to the child node at the specified index
77    ///
78    /// # Safety
79    ///
80    /// Can only be called on an inner node.
81    pub(super) unsafe fn ensure_child(&self, idx: i32, to_insert: Self) -> &Self {
82        // Safety: this is an inner node by assumption
83        if let Some(child) = unsafe { self.get_child(idx) } {
84            child
85        } else {
86            let _ = unsafe { self.inner.try_insert(idx, to_insert) };
87            // Safety: either we inserted the node or another thread did. In either case, we can now
88            // unwrap the child node.
89            unsafe { self.get_child(idx).unwrap() }
90        }
91    }
92
93    /// Retrieves a reference to the child node at the specified index, if it exists.
94    ///
95    /// # Parameters
96    ///
97    /// * `idx`: The index of the child node to retrieve
98    ///
99    /// # Returns
100    ///
101    /// * `Some(&Self)` if a child node exists at the specified index
102    /// * `None` if no child node exists at the specified index
103    ///
104    /// # Safety
105    ///
106    /// Can only be called on an inner node.
107    pub(super) unsafe fn get_child(&self, idx: i32) -> Option<&Self> {
108        unsafe { self.inner.get(idx) }
109    }
110
111    /// Retrieves a mutable reference to the child node at the specified index, if it exists.
112    ///
113    /// # Parameters
114    ///
115    /// * `idx`: The index of the child node to retrieve
116    ///
117    /// # Returns
118    ///
119    /// * `Some(&mut Self)` if a child node exists at the specified index
120    /// * `None` if no child node exists at the specified index
121    ///
122    /// # Safety
123    ///
124    /// Can only be called on an inner node.
125    pub(super) unsafe fn get_child_mut(&mut self, idx: i32) -> Option<&mut Self> {
126        unsafe { self.inner.get_mut(idx) }
127    }
128
129    /// Retrieves a reference to the value at the specified index, if it exists.
130    ///
131    /// # Parameters
132    ///
133    /// * `idx`: The index of the value to retrieve
134    ///
135    /// # Returns
136    ///
137    /// * `Some(&V)` if a value exists at the specified index
138    /// * `None` if no value exists at the specified index
139    ///
140    /// # Safety
141    ///
142    /// Can only be called on a leaf node.
143    pub(super) unsafe fn get_value(&self, idx: i32) -> Option<&V> {
144        unsafe { self.leaf.get(idx) }
145    }
146
147    /// Retrieves a mutable reference to the value at the specified index, if it exists.
148    ///
149    /// # Parameters
150    ///
151    /// * `idx`: The index of the value to retrieve
152    ///
153    /// # Returns
154    ///
155    /// * `Some(&mut V)` if a value exists at the specified index
156    /// * `None` if no value exists at the specified index
157    ///
158    /// # Safety
159    ///
160    /// Can only be called on a leaf node.
161    pub(super) unsafe fn get_value_mut(&mut self, idx: i32) -> Option<&mut V> {
162        unsafe { self.leaf.get_mut(idx) }
163    }
164
165    /// Sets the value at the specified index.
166    ///
167    /// # Parameters
168    ///
169    /// * `idx`: The index at which to set the value
170    /// * `value`: The value to set
171    ///
172    /// # Safety
173    ///
174    /// Can only be called on a leaf node.
175    pub(super) unsafe fn set_value(&self, idx: i32, value: V) {
176        unsafe { self.leaf.insert(idx, value) }
177    }
178
179    /// Attempts to set the value at the specified index.
180    ///
181    /// # Parameters
182    ///
183    /// * `idx`: The index at which to set the value
184    /// * `value`: The value to set
185    ///
186    /// # Returns
187    ///
188    /// * `Ok(())` if the value was successfully set
189    /// * `Err(value)` if the index was already occupied, returning the value that we tried to
190    ///   insert
191    ///
192    /// # Safety
193    ///
194    /// Can only be called on a leaf node.
195    pub(super) unsafe fn try_set_value(&self, idx: i32, value: V) -> Result<(), V> {
196        unsafe { self.leaf.try_insert(idx, value) }
197    }
198
199    /// Returns a reference to the inner grove.
200    ///
201    /// # Safety
202    ///
203    /// Can only be called on an inner node.
204    pub(super) unsafe fn inner(&self) -> &TwoEndedGrove<Self> {
205        unsafe { &self.inner }
206    }
207
208    /// Returns a reference to the leaf grove.
209    ///
210    /// # Safety
211    ///
212    /// Can only be called on a leaf node.
213    pub(super) unsafe fn leaf(&self) -> &TwoEndedGrove<V> {
214        unsafe { &self.leaf }
215    }
216
217    /// Recursively drops the node and all its children.
218    ///
219    /// This method is called by the `Drop` implementation of `KdTrie` to ensure
220    /// proper cleanup of all allocated memory.
221    ///
222    /// # Parameters
223    ///
224    /// * `dimensions`: The total number of dimensions in the trie
225    /// * `level`: The current level in the trie (the root node has level 0)
226    pub(super) fn drop_level(&mut self, dimensions: usize, level: usize) {
227        if level == dimensions {
228            return;
229        }
230
231        if level == dimensions - 1 {
232            // This is a leaf node
233            unsafe { ManuallyDrop::drop(&mut self.leaf) };
234        } else {
235            // This is an inner node
236            unsafe {
237                for node in self.inner.values_mut() {
238                    node.drop_level(dimensions, level + 1);
239                }
240                ManuallyDrop::drop(&mut self.inner);
241            }
242        }
243    }
244}