|
1 | 1 | use super::map::MIN_LEN;
|
2 |
| -use super::node::{marker, ForceResult, Handle, NodeRef}; |
| 2 | +use super::node::{marker, ForceResult::*, Handle, LeftOrRight::*, NodeRef}; |
3 | 3 | use super::unwrap_unchecked;
|
4 | 4 | use core::mem;
|
5 |
| -use core::ptr; |
6 | 5 |
|
7 | 6 | impl<'a, K: 'a, V: 'a> Handle<NodeRef<marker::Mut<'a>, K, V, marker::LeafOrInternal>, marker::KV> {
|
8 |
| - /// Removes a key/value-pair from the map, and returns that pair, as well as |
9 |
| - /// the leaf edge corresponding to that former pair. |
| 7 | + /// Removes a key/value-pair from the tree, and returns that pair, as well as |
| 8 | + /// the leaf edge corresponding to that former pair. It's possible this empties |
| 9 | + /// a root node that is internal, which the caller should pop from the map |
| 10 | + /// holding the tree. The caller should also decrement the map's length. |
10 | 11 | pub fn remove_kv_tracking<F: FnOnce()>(
|
11 | 12 | self,
|
12 | 13 | handle_emptied_internal_root: F,
|
13 | 14 | ) -> ((K, V), Handle<NodeRef<marker::Mut<'a>, K, V, marker::Leaf>, marker::Edge>) {
|
14 |
| - let (old_kv, mut pos, was_internal) = match self.force() { |
15 |
| - ForceResult::Leaf(leaf) => { |
16 |
| - let (old_kv, pos) = leaf.remove(); |
17 |
| - (old_kv, pos, false) |
18 |
| - } |
19 |
| - ForceResult::Internal(mut internal) => { |
20 |
| - // Replace the location freed in the internal node with an |
21 |
| - // adjacent KV, and remove that adjacent KV from its leaf. |
22 |
| - // Always choose the adjacent KV on the left side because |
23 |
| - // it is typically faster to pop an element from the end |
24 |
| - // of the KV arrays without needing to shift other elements. |
25 |
| - |
26 |
| - let key_loc = internal.kv_mut().0 as *mut K; |
27 |
| - let val_loc = internal.kv_mut().1 as *mut V; |
28 |
| - |
29 |
| - let to_remove = internal.left_edge().descend().last_leaf_edge().left_kv().ok(); |
30 |
| - let to_remove = unsafe { unwrap_unchecked(to_remove) }; |
31 |
| - |
32 |
| - let (kv, pos) = to_remove.remove(); |
33 |
| - |
34 |
| - let old_key = unsafe { mem::replace(&mut *key_loc, kv.0) }; |
35 |
| - let old_val = unsafe { mem::replace(&mut *val_loc, kv.1) }; |
36 |
| - |
37 |
| - ((old_key, old_val), pos, true) |
38 |
| - } |
39 |
| - }; |
40 |
| - |
41 |
| - // Handle underflow |
42 |
| - let mut cur_node = unsafe { ptr::read(&pos).into_node().forget_type() }; |
43 |
| - let mut at_leaf = true; |
44 |
| - while cur_node.len() < MIN_LEN { |
45 |
| - match handle_underfull_node(cur_node) { |
46 |
| - UnderflowResult::AtRoot => break, |
47 |
| - UnderflowResult::Merged(edge, merged_with_left, offset) => { |
48 |
| - // If we merged with our right sibling then our tracked |
49 |
| - // position has not changed. However if we merged with our |
50 |
| - // left sibling then our tracked position is now dangling. |
51 |
| - if at_leaf && merged_with_left { |
52 |
| - let idx = pos.idx() + offset; |
53 |
| - let node = match unsafe { ptr::read(&edge).descend().force() } { |
54 |
| - ForceResult::Leaf(leaf) => leaf, |
55 |
| - ForceResult::Internal(_) => unreachable!(), |
56 |
| - }; |
57 |
| - pos = unsafe { Handle::new_edge(node, idx) }; |
58 |
| - } |
| 15 | + match self.force() { |
| 16 | + Leaf(node) => node.remove_leaf_kv(handle_emptied_internal_root), |
| 17 | + Internal(node) => node.remove_internal_kv(handle_emptied_internal_root), |
| 18 | + } |
| 19 | + } |
| 20 | +} |
59 | 21 |
|
60 |
| - let parent = edge.into_node(); |
61 |
| - if parent.len() == 0 { |
62 |
| - // The parent that was just emptied must be the root, |
63 |
| - // because nodes on a lower level would not have been |
64 |
| - // left with a single child. |
65 |
| - handle_emptied_internal_root(); |
66 |
| - break; |
| 22 | +impl<'a, K: 'a, V: 'a> Handle<NodeRef<marker::Mut<'a>, K, V, marker::Leaf>, marker::KV> { |
| 23 | + fn remove_leaf_kv<F: FnOnce()>( |
| 24 | + self, |
| 25 | + handle_emptied_internal_root: F, |
| 26 | + ) -> ((K, V), Handle<NodeRef<marker::Mut<'a>, K, V, marker::Leaf>, marker::Edge>) { |
| 27 | + let (old_kv, mut pos) = self.remove(); |
| 28 | + let len = pos.reborrow().into_node().len(); |
| 29 | + if len < MIN_LEN { |
| 30 | + let idx = pos.idx(); |
| 31 | + // We have to temporarily forget the child type, because there is no |
| 32 | + // distinct node type for the immediate parents of a leaf. |
| 33 | + let new_pos = match pos.into_node().forget_type().choose_parent_kv() { |
| 34 | + Ok(Left(left_parent_kv)) => { |
| 35 | + debug_assert!(left_parent_kv.right_child_len() == MIN_LEN - 1); |
| 36 | + if left_parent_kv.can_merge() { |
| 37 | + left_parent_kv.merge(Some(Right(idx))) |
67 | 38 | } else {
|
68 |
| - cur_node = parent.forget_type(); |
69 |
| - at_leaf = false; |
| 39 | + debug_assert!(left_parent_kv.left_child_len() > MIN_LEN); |
| 40 | + left_parent_kv.steal_left(idx) |
70 | 41 | }
|
71 | 42 | }
|
72 |
| - UnderflowResult::Stole(stole_from_left) => { |
73 |
| - // Adjust the tracked position if we stole from a left sibling |
74 |
| - if stole_from_left && at_leaf { |
75 |
| - // SAFETY: This is safe since we just added an element to our node. |
76 |
| - unsafe { |
77 |
| - pos.move_next_unchecked(); |
78 |
| - } |
| 43 | + Ok(Right(right_parent_kv)) => { |
| 44 | + debug_assert!(right_parent_kv.left_child_len() == MIN_LEN - 1); |
| 45 | + if right_parent_kv.can_merge() { |
| 46 | + right_parent_kv.merge(Some(Left(idx))) |
| 47 | + } else { |
| 48 | + debug_assert!(right_parent_kv.right_child_len() > MIN_LEN); |
| 49 | + right_parent_kv.steal_right(idx) |
79 | 50 | }
|
80 |
| - break; |
81 | 51 | }
|
82 |
| - } |
83 |
| - } |
| 52 | + Err(pos) => unsafe { Handle::new_edge(pos, idx) }, |
| 53 | + }; |
| 54 | + // SAFETY: `new_pos` is the leaf we started from or a sibling. |
| 55 | + pos = unsafe { new_pos.cast_to_leaf_unchecked() }; |
84 | 56 |
|
85 |
| - // If we deleted from an internal node then we need to compensate for |
86 |
| - // the earlier swap and adjust the tracked position to point to the |
87 |
| - // next element. |
88 |
| - if was_internal { |
89 |
| - pos = unsafe { unwrap_unchecked(pos.next_kv().ok()).next_leaf_edge() }; |
| 57 | + // Only if we merged, the parent (if any) has shrunk, but skipping |
| 58 | + // the following step does not pay off in benchmarks. |
| 59 | + // |
| 60 | + // SAFETY: We won't destroy or rearrange the leaf where `pos` is at |
| 61 | + // by handling its parent recursively; at worst we will destroy or |
| 62 | + // rearrange the parent through the grandparent, thus change the |
| 63 | + // leaf's parent pointer. |
| 64 | + if let Ok(parent) = unsafe { pos.reborrow_mut() }.into_node().ascend() { |
| 65 | + parent.into_node().handle_shrunk_node_recursively(handle_emptied_internal_root); |
| 66 | + } |
90 | 67 | }
|
91 |
| - |
92 | 68 | (old_kv, pos)
|
93 | 69 | }
|
94 | 70 | }
|
95 | 71 |
|
96 |
| -enum UnderflowResult<'a, K, V> { |
97 |
| - AtRoot, |
98 |
| - Merged(Handle<NodeRef<marker::Mut<'a>, K, V, marker::Internal>, marker::Edge>, bool, usize), |
99 |
| - Stole(bool), |
100 |
| -} |
| 72 | +impl<'a, K: 'a, V: 'a> Handle<NodeRef<marker::Mut<'a>, K, V, marker::Internal>, marker::KV> { |
| 73 | + fn remove_internal_kv<F: FnOnce()>( |
| 74 | + self, |
| 75 | + handle_emptied_internal_root: F, |
| 76 | + ) -> ((K, V), Handle<NodeRef<marker::Mut<'a>, K, V, marker::Leaf>, marker::Edge>) { |
| 77 | + // Remove an adjacent KV from its leaf and then put it back in place of |
| 78 | + // the element we were asked to remove. Prefer the left adjacent KV, |
| 79 | + // for the reasons listed in `choose_parent_kv`. |
| 80 | + let left_leaf_kv = self.left_edge().descend().last_leaf_edge().left_kv(); |
| 81 | + let left_leaf_kv = unsafe { unwrap_unchecked(left_leaf_kv.ok()) }; |
| 82 | + let (left_kv, left_hole) = left_leaf_kv.remove_leaf_kv(handle_emptied_internal_root); |
101 | 83 |
|
102 |
| -fn handle_underfull_node<'a, K: 'a, V: 'a>( |
103 |
| - node: NodeRef<marker::Mut<'a>, K, V, marker::LeafOrInternal>, |
104 |
| -) -> UnderflowResult<'_, K, V> { |
105 |
| - let parent = match node.ascend() { |
106 |
| - Ok(parent) => parent, |
107 |
| - Err(_) => return UnderflowResult::AtRoot, |
108 |
| - }; |
| 84 | + // The internal node may have been stolen from or merged. Go back right |
| 85 | + // to find where the original KV ended up. |
| 86 | + let mut internal = unsafe { unwrap_unchecked(left_hole.next_kv().ok()) }; |
| 87 | + let old_key = mem::replace(internal.kv_mut().0, left_kv.0); |
| 88 | + let old_val = mem::replace(internal.kv_mut().1, left_kv.1); |
| 89 | + let pos = internal.next_leaf_edge(); |
| 90 | + ((old_key, old_val), pos) |
| 91 | + } |
| 92 | +} |
109 | 93 |
|
110 |
| - // Prefer the left KV if it exists. Merging with the left side is faster, |
111 |
| - // since merging happens towards the left and `node` has fewer elements. |
112 |
| - // Stealing from the left side is faster, since we can pop from the end of |
113 |
| - // the KV arrays. |
114 |
| - let (is_left, mut handle) = match parent.left_kv() { |
115 |
| - Ok(left) => (true, left), |
116 |
| - Err(parent) => { |
117 |
| - let right = unsafe { unwrap_unchecked(parent.right_kv().ok()) }; |
118 |
| - (false, right) |
| 94 | +impl<'a, K: 'a, V: 'a> NodeRef<marker::Mut<'a>, K, V, marker::Internal> { |
| 95 | + /// Stocks up a possibly underfull internal node, recursively. |
| 96 | + /// Climbs up until it reaches an ancestor that has elements to spare or the root. |
| 97 | + fn handle_shrunk_node_recursively<F: FnOnce()>(mut self, handle_emptied_internal_root: F) { |
| 98 | + loop { |
| 99 | + self = match self.len() { |
| 100 | + 0 => { |
| 101 | + // An empty node must be the root, because length is only |
| 102 | + // reduced by one, and non-root underfull nodes are stocked up, |
| 103 | + // so non-root nodes never have fewer than MIN_LEN - 1 elements. |
| 104 | + debug_assert!(self.ascend().is_err()); |
| 105 | + handle_emptied_internal_root(); |
| 106 | + return; |
| 107 | + } |
| 108 | + 1..MIN_LEN => { |
| 109 | + if let Some(parent) = self.handle_underfull_node_locally() { |
| 110 | + parent |
| 111 | + } else { |
| 112 | + return; |
| 113 | + } |
| 114 | + } |
| 115 | + _ => return, |
| 116 | + } |
119 | 117 | }
|
120 |
| - }; |
| 118 | + } |
121 | 119 |
|
122 |
| - if handle.can_merge() { |
123 |
| - let offset = if is_left { handle.reborrow().left_edge().descend().len() + 1 } else { 0 }; |
124 |
| - UnderflowResult::Merged(handle.merge(), is_left, offset) |
125 |
| - } else { |
126 |
| - if is_left { |
127 |
| - handle.steal_left(); |
128 |
| - } else { |
129 |
| - handle.steal_right(); |
| 120 | + /// Stocks up an underfull internal node, possibly at the cost of shrinking |
| 121 | + /// its parent instead, which is then returned. |
| 122 | + fn handle_underfull_node_locally( |
| 123 | + self, |
| 124 | + ) -> Option<NodeRef<marker::Mut<'a>, K, V, marker::Internal>> { |
| 125 | + match self.forget_type().choose_parent_kv() { |
| 126 | + Ok(Left(left_parent_kv)) => { |
| 127 | + debug_assert!(left_parent_kv.right_child_len() == MIN_LEN - 1); |
| 128 | + if left_parent_kv.can_merge() { |
| 129 | + let pos = left_parent_kv.merge(None); |
| 130 | + let parent_edge = unsafe { unwrap_unchecked(pos.into_node().ascend().ok()) }; |
| 131 | + Some(parent_edge.into_node()) |
| 132 | + } else { |
| 133 | + debug_assert!(left_parent_kv.left_child_len() > MIN_LEN); |
| 134 | + left_parent_kv.steal_left(0); |
| 135 | + None |
| 136 | + } |
| 137 | + } |
| 138 | + Ok(Right(right_parent_kv)) => { |
| 139 | + debug_assert!(right_parent_kv.left_child_len() == MIN_LEN - 1); |
| 140 | + if right_parent_kv.can_merge() { |
| 141 | + let pos = right_parent_kv.merge(None); |
| 142 | + let parent_edge = unsafe { unwrap_unchecked(pos.into_node().ascend().ok()) }; |
| 143 | + Some(parent_edge.into_node()) |
| 144 | + } else { |
| 145 | + debug_assert!(right_parent_kv.right_child_len() > MIN_LEN); |
| 146 | + right_parent_kv.steal_right(0); |
| 147 | + None |
| 148 | + } |
| 149 | + } |
| 150 | + Err(_) => None, |
130 | 151 | }
|
131 |
| - UnderflowResult::Stole(is_left) |
132 | 152 | }
|
133 | 153 | }
|
0 commit comments