Skip to content

Commit eb70c82

Browse files
committed
BTreeMap: Change internal insert function to return a handle
This is a prerequisite for cursor support for `BTreeMap`.
1 parent a322848 commit eb70c82

File tree

3 files changed

+119
-37
lines changed

3 files changed

+119
-37
lines changed

library/alloc/src/collections/btree/borrow.rs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,28 @@ impl<'a, T> DormantMutRef<'a, T> {
4141
// SAFETY: our own safety conditions imply this reference is again unique.
4242
unsafe { &mut *self.ptr.as_ptr() }
4343
}
44+
45+
/// Borrows a new mutable reference from the unique borrow initially captured.
46+
///
47+
/// # Safety
48+
///
49+
/// The reborrow must have ended, i.e., the reference returned by `new` and
50+
/// all pointers and references derived from it, must not be used anymore.
51+
pub unsafe fn reborrow(&mut self) -> &'a mut T {
52+
// SAFETY: our own safety conditions imply this reference is again unique.
53+
unsafe { &mut *self.ptr.as_ptr() }
54+
}
55+
56+
/// Borrows a new shared reference from the unique borrow initially captured.
57+
///
58+
/// # Safety
59+
///
60+
/// The reborrow must have ended, i.e., the reference returned by `new` and
61+
/// all pointers and references derived from it, must not be used anymore.
62+
pub unsafe fn reborrow_shared(&self) -> &'a T {
63+
// SAFETY: our own safety conditions imply this reference is again unique.
64+
unsafe { &*self.ptr.as_ptr() }
65+
}
4466
}
4567

4668
#[cfg(test)]

library/alloc/src/collections/btree/map/entry.rs

Lines changed: 21 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -347,7 +347,7 @@ impl<'a, K: Ord, V, A: Allocator + Clone> VacantEntry<'a, K, V, A> {
347347
/// assert_eq!(map["poneyland"], 37);
348348
/// ```
349349
#[stable(feature = "rust1", since = "1.0.0")]
350-
pub fn insert(self, value: V) -> &'a mut V {
350+
pub fn insert(mut self, value: V) -> &'a mut V {
351351
let out_ptr = match self.handle {
352352
None => {
353353
// SAFETY: There is no tree yet so no reference to it exists.
@@ -358,25 +358,27 @@ impl<'a, K: Ord, V, A: Allocator + Clone> VacantEntry<'a, K, V, A> {
358358
map.length = 1;
359359
val_ptr
360360
}
361-
Some(handle) => match handle.insert_recursing(self.key, value, self.alloc.clone()) {
362-
(None, val_ptr) => {
363-
// SAFETY: We have consumed self.handle.
364-
let map = unsafe { self.dormant_map.awaken() };
365-
map.length += 1;
366-
val_ptr
367-
}
368-
(Some(ins), val_ptr) => {
369-
drop(ins.left);
370-
// SAFETY: We have consumed self.handle and dropped the
371-
// remaining reference to the tree, ins.left.
372-
let map = unsafe { self.dormant_map.awaken() };
373-
let root = map.root.as_mut().unwrap(); // same as ins.left
374-
root.push_internal_level(self.alloc).push(ins.kv.0, ins.kv.1, ins.right);
375-
map.length += 1;
376-
val_ptr
377-
}
378-
},
361+
Some(handle) => {
362+
let new_handle =
363+
handle.insert_recursing(self.key, value, self.alloc.clone(), |ins| {
364+
drop(ins.left);
365+
// SAFETY: Pushing a new root node doesn't invalidate
366+
// handles to existing nodes.
367+
let map = unsafe { self.dormant_map.reborrow() };
368+
let root = map.root.as_mut().unwrap(); // same as ins.left
369+
root.push_internal_level(self.alloc).push(ins.kv.0, ins.kv.1, ins.right)
370+
});
371+
372+
// Get the pointer to the value
373+
let val_ptr = new_handle.into_val_mut();
374+
375+
// SAFETY: We have consumed self.handle.
376+
let map = unsafe { self.dormant_map.awaken() };
377+
map.length += 1;
378+
val_ptr
379+
}
379380
};
381+
380382
// Now that we have finished growing the tree using borrowed references,
381383
// dereference the pointer to a part of it, that we picked up along the way.
382384
unsafe { &mut *out_ptr }

library/alloc/src/collections/btree/node.rs

Lines changed: 76 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -442,6 +442,24 @@ impl<'a, K, V, Type> NodeRef<marker::Mut<'a>, K, V, Type> {
442442
// SAFETY: we have exclusive access to the entire node.
443443
unsafe { &mut *ptr }
444444
}
445+
446+
/// Returns a dormant copy of this node with its lifetime erased which can
447+
/// be reawakened later.
448+
pub fn dormant(&self) -> NodeRef<marker::DormantMut, K, V, Type> {
449+
NodeRef { height: self.height, node: self.node, _marker: PhantomData }
450+
}
451+
}
452+
453+
impl<K, V, Type> NodeRef<marker::DormantMut, K, V, Type> {
454+
/// Revert to the unique borrow initially captured.
455+
///
456+
/// # Safety
457+
///
458+
/// The reborrow must have ended, i.e., the reference returned by `new` and
459+
/// all pointers and references derived from it, must not be used anymore.
460+
pub unsafe fn awaken<'a>(self) -> NodeRef<marker::Mut<'a>, K, V, Type> {
461+
NodeRef { height: self.height, node: self.node, _marker: PhantomData }
462+
}
445463
}
446464

447465
impl<K, V, Type> NodeRef<marker::Dying, K, V, Type> {
@@ -798,6 +816,25 @@ impl<'a, K, V, NodeType, HandleType> Handle<NodeRef<marker::Mut<'a>, K, V, NodeT
798816
// We can't use Handle::new_kv or Handle::new_edge because we don't know our type
799817
Handle { node: unsafe { self.node.reborrow_mut() }, idx: self.idx, _marker: PhantomData }
800818
}
819+
820+
/// Returns a dormant copy of this handle which can be reawakened later.
821+
///
822+
/// See [`DormantMutRef`] for more details.
823+
pub fn dormant(&self) -> Handle<NodeRef<marker::DormantMut, K, V, NodeType>, HandleType> {
824+
Handle { node: self.node.dormant(), idx: self.idx, _marker: PhantomData }
825+
}
826+
}
827+
828+
impl<K, V, NodeType, HandleType> Handle<NodeRef<marker::DormantMut, K, V, NodeType>, HandleType> {
829+
/// Revert to the unique borrow initially captured.
830+
///
831+
/// # Safety
832+
///
833+
/// The reborrow must have ended, i.e., the reference returned by `new` and
834+
/// all pointers and references derived from it, must not be used anymore.
835+
pub unsafe fn awaken<'a>(self) -> Handle<NodeRef<marker::Mut<'a>, K, V, NodeType>, HandleType> {
836+
Handle { node: unsafe { self.node.awaken() }, idx: self.idx, _marker: PhantomData }
837+
}
801838
}
802839

803840
impl<BorrowType, K, V, NodeType> Handle<NodeRef<BorrowType, K, V, NodeType>, marker::Edge> {
@@ -851,9 +888,11 @@ impl<'a, K: 'a, V: 'a> Handle<NodeRef<marker::Mut<'a>, K, V, marker::Leaf>, mark
851888
/// Inserts a new key-value pair between the key-value pairs to the right and left of
852889
/// this edge. This method assumes that there is enough space in the node for the new
853890
/// pair to fit.
854-
///
855-
/// The returned pointer points to the inserted value.
856-
fn insert_fit(&mut self, key: K, val: V) -> *mut V {
891+
unsafe fn insert_fit(
892+
mut self,
893+
key: K,
894+
val: V,
895+
) -> Handle<NodeRef<marker::Mut<'a>, K, V, marker::Leaf>, marker::KV> {
857896
debug_assert!(self.node.len() < CAPACITY);
858897
let new_len = self.node.len() + 1;
859898

@@ -862,7 +901,7 @@ impl<'a, K: 'a, V: 'a> Handle<NodeRef<marker::Mut<'a>, K, V, marker::Leaf>, mark
862901
slice_insert(self.node.val_area_mut(..new_len), self.idx, val);
863902
*self.node.len_mut() = new_len as u16;
864903

865-
self.node.val_area_mut(self.idx).assume_init_mut()
904+
Handle::new_kv(self.node, self.idx)
866905
}
867906
}
868907
}
@@ -871,30 +910,37 @@ impl<'a, K: 'a, V: 'a> Handle<NodeRef<marker::Mut<'a>, K, V, marker::Leaf>, mark
871910
/// Inserts a new key-value pair between the key-value pairs to the right and left of
872911
/// this edge. This method splits the node if there isn't enough room.
873912
///
874-
/// The returned pointer points to the inserted value.
913+
/// Returns a dormant handle to the inserted node which can be reawakened
914+
/// once splitting is complete.
875915
fn insert<A: Allocator + Clone>(
876-
mut self,
916+
self,
877917
key: K,
878918
val: V,
879919
alloc: A,
880-
) -> (Option<SplitResult<'a, K, V, marker::Leaf>>, *mut V) {
920+
) -> (
921+
Option<SplitResult<'a, K, V, marker::Leaf>>,
922+
Handle<NodeRef<marker::DormantMut, K, V, marker::Leaf>, marker::KV>,
923+
) {
881924
if self.node.len() < CAPACITY {
882-
let val_ptr = self.insert_fit(key, val);
883-
(None, val_ptr)
925+
// SAFETY: There is enough space in the node for insertion.
926+
let handle = unsafe { self.insert_fit(key, val) };
927+
(None, handle.dormant())
884928
} else {
885929
let (middle_kv_idx, insertion) = splitpoint(self.idx);
886930
let middle = unsafe { Handle::new_kv(self.node, middle_kv_idx) };
887931
let mut result = middle.split(alloc);
888-
let mut insertion_edge = match insertion {
932+
let insertion_edge = match insertion {
889933
LeftOrRight::Left(insert_idx) => unsafe {
890934
Handle::new_edge(result.left.reborrow_mut(), insert_idx)
891935
},
892936
LeftOrRight::Right(insert_idx) => unsafe {
893937
Handle::new_edge(result.right.borrow_mut(), insert_idx)
894938
},
895939
};
896-
let val_ptr = insertion_edge.insert_fit(key, val);
897-
(Some(result), val_ptr)
940+
// SAFETY: We just split the node, so there is enough space for
941+
// insertion.
942+
let handle = unsafe { insertion_edge.insert_fit(key, val).dormant() };
943+
(Some(result), handle)
898944
}
899945
}
900946
}
@@ -976,21 +1022,31 @@ impl<'a, K: 'a, V: 'a> Handle<NodeRef<marker::Mut<'a>, K, V, marker::Leaf>, mark
9761022
key: K,
9771023
value: V,
9781024
alloc: A,
979-
) -> (Option<SplitResult<'a, K, V, marker::LeafOrInternal>>, *mut V) {
980-
let (mut split, val_ptr) = match self.insert(key, value, alloc.clone()) {
981-
(None, val_ptr) => return (None, val_ptr),
982-
(Some(split), val_ptr) => (split.forget_node_type(), val_ptr),
1025+
split_root: impl FnOnce(SplitResult<'a, K, V, marker::LeafOrInternal>),
1026+
) -> Handle<NodeRef<marker::Mut<'a>, K, V, marker::Leaf>, marker::KV> {
1027+
let (mut split, handle) = match self.insert(key, value, alloc.clone()) {
1028+
// SAFETY: we have finished splitting and can now re-awaken the
1029+
// handle to the inserted element.
1030+
(None, handle) => return unsafe { handle.awaken() },
1031+
(Some(split), handle) => (split.forget_node_type(), handle),
9831032
};
9841033

9851034
loop {
9861035
split = match split.left.ascend() {
9871036
Ok(parent) => {
9881037
match parent.insert(split.kv.0, split.kv.1, split.right, alloc.clone()) {
989-
None => return (None, val_ptr),
1038+
// SAFETY: we have finished splitting and can now re-awaken the
1039+
// handle to the inserted element.
1040+
None => return unsafe { handle.awaken() },
9901041
Some(split) => split.forget_node_type(),
9911042
}
9921043
}
993-
Err(root) => return (Some(SplitResult { left: root, ..split }), val_ptr),
1044+
Err(root) => {
1045+
split_root(SplitResult { left: root, ..split });
1046+
// SAFETY: we have finished splitting and can now re-awaken the
1047+
// handle to the inserted element.
1048+
return unsafe { handle.awaken() };
1049+
}
9941050
};
9951051
}
9961052
}
@@ -1667,6 +1723,7 @@ pub mod marker {
16671723

16681724
pub enum Owned {}
16691725
pub enum Dying {}
1726+
pub enum DormantMut {}
16701727
pub struct Immut<'a>(PhantomData<&'a ()>);
16711728
pub struct Mut<'a>(PhantomData<&'a mut ()>);
16721729
pub struct ValMut<'a>(PhantomData<&'a mut ()>);
@@ -1688,6 +1745,7 @@ pub mod marker {
16881745
impl<'a> BorrowType for Immut<'a> {}
16891746
impl<'a> BorrowType for Mut<'a> {}
16901747
impl<'a> BorrowType for ValMut<'a> {}
1748+
impl BorrowType for DormantMut {}
16911749

16921750
pub enum KV {}
16931751
pub enum Edge {}

0 commit comments

Comments
 (0)