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}