mirror of
https://github.com/rust-lang/rust.git
synced 2025-04-28 11:07:42 +00:00
Auto merge of #76929 - ssomers:btree_cleanup_2, r=Mark-Simulacrum
BTreeMap: wrap node's raw parent pointer in NonNull Now that the other `*const` (root) is gone, seemed like a small step forward. r? `@Mark-Simulacrum`
This commit is contained in:
commit
f68e08933d
@ -12,7 +12,7 @@
|
|||||||
// edges: if height > 0 {
|
// edges: if height > 0 {
|
||||||
// [Box<Node<K, V, height - 1>>; 2 * B]
|
// [Box<Node<K, V, height - 1>>; 2 * B]
|
||||||
// } else { () },
|
// } else { () },
|
||||||
// parent: *const Node<K, V, height + 1>,
|
// parent: Option<NonNull<Node<K, V, height + 1>>>,
|
||||||
// parent_idx: u16,
|
// parent_idx: u16,
|
||||||
// len: u16,
|
// len: u16,
|
||||||
// }
|
// }
|
||||||
@ -50,9 +50,8 @@ const EDGE_IDX_RIGHT_OF_CENTER: usize = B;
|
|||||||
/// The underlying representation of leaf nodes.
|
/// The underlying representation of leaf nodes.
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
struct LeafNode<K, V> {
|
struct LeafNode<K, V> {
|
||||||
/// We use `*const` as opposed to `*mut` so as to be covariant in `K` and `V`.
|
/// We want to be covariant in `K` and `V`.
|
||||||
/// This either points to an actual node or is null.
|
parent: Option<NonNull<InternalNode<K, V>>>,
|
||||||
parent: *const InternalNode<K, V>,
|
|
||||||
|
|
||||||
/// This node's index into the parent node's `edges` array.
|
/// This node's index into the parent node's `edges` array.
|
||||||
/// `*node.parent.edges[node.parent_idx]` should be the same thing as `node`.
|
/// `*node.parent.edges[node.parent_idx]` should be the same thing as `node`.
|
||||||
@ -80,7 +79,7 @@ impl<K, V> LeafNode<K, V> {
|
|||||||
// be both slightly faster and easier to track in Valgrind.
|
// be both slightly faster and easier to track in Valgrind.
|
||||||
keys: MaybeUninit::uninit_array(),
|
keys: MaybeUninit::uninit_array(),
|
||||||
vals: MaybeUninit::uninit_array(),
|
vals: MaybeUninit::uninit_array(),
|
||||||
parent: ptr::null(),
|
parent: None,
|
||||||
parent_idx: MaybeUninit::uninit(),
|
parent_idx: MaybeUninit::uninit(),
|
||||||
len: 0,
|
len: 0,
|
||||||
}
|
}
|
||||||
@ -224,7 +223,7 @@ impl<K, V> Root<K, V> {
|
|||||||
)
|
)
|
||||||
};
|
};
|
||||||
self.height -= 1;
|
self.height -= 1;
|
||||||
self.node_as_mut().as_leaf_mut().parent = ptr::null();
|
self.node_as_mut().as_leaf_mut().parent = None;
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
Global.dealloc(NonNull::from(top).cast(), Layout::new::<InternalNode<K, V>>());
|
Global.dealloc(NonNull::from(top).cast(), Layout::new::<InternalNode<K, V>>());
|
||||||
@ -309,7 +308,7 @@ impl<BorrowType, K, V, Type> NodeRef<BorrowType, K, V, Type> {
|
|||||||
pub fn len(&self) -> usize {
|
pub fn len(&self) -> usize {
|
||||||
// Crucially, we only access the `len` field here. If BorrowType is marker::ValMut,
|
// Crucially, we only access the `len` field here. If BorrowType is marker::ValMut,
|
||||||
// there might be outstanding mutable references to values that we must not invalidate.
|
// there might be outstanding mutable references to values that we must not invalidate.
|
||||||
unsafe { (*self.as_leaf_ptr()).len as usize }
|
unsafe { usize::from((*self.as_leaf_ptr()).len) }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the height of this node in the whole tree. Zero height denotes the
|
/// Returns the height of this node in the whole tree. Zero height denotes the
|
||||||
@ -365,16 +364,19 @@ impl<BorrowType, K, V, Type> NodeRef<BorrowType, K, V, Type> {
|
|||||||
) -> Result<Handle<NodeRef<BorrowType, K, V, marker::Internal>, marker::Edge>, Self> {
|
) -> Result<Handle<NodeRef<BorrowType, K, V, marker::Internal>, marker::Edge>, Self> {
|
||||||
// We need to use raw pointers to nodes because, if BorrowType is marker::ValMut,
|
// We need to use raw pointers to nodes because, if BorrowType is marker::ValMut,
|
||||||
// there might be outstanding mutable references to values that we must not invalidate.
|
// there might be outstanding mutable references to values that we must not invalidate.
|
||||||
let parent_as_leaf = unsafe { (*self.as_leaf_ptr()).parent as *const LeafNode<K, V> };
|
let leaf_ptr = self.as_leaf_ptr();
|
||||||
if let Some(non_zero) = NonNull::new(parent_as_leaf as *mut _) {
|
unsafe { (*leaf_ptr).parent }
|
||||||
Ok(Handle {
|
.as_ref()
|
||||||
node: NodeRef { height: self.height + 1, node: non_zero, _marker: PhantomData },
|
.map(|parent| Handle {
|
||||||
idx: unsafe { usize::from(*(*self.as_leaf_ptr()).parent_idx.as_ptr()) },
|
node: NodeRef {
|
||||||
|
height: self.height + 1,
|
||||||
|
node: parent.cast(),
|
||||||
|
_marker: PhantomData,
|
||||||
|
},
|
||||||
|
idx: unsafe { usize::from((*leaf_ptr).parent_idx.assume_init()) },
|
||||||
_marker: PhantomData,
|
_marker: PhantomData,
|
||||||
})
|
})
|
||||||
} else {
|
.ok_or(self)
|
||||||
Err(self)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn first_edge(self) -> Handle<Self, marker::Edge> {
|
pub fn first_edge(self) -> Handle<Self, marker::Edge> {
|
||||||
@ -572,7 +574,7 @@ impl<'a, K: 'a, V: 'a> NodeRef<marker::Mut<'a>, K, V, marker::Leaf> {
|
|||||||
/// Adds a key/value pair to the end of the node.
|
/// Adds a key/value pair to the end of the node.
|
||||||
pub fn push(&mut self, key: K, val: V) {
|
pub fn push(&mut self, key: K, val: V) {
|
||||||
let len = &mut self.as_leaf_mut().len;
|
let len = &mut self.as_leaf_mut().len;
|
||||||
let idx = *len as usize;
|
let idx = usize::from(*len);
|
||||||
assert!(idx < CAPACITY);
|
assert!(idx < CAPACITY);
|
||||||
*len += 1;
|
*len += 1;
|
||||||
unsafe {
|
unsafe {
|
||||||
@ -617,7 +619,7 @@ impl<'a, K: 'a, V: 'a> NodeRef<marker::Mut<'a>, K, V, marker::Internal> {
|
|||||||
assert!(edge.height == self.height - 1);
|
assert!(edge.height == self.height - 1);
|
||||||
|
|
||||||
let len = &mut self.as_leaf_mut().len;
|
let len = &mut self.as_leaf_mut().len;
|
||||||
let idx = *len as usize;
|
let idx = usize::from(*len);
|
||||||
assert!(idx < CAPACITY);
|
assert!(idx < CAPACITY);
|
||||||
*len += 1;
|
*len += 1;
|
||||||
unsafe {
|
unsafe {
|
||||||
@ -672,7 +674,7 @@ impl<'a, K: 'a, V: 'a> NodeRef<marker::Mut<'a>, K, V, marker::LeafOrInternal> {
|
|||||||
let edge =
|
let edge =
|
||||||
ptr::read(internal.as_internal().edges.get_unchecked(idx + 1).as_ptr());
|
ptr::read(internal.as_internal().edges.get_unchecked(idx + 1).as_ptr());
|
||||||
let mut new_root = Root { node: edge, height: internal.height - 1 };
|
let mut new_root = Root { node: edge, height: internal.height - 1 };
|
||||||
new_root.node_as_mut().as_leaf_mut().parent = ptr::null();
|
new_root.node_as_mut().as_leaf_mut().parent = None;
|
||||||
Some(new_root)
|
Some(new_root)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -704,7 +706,7 @@ impl<'a, K: 'a, V: 'a> NodeRef<marker::Mut<'a>, K, V, marker::LeafOrInternal> {
|
|||||||
);
|
);
|
||||||
|
|
||||||
let mut new_root = Root { node: edge, height: internal.height - 1 };
|
let mut new_root = Root { node: edge, height: internal.height - 1 };
|
||||||
new_root.node_as_mut().as_leaf_mut().parent = ptr::null();
|
new_root.node_as_mut().as_leaf_mut().parent = None;
|
||||||
|
|
||||||
for i in 0..old_len {
|
for i in 0..old_len {
|
||||||
Handle::new_edge(internal.reborrow_mut(), i).correct_parent_link();
|
Handle::new_edge(internal.reborrow_mut(), i).correct_parent_link();
|
||||||
@ -956,7 +958,7 @@ impl<'a, K, V> Handle<NodeRef<marker::Mut<'a>, K, V, marker::Internal>, marker::
|
|||||||
/// when the ordering of edges has been changed, such as in the various `insert` methods.
|
/// when the ordering of edges has been changed, such as in the various `insert` methods.
|
||||||
fn correct_parent_link(mut self) {
|
fn correct_parent_link(mut self) {
|
||||||
let idx = self.idx as u16;
|
let idx = self.idx as u16;
|
||||||
let ptr = self.node.as_internal_mut() as *mut _;
|
let ptr = NonNull::new(self.node.as_internal_mut());
|
||||||
let mut child = self.descend();
|
let mut child = self.descend();
|
||||||
child.as_leaf_mut().parent = ptr;
|
child.as_leaf_mut().parent = ptr;
|
||||||
child.as_leaf_mut().parent_idx.write(idx);
|
child.as_leaf_mut().parent_idx.write(idx);
|
||||||
|
Loading…
Reference in New Issue
Block a user