Skip to content

Commit 9f7b58f

Browse files
committed
Make implementation of navigation simpler, safer and faster
1 parent 4f6661a commit 9f7b58f

File tree

3 files changed

+148
-150
lines changed

3 files changed

+148
-150
lines changed

src/liballoc/collections/btree/map.rs

+4-7
Original file line numberDiff line numberDiff line change
@@ -1473,16 +1473,13 @@ impl<K, V> Drop for IntoIter<K, V> {
14731473
fn drop(&mut self) {
14741474
self.for_each(drop);
14751475
unsafe {
1476-
let leaf_node = ptr::read(&self.front).into_node();
1477-
if leaf_node.is_shared_root() {
1476+
let mut node = ptr::read(&self.front).into_node().forget_type();
1477+
if node.is_shared_root() {
14781478
return;
14791479
}
14801480

1481-
if let Some(first_parent) = leaf_node.deallocate_and_ascend() {
1482-
let mut cur_internal_node = first_parent.into_node();
1483-
while let Some(parent) = cur_internal_node.deallocate_and_ascend() {
1484-
cur_internal_node = parent.into_node()
1485-
}
1481+
while let Some(parent) = node.deallocate_and_ascend() {
1482+
node = parent.into_node().forget_type();
14861483
}
14871484
}
14881485
}

src/liballoc/collections/btree/navigate.rs

+122-123
Original file line numberDiff line numberDiff line change
@@ -3,151 +3,112 @@ use core::ptr;
33
use super::node::{marker, ForceResult::*, Handle, NodeRef};
44
use super::unwrap_unchecked;
55

6-
macro_rules! def_next {
7-
{ unsafe fn $name:ident : $next_kv:ident $next_edge:ident $initial_leaf_edge:ident } => {
8-
/// Given a leaf edge handle into an immutable tree, returns a handle to the next
9-
/// leaf edge and references to the key and value between these edges.
10-
/// Unsafe because the caller must ensure that the given leaf edge has a successor.
11-
unsafe fn $name <'a, K: 'a, V: 'a>(
12-
leaf_edge: Handle<NodeRef<marker::Immut<'a>, K, V, marker::Leaf>, marker::Edge>,
13-
) -> (Handle<NodeRef<marker::Immut<'a>, K, V, marker::Leaf>, marker::Edge>, &'a K, &'a V) {
14-
let mut cur_handle = match leaf_edge.$next_kv() {
15-
Ok(leaf_kv) => {
16-
let (k, v) = leaf_kv.into_kv();
17-
let next_leaf_edge = leaf_kv.$next_edge();
18-
return (next_leaf_edge, k, v);
19-
}
20-
Err(last_edge) => {
21-
let next_level = last_edge.into_node().ascend().ok();
22-
unwrap_unchecked(next_level)
23-
}
24-
};
25-
26-
loop {
27-
cur_handle = match cur_handle.$next_kv() {
28-
Ok(internal_kv) => {
29-
let (k, v) = internal_kv.into_kv();
30-
let next_internal_edge = internal_kv.$next_edge();
31-
let next_leaf_edge = next_internal_edge.descend().$initial_leaf_edge();
32-
return (next_leaf_edge, k, v);
33-
}
34-
Err(last_edge) => {
35-
let next_level = last_edge.into_node().ascend().ok();
36-
unwrap_unchecked(next_level)
37-
}
38-
}
6+
impl<BorrowType, K, V> Handle<NodeRef<BorrowType, K, V, marker::Leaf>, marker::Edge> {
7+
/// Given a leaf edge handle, returns [`Result::Ok`] with a handle to the neighboring KV
8+
/// on the right side, which is either in the same leaf node or in an ancestor node.
9+
/// If the leaf edge is the last one in the tree, returns [`Result::Err`] with the root node.
10+
pub fn next_kv(
11+
self,
12+
) -> Result<
13+
Handle<NodeRef<BorrowType, K, V, marker::LeafOrInternal>, marker::KV>,
14+
NodeRef<BorrowType, K, V, marker::LeafOrInternal>,
15+
> {
16+
let mut edge = self.forget_node_type();
17+
loop {
18+
edge = match edge.right_kv() {
19+
Ok(internal_kv) => return Ok(internal_kv),
20+
Err(last_edge) => match last_edge.into_node().ascend() {
21+
Ok(parent_edge) => parent_edge.forget_node_type(),
22+
Err(root) => return Err(root.forget_type()),
23+
},
3924
}
4025
}
41-
};
42-
}
43-
44-
macro_rules! def_next_mut {
45-
{ unsafe fn $name:ident : $next_kv:ident $next_edge:ident $initial_leaf_edge:ident } => {
46-
/// Given a leaf edge handle into a mutable tree, returns handles to the next
47-
/// leaf edge and to the KV between these edges.
48-
/// Unsafe for two reasons:
49-
/// - the caller must ensure that the given leaf edge has a successor;
50-
/// - both returned handles represent mutable references into the same tree
51-
/// that can easily invalidate each other, even on immutable use.
52-
unsafe fn $name <'a, K: 'a, V: 'a>(
53-
leaf_edge: Handle<NodeRef<marker::Mut<'a>, K, V, marker::Leaf>, marker::Edge>,
54-
) -> (Handle<NodeRef<marker::Mut<'a>, K, V, marker::Leaf>, marker::Edge>,
55-
Handle<NodeRef<marker::Mut<'a>, K, V, marker::LeafOrInternal>, marker::KV>) {
56-
let mut cur_handle = match leaf_edge.$next_kv() {
57-
Ok(leaf_kv) => {
58-
let next_leaf_edge = ptr::read(&leaf_kv).$next_edge();
59-
return (next_leaf_edge, leaf_kv.forget_node_type());
60-
}
61-
Err(last_edge) => {
62-
let next_level = last_edge.into_node().ascend().ok();
63-
unwrap_unchecked(next_level)
64-
}
65-
};
26+
}
6627

67-
loop {
68-
cur_handle = match cur_handle.$next_kv() {
69-
Ok(internal_kv) => {
70-
let next_internal_edge = ptr::read(&internal_kv).$next_edge();
71-
let next_leaf_edge = next_internal_edge.descend().$initial_leaf_edge();
72-
return (next_leaf_edge, internal_kv.forget_node_type());
73-
}
74-
Err(last_edge) => {
75-
let next_level = last_edge.into_node().ascend().ok();
76-
unwrap_unchecked(next_level)
77-
}
78-
}
28+
/// Given a leaf edge handle, returns [`Result::Ok`] with a handle to the neighboring KV
29+
/// on the left side, which is either in the same leaf node or in an ancestor node.
30+
/// If the leaf edge is the first one in the tree, returns [`Result::Err`] with the root node.
31+
pub fn next_back_kv(
32+
self,
33+
) -> Result<
34+
Handle<NodeRef<BorrowType, K, V, marker::LeafOrInternal>, marker::KV>,
35+
NodeRef<BorrowType, K, V, marker::LeafOrInternal>,
36+
> {
37+
let mut edge = self.forget_node_type();
38+
loop {
39+
edge = match edge.left_kv() {
40+
Ok(internal_kv) => return Ok(internal_kv),
41+
Err(last_edge) => match last_edge.into_node().ascend() {
42+
Ok(parent_edge) => parent_edge.forget_node_type(),
43+
Err(root) => return Err(root.forget_type()),
44+
},
7945
}
8046
}
81-
};
47+
}
8248
}
8349

84-
macro_rules! def_next_dealloc {
85-
{ unsafe fn $name:ident : $next_kv:ident $next_edge:ident $initial_leaf_edge:ident } => {
86-
/// Given a leaf edge handle into an owned tree, returns a handle to the next
87-
/// leaf edge and the key and value between these edges, while deallocating
88-
/// any node left behind.
50+
macro_rules! def_next_kv_uncheched_dealloc {
51+
{ unsafe fn $name:ident : $adjacent_kv:ident } => {
52+
/// Given a leaf edge handle into an owned tree, returns a handle to the next KV,
53+
/// while deallocating any node left behind.
8954
/// Unsafe for two reasons:
90-
/// - the caller must ensure that the given leaf edge has a successor;
91-
/// - the node pointed at by the given handle, and its ancestors, may be deallocated,
55+
/// - The caller must ensure that the leaf edge is not the last one in the tree.
56+
/// - The node pointed at by the given handle, and its ancestors, may be deallocated,
9257
/// while the reference to those nodes in the surviving ancestors is left dangling;
93-
/// thus using the returned handle is dangerous.
58+
/// thus using the returned handle to navigate further is dangerous.
9459
unsafe fn $name <K, V>(
9560
leaf_edge: Handle<NodeRef<marker::Owned, K, V, marker::Leaf>, marker::Edge>,
96-
) -> (Handle<NodeRef<marker::Owned, K, V, marker::Leaf>, marker::Edge>, K, V) {
97-
let mut cur_handle = match leaf_edge.$next_kv() {
98-
Ok(leaf_kv) => {
99-
let k = ptr::read(leaf_kv.reborrow().into_kv().0);
100-
let v = ptr::read(leaf_kv.reborrow().into_kv().1);
101-
let next_leaf_edge = leaf_kv.$next_edge();
102-
return (next_leaf_edge, k, v);
103-
}
104-
Err(last_edge) => {
105-
unwrap_unchecked(last_edge.into_node().deallocate_and_ascend())
106-
}
107-
};
108-
61+
) -> Handle<NodeRef<marker::Owned, K, V, marker::LeafOrInternal>, marker::KV> {
62+
let mut edge = leaf_edge.forget_node_type();
10963
loop {
110-
cur_handle = match cur_handle.$next_kv() {
111-
Ok(internal_kv) => {
112-
let k = ptr::read(internal_kv.reborrow().into_kv().0);
113-
let v = ptr::read(internal_kv.reborrow().into_kv().1);
114-
let next_internal_edge = internal_kv.$next_edge();
115-
let next_leaf_edge = next_internal_edge.descend().$initial_leaf_edge();
116-
return (next_leaf_edge, k, v);
117-
}
64+
edge = match edge.$adjacent_kv() {
65+
Ok(internal_kv) => return internal_kv,
11866
Err(last_edge) => {
119-
unwrap_unchecked(last_edge.into_node().deallocate_and_ascend())
67+
let parent_edge = last_edge.into_node().deallocate_and_ascend();
68+
unwrap_unchecked(parent_edge).forget_node_type()
12069
}
12170
}
12271
}
12372
}
12473
};
12574
}
12675

127-
def_next! {unsafe fn next_unchecked: right_kv right_edge first_leaf_edge}
128-
def_next! {unsafe fn next_back_unchecked: left_kv left_edge last_leaf_edge}
129-
def_next_mut! {unsafe fn next_unchecked_mut: right_kv right_edge first_leaf_edge}
130-
def_next_mut! {unsafe fn next_back_unchecked_mut: left_kv left_edge last_leaf_edge}
131-
def_next_dealloc! {unsafe fn next_unchecked_deallocating: right_kv right_edge first_leaf_edge}
132-
def_next_dealloc! {unsafe fn next_back_unchecked_deallocating: left_kv left_edge last_leaf_edge}
76+
def_next_kv_uncheched_dealloc! {unsafe fn next_kv_unchecked_dealloc: right_kv}
77+
def_next_kv_uncheched_dealloc! {unsafe fn next_back_kv_unchecked_dealloc: left_kv}
78+
79+
/// This replaces the value behind the `v` unique reference by calling the
80+
/// relevant function.
81+
///
82+
/// Safety: The change closure must not panic.
83+
#[inline]
84+
unsafe fn replace<T, R>(v: &mut T, change: impl FnOnce(T) -> (T, R)) -> R {
85+
let value = ptr::read(v);
86+
let (new_value, ret) = change(value);
87+
ptr::write(v, new_value);
88+
ret
89+
}
13390

13491
impl<'a, K, V> Handle<NodeRef<marker::Immut<'a>, K, V, marker::Leaf>, marker::Edge> {
13592
/// Moves the leaf edge handle to the next leaf edge and returns references to the
13693
/// key and value in between.
13794
/// Unsafe because the caller must ensure that the leaf edge is not the last one in the tree.
13895
pub unsafe fn next_unchecked(&mut self) -> (&'a K, &'a V) {
139-
let (next_edge, k, v) = next_unchecked(*self);
140-
*self = next_edge;
141-
(k, v)
96+
replace(self, |leaf_edge| {
97+
let kv = leaf_edge.next_kv();
98+
let kv = unwrap_unchecked(kv.ok());
99+
(kv.next_leaf_edge(), kv.into_kv())
100+
})
142101
}
143102

144103
/// Moves the leaf edge handle to the previous leaf edge and returns references to the
145104
/// key and value in between.
146105
/// Unsafe because the caller must ensure that the leaf edge is not the first one in the tree.
147106
pub unsafe fn next_back_unchecked(&mut self) -> (&'a K, &'a V) {
148-
let (next_edge, k, v) = next_back_unchecked(*self);
149-
*self = next_edge;
150-
(k, v)
107+
replace(self, |leaf_edge| {
108+
let kv = leaf_edge.next_back_kv();
109+
let kv = unwrap_unchecked(kv.ok());
110+
(kv.next_back_leaf_edge(), kv.into_kv())
111+
})
151112
}
152113
}
153114

@@ -158,8 +119,11 @@ impl<'a, K, V> Handle<NodeRef<marker::Mut<'a>, K, V, marker::Leaf>, marker::Edge
158119
/// - The caller must ensure that the leaf edge is not the last one in the tree.
159120
/// - Using the updated handle may well invalidate the returned references.
160121
pub unsafe fn next_unchecked(&mut self) -> (&'a mut K, &'a mut V) {
161-
let (next_edge, kv) = next_unchecked_mut(ptr::read(self));
162-
*self = next_edge;
122+
let kv = replace(self, |leaf_edge| {
123+
let kv = leaf_edge.next_kv();
124+
let kv = unwrap_unchecked(kv.ok());
125+
(ptr::read(&kv).next_leaf_edge(), kv)
126+
});
163127
// Doing the descend (and perhaps another move) invalidates the references
164128
// returned by `into_kv_mut`, so we have to do this last.
165129
kv.into_kv_mut()
@@ -171,8 +135,11 @@ impl<'a, K, V> Handle<NodeRef<marker::Mut<'a>, K, V, marker::Leaf>, marker::Edge
171135
/// - The caller must ensure that the leaf edge is not the first one in the tree.
172136
/// - Using the updated handle may well invalidate the returned references.
173137
pub unsafe fn next_back_unchecked(&mut self) -> (&'a mut K, &'a mut V) {
174-
let (next_edge, kv) = next_back_unchecked_mut(ptr::read(self));
175-
*self = next_edge;
138+
let kv = replace(self, |leaf_edge| {
139+
let kv = leaf_edge.next_back_kv();
140+
let kv = unwrap_unchecked(kv.ok());
141+
(ptr::read(&kv).next_back_leaf_edge(), kv)
142+
});
176143
// Doing the descend (and perhaps another move) invalidates the references
177144
// returned by `into_kv_mut`, so we have to do this last.
178145
kv.into_kv_mut()
@@ -192,9 +159,12 @@ impl<K, V> Handle<NodeRef<marker::Owned, K, V, marker::Leaf>, marker::Edge> {
192159
/// if the two preconditions above hold.
193160
/// - Using the updated handle may well invalidate the returned references.
194161
pub unsafe fn next_unchecked(&mut self) -> (K, V) {
195-
let (next_edge, k, v) = next_unchecked_deallocating(ptr::read(self));
196-
*self = next_edge;
197-
(k, v)
162+
replace(self, |leaf_edge| {
163+
let kv = next_kv_unchecked_dealloc(leaf_edge);
164+
let k = ptr::read(kv.reborrow().into_kv().0);
165+
let v = ptr::read(kv.reborrow().into_kv().1);
166+
(kv.next_leaf_edge(), (k, v))
167+
})
198168
}
199169

200170
/// Moves the leaf edge handle to the previous leaf edge and returns the key
@@ -209,9 +179,12 @@ impl<K, V> Handle<NodeRef<marker::Owned, K, V, marker::Leaf>, marker::Edge> {
209179
/// if the two preconditions above hold.
210180
/// - Using the updated handle may well invalidate the returned references.
211181
pub unsafe fn next_back_unchecked(&mut self) -> (K, V) {
212-
let (next_edge, k, v) = next_back_unchecked_deallocating(ptr::read(self));
213-
*self = next_edge;
214-
(k, v)
182+
replace(self, |leaf_edge| {
183+
let kv = next_back_kv_unchecked_dealloc(leaf_edge);
184+
let k = ptr::read(kv.reborrow().into_kv().0);
185+
let v = ptr::read(kv.reborrow().into_kv().1);
186+
(kv.next_back_leaf_edge(), (k, v))
187+
})
215188
}
216189
}
217190

@@ -242,3 +215,29 @@ impl<BorrowType, K, V> NodeRef<BorrowType, K, V, marker::LeafOrInternal> {
242215
}
243216
}
244217
}
218+
219+
impl<BorrowType, K, V> Handle<NodeRef<BorrowType, K, V, marker::LeafOrInternal>, marker::KV> {
220+
/// Returns the leaf edge closest to a KV for forward navigation.
221+
pub fn next_leaf_edge(self) -> Handle<NodeRef<BorrowType, K, V, marker::Leaf>, marker::Edge> {
222+
match self.force() {
223+
Leaf(leaf_kv) => leaf_kv.right_edge(),
224+
Internal(internal_kv) => {
225+
let next_internal_edge = internal_kv.right_edge();
226+
next_internal_edge.descend().first_leaf_edge()
227+
}
228+
}
229+
}
230+
231+
/// Returns the leaf edge closest to a KV for backward navigation.
232+
pub fn next_back_leaf_edge(
233+
self,
234+
) -> Handle<NodeRef<BorrowType, K, V, marker::Leaf>, marker::Edge> {
235+
match self.force() {
236+
Leaf(leaf_kv) => leaf_kv.left_edge(),
237+
Internal(internal_kv) => {
238+
let next_internal_edge = internal_kv.left_edge();
239+
next_internal_edge.descend().last_leaf_edge()
240+
}
241+
}
242+
}
243+
}

0 commit comments

Comments
 (0)