refactor(tree): simplify node structure and improve memory handling
- Replaced `InternalNode` with a unified `LeafNode` structure to simplify the node hierarchy and reduce redundancy. - Introduced `capacity` field in `LeafNode` to dynamically manage keys and edges, replacing fixed-size arrays. - Added methods for growing node capacity and handling dynamic memory allocation for keys and edges. - Updated `NodeRef` methods to work with the new `LeafNode` structure, including safe handling of raw pointers and memory operations. - Adjusted tests to reflect the new node structure and ensure correctness.
This commit is contained in:
parent
affa52ba73
commit
b11805aacd
|
|
@ -5,7 +5,8 @@
|
||||||
strict_provenance_atomic_ptr,
|
strict_provenance_atomic_ptr,
|
||||||
box_vec_non_null,
|
box_vec_non_null,
|
||||||
maybe_uninit_slice,
|
maybe_uninit_slice,
|
||||||
debug_closure_helpers
|
debug_closure_helpers,
|
||||||
|
slice_ptr_get,
|
||||||
)
|
)
|
||||||
)]
|
)]
|
||||||
#![cfg_attr(feature = "transposed-option", feature(try_trait_v2))]
|
#![cfg_attr(feature = "transposed-option", feature(try_trait_v2))]
|
||||||
|
|
|
||||||
373
src/tree.rs
373
src/tree.rs
|
|
@ -68,20 +68,13 @@ const CAPACITY: usize = 16;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct LeafNode<K, V> {
|
struct LeafNode<K, V> {
|
||||||
parent: Option<NonNull<InternalNode<K, V>>>,
|
parent: Option<BoxedNode<K, V>>,
|
||||||
parent_idx: MaybeUninit<u16>,
|
parent_idx: MaybeUninit<u16>,
|
||||||
value: Option<V>,
|
value: Option<V>,
|
||||||
leaf: bool,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
#[repr(C)]
|
|
||||||
struct InternalNode<K, V> {
|
|
||||||
data: LeafNode<K, V>,
|
|
||||||
next: Option<NonNull<InternalNode<K, V>>>,
|
|
||||||
len: u16,
|
len: u16,
|
||||||
keys: [MaybeUninit<K>; CAPACITY],
|
capacity: u16,
|
||||||
edges: [MaybeUninit<BoxedNode<K, V>>; CAPACITY],
|
keys: NonNull<MaybeUninit<K>>,
|
||||||
|
edges: NonNull<MaybeUninit<BoxedNode<K, V>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
type BoxedNode<K, V> = NonNull<LeafNode<K, V>>;
|
type BoxedNode<K, V> = NonNull<LeafNode<K, V>>;
|
||||||
|
|
@ -137,9 +130,13 @@ impl<K, V> LeafNode<K, V> {
|
||||||
unsafe fn init(this: *mut Self) {
|
unsafe fn init(this: *mut Self) {
|
||||||
unsafe {
|
unsafe {
|
||||||
(&raw mut (*this).parent).write(None);
|
(&raw mut (*this).parent).write(None);
|
||||||
(&raw mut (*this).leaf).write(true);
|
|
||||||
(&raw mut (*this).value).write(None);
|
|
||||||
// parent_idx may be left uninitialized
|
// parent_idx may be left uninitialized
|
||||||
|
(&raw mut (*this).value).write(None);
|
||||||
|
(&raw mut (*this).len).write(0);
|
||||||
|
(&raw mut (*this).capacity).write(0);
|
||||||
|
// keys and edges are dangling pointers
|
||||||
|
(&raw mut (*this).keys).write(NonNull::dangling());
|
||||||
|
(&raw mut (*this).edges).write(NonNull::dangling());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -152,44 +149,6 @@ impl<K, V> LeafNode<K, V> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<K, V> InternalNode<K, V> {
|
|
||||||
unsafe fn init(this: *mut Self) {
|
|
||||||
unsafe {
|
|
||||||
LeafNode::init(&raw mut (*this).data);
|
|
||||||
(&raw mut (*this).data.leaf).write(false);
|
|
||||||
(&raw mut (*this).next).write(None);
|
|
||||||
(&raw mut (*this).len).write(0);
|
|
||||||
// keys and edges may be left uninitialized
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn init_with_leaf(this: *mut Self, leaf: Box<LeafNode<K, V>>) {
|
|
||||||
let mut uninit: Box<MaybeUninit<LeafNode<K, V>>> = unsafe { core::mem::transmute(leaf) };
|
|
||||||
unsafe {
|
|
||||||
core::mem::swap(uninit.assume_init_mut(), &mut (*this).data);
|
|
||||||
(&raw mut (*this).data.leaf).write(false);
|
|
||||||
(&raw mut (*this).next).write(None);
|
|
||||||
(&raw mut (*this).len).write(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn new_with_leaf(leaf: Box<LeafNode<K, V>>) -> Box<Self> {
|
|
||||||
let mut this = Box::<Self>::new_uninit();
|
|
||||||
unsafe {
|
|
||||||
Self::init_with_leaf(this.as_mut_ptr(), leaf);
|
|
||||||
this.assume_init()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn new() -> Box<Self> {
|
|
||||||
let mut this = Box::<Self>::new_uninit();
|
|
||||||
unsafe {
|
|
||||||
Self::init(this.as_mut_ptr());
|
|
||||||
this.assume_init()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<K, V> NodeRef<marker::Owned, K, V, marker::Leaf> {
|
impl<K, V> NodeRef<marker::Owned, K, V, marker::Leaf> {
|
||||||
fn new_leaf() -> Self {
|
fn new_leaf() -> Self {
|
||||||
let node = LeafNode::new();
|
let node = LeafNode::new();
|
||||||
|
|
@ -200,33 +159,15 @@ impl<K, V> NodeRef<marker::Owned, K, V, marker::Leaf> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<K, V> NodeRef<marker::Owned, K, V, marker::Internal> {
|
impl<BorrowType, K, V> NodeRef<BorrowType, K, V, marker::Internal> {
|
||||||
fn new_internal() -> Self {
|
/// Unpack a node reference that was packed as `NodeRef::parent`.
|
||||||
let node = InternalNode::new();
|
fn new_internal(node: BoxedNode<K, V>) -> Self {
|
||||||
unsafe { NodeRef::from_new_internal(node) }
|
let node = NodeRef {
|
||||||
}
|
|
||||||
|
|
||||||
/// # Safety
|
|
||||||
/// `height` must not be zero.
|
|
||||||
unsafe fn from_new_internal(internal: Box<InternalNode<K, V>>) -> Self {
|
|
||||||
let node = NonNull::from(Box::leak(internal)).cast();
|
|
||||||
let mut this = NodeRef {
|
|
||||||
node,
|
node,
|
||||||
_marker: PhantomData,
|
_marker: PhantomData,
|
||||||
};
|
};
|
||||||
this
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<BorrowType, K, V> NodeRef<BorrowType, K, V, marker::Internal> {
|
// debug_assert!(!node.is_leaf());
|
||||||
/// Unpack a node reference that was packed as `NodeRef::parent`.
|
|
||||||
fn from_internal(node: NonNull<InternalNode<K, V>>) -> Self {
|
|
||||||
let node = NodeRef {
|
|
||||||
node: node.cast(),
|
|
||||||
_marker: PhantomData,
|
|
||||||
};
|
|
||||||
|
|
||||||
debug_assert!(!node.is_leaf());
|
|
||||||
|
|
||||||
node
|
node
|
||||||
}
|
}
|
||||||
|
|
@ -251,11 +192,13 @@ impl<BorrowType: marker::BorrowType, K, V, Type> NodeRef<BorrowType, K, V, Type>
|
||||||
|
|
||||||
// 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 leaf_ptr: *const _ = Self::as_leaf_ptr(&self);
|
let leaf_ptr = Self::as_leaf_ptr(&self).cast_const();
|
||||||
unsafe { (*leaf_ptr).parent }
|
unsafe { (*leaf_ptr).parent }
|
||||||
.as_ref()
|
|
||||||
.map(|parent| Handle {
|
.map(|parent| Handle {
|
||||||
node: NodeRef::from_internal(*parent),
|
node: NodeRef {
|
||||||
|
node: parent,
|
||||||
|
_marker: PhantomData,
|
||||||
|
},
|
||||||
idx: unsafe { usize::from((*leaf_ptr).parent_idx.assume_init()) },
|
idx: unsafe { usize::from((*leaf_ptr).parent_idx.assume_init()) },
|
||||||
_marker: PhantomData,
|
_marker: PhantomData,
|
||||||
})
|
})
|
||||||
|
|
@ -295,12 +238,9 @@ impl<BorrowType: marker::BorrowType, K, V>
|
||||||
// node pointer is dereferenced, we access the edges array with a
|
// node pointer is dereferenced, we access the edges array with a
|
||||||
// reference (Rust issue #73987) and invalidate any other references
|
// reference (Rust issue #73987) and invalidate any other references
|
||||||
// to or inside the array, should any be around.
|
// to or inside the array, should any be around.
|
||||||
let parent_ptr = NodeRef::as_internal_ptr(&self.node);
|
|
||||||
let node = unsafe {
|
let node = unsafe {
|
||||||
(*parent_ptr)
|
// in this case, no references to the node are created.
|
||||||
.edges
|
self.node.edge_area(self.idx).assume_init_read()
|
||||||
.get_unchecked(self.idx)
|
|
||||||
.assume_init_read()
|
|
||||||
};
|
};
|
||||||
NodeRef {
|
NodeRef {
|
||||||
node,
|
node,
|
||||||
|
|
@ -340,39 +280,14 @@ impl<'a, K, V, NodeType, HandleType> Handle<NodeRef<marker::Mut<'a>, K, V, NodeT
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<BorrowType, K, V> NodeRef<BorrowType, K, V, marker::Internal> {
|
impl<'a, K, V, NodeType> NodeRef<marker::Mut<'a>, K, V, NodeType> {
|
||||||
/// Exposes the data of an internal node.
|
|
||||||
///
|
|
||||||
/// Returns a raw ptr to avoid invalidating other references to this node.
|
|
||||||
fn as_internal_ptr(this: &Self) -> *mut InternalNode<K, V> {
|
|
||||||
// SAFETY: the static node type is `Internal`.
|
|
||||||
this.node.as_ptr() as *mut InternalNode<K, V>
|
|
||||||
}
|
|
||||||
|
|
||||||
fn as_internal_non_null(this: &Self) -> NonNull<InternalNode<K, V>> {
|
|
||||||
// SAFETY: the static node type is `Internal`.
|
|
||||||
unsafe { NonNull::new_unchecked(Self::as_internal_ptr(this)) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a, K, V> NodeRef<marker::Mut<'a>, K, V, marker::Internal> {
|
|
||||||
/// Borrows exclusive access to the data of an internal node.
|
|
||||||
fn as_internal_mut(&mut self) -> &mut InternalNode<K, V> {
|
|
||||||
let ptr = Self::as_internal_ptr(self);
|
|
||||||
unsafe { &mut *ptr }
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(super) fn len_mut(&mut self) -> &mut u16 {
|
pub(super) fn len_mut(&mut self) -> &mut u16 {
|
||||||
// SAFETY: we have exclusive access to the entire node.
|
// SAFETY: we have exclusive access to the entire node.
|
||||||
unsafe { &mut (*Self::as_internal_ptr(self)).len }
|
unsafe { &mut (*Self::as_leaf_ptr(self)).len }
|
||||||
}
|
}
|
||||||
|
pub(super) fn capacity_mut(&mut self) -> &mut u16 {
|
||||||
pub(super) fn next_mut(&mut self) -> Option<NodeRef<marker::Mut<'a>, K, V, marker::Internal>> {
|
// SAFETY: we have exclusive access to the entire node.
|
||||||
let internal = self.as_internal_mut();
|
unsafe { &mut (*Self::as_leaf_ptr(self)).len }
|
||||||
internal.next.map(|next| NodeRef {
|
|
||||||
node: next.cast(),
|
|
||||||
_marker: PhantomData,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -447,7 +362,45 @@ impl<'a, K, V, Type> NodeRef<marker::Mut<'a>, K, V, Type> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, K: 'a, V: 'a> NodeRef<marker::Mut<'a>, K, V, marker::Internal> {
|
impl<'a, K: 'a, V: 'a, BorrowType> NodeRef<BorrowType, K, V, marker::Internal> {
|
||||||
|
/// Borrows shared access to an element of the key storage area.
|
||||||
|
///
|
||||||
|
/// # Safety
|
||||||
|
/// `index` is in bounds of 0..CAPACITY
|
||||||
|
unsafe fn key_area<I, Output: ?Sized>(&self, index: I) -> &Output
|
||||||
|
where
|
||||||
|
I: core::slice::SliceIndex<[MaybeUninit<K>], Output = Output>,
|
||||||
|
{
|
||||||
|
// SAFETY: the caller will not be able to call further methods on self
|
||||||
|
// until the key slice reference is dropped, as we have unique access
|
||||||
|
// for the lifetime of the borrow.
|
||||||
|
unsafe {
|
||||||
|
let keys = (*self.node.as_ptr()).keys;
|
||||||
|
let capacity = (*self.node.as_ptr()).capacity as usize;
|
||||||
|
core::slice::from_raw_parts(keys.as_ptr(), capacity).get_unchecked(index)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Borrows shared access to an element or slice of the node's value storage area.
|
||||||
|
///
|
||||||
|
/// # Safety
|
||||||
|
/// `index` is in bounds of 0..node.capacity
|
||||||
|
unsafe fn edge_area<I, Output: ?Sized>(&self, index: I) -> &Output
|
||||||
|
where
|
||||||
|
I: core::slice::SliceIndex<[MaybeUninit<BoxedNode<K, V>>], Output = Output>,
|
||||||
|
{
|
||||||
|
// SAFETY: the caller will not be able to call further methods on self
|
||||||
|
// until the value slice reference is dropped, as we have unique access
|
||||||
|
// for the lifetime of the borrow.
|
||||||
|
unsafe {
|
||||||
|
let edges = (*self.node.as_ptr()).edges;
|
||||||
|
let capacity = (*self.node.as_ptr()).capacity as usize;
|
||||||
|
core::slice::from_raw_parts(edges.as_ptr(), capacity).get_unchecked(index)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, K: 'a, V: 'a, NodeType> NodeRef<marker::Mut<'a>, K, V, NodeType> {
|
||||||
/// Borrows exclusive access to an element of the key storage area.
|
/// Borrows exclusive access to an element of the key storage area.
|
||||||
///
|
///
|
||||||
/// # Safety
|
/// # Safety
|
||||||
|
|
@ -460,9 +413,8 @@ impl<'a, K: 'a, V: 'a> NodeRef<marker::Mut<'a>, K, V, marker::Internal> {
|
||||||
// until the key slice reference is dropped, as we have unique access
|
// until the key slice reference is dropped, as we have unique access
|
||||||
// for the lifetime of the borrow.
|
// for the lifetime of the borrow.
|
||||||
unsafe {
|
unsafe {
|
||||||
self.as_internal_mut()
|
let leaf = self.as_leaf_mut();
|
||||||
.keys
|
core::slice::from_raw_parts_mut(leaf.keys.as_ptr(), leaf.capacity as usize)
|
||||||
.as_mut_slice()
|
|
||||||
.get_unchecked_mut(index)
|
.get_unchecked_mut(index)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -470,7 +422,7 @@ impl<'a, K: 'a, V: 'a> NodeRef<marker::Mut<'a>, K, V, marker::Internal> {
|
||||||
/// Borrows exclusive access to an element or slice of the node's value storage area.
|
/// Borrows exclusive access to an element or slice of the node's value storage area.
|
||||||
///
|
///
|
||||||
/// # Safety
|
/// # Safety
|
||||||
/// `index` is in bounds of 0..CAPACITY
|
/// `index` is in bounds of 0..node.capacity
|
||||||
unsafe fn edge_area_mut<I, Output: ?Sized>(&mut self, index: I) -> &mut Output
|
unsafe fn edge_area_mut<I, Output: ?Sized>(&mut self, index: I) -> &mut Output
|
||||||
where
|
where
|
||||||
I: core::slice::SliceIndex<[MaybeUninit<BoxedNode<K, V>>], Output = Output>,
|
I: core::slice::SliceIndex<[MaybeUninit<BoxedNode<K, V>>], Output = Output>,
|
||||||
|
|
@ -479,9 +431,8 @@ impl<'a, K: 'a, V: 'a> NodeRef<marker::Mut<'a>, K, V, marker::Internal> {
|
||||||
// until the value slice reference is dropped, as we have unique access
|
// until the value slice reference is dropped, as we have unique access
|
||||||
// for the lifetime of the borrow.
|
// for the lifetime of the borrow.
|
||||||
unsafe {
|
unsafe {
|
||||||
self.as_internal_mut()
|
let leaf = self.as_leaf_mut();
|
||||||
.edges
|
core::slice::from_raw_parts_mut(leaf.edges.as_ptr(), leaf.capacity as usize)
|
||||||
.as_mut_slice()
|
|
||||||
.get_unchecked_mut(index)
|
.get_unchecked_mut(index)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -520,7 +471,7 @@ impl<K, V, NodeType, HandleType> Handle<NodeRef<marker::DormantMut, K, V, NodeTy
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<BorrowType, K, V> NodeRef<BorrowType, K, V, marker::Internal> {
|
impl<BorrowType, K, V, NodeType> NodeRef<BorrowType, K, V, NodeType> {
|
||||||
/// Finds the length of the node. This is the number of keys or values.
|
/// Finds the length of the node. This is the number of keys or values.
|
||||||
/// The number of edges is `len() + 1`.
|
/// The number of edges is `len() + 1`.
|
||||||
/// Note that, despite being safe, calling this function can have the side effect
|
/// Note that, despite being safe, calling this function can have the side effect
|
||||||
|
|
@ -528,13 +479,17 @@ impl<BorrowType, K, V> NodeRef<BorrowType, K, V, marker::Internal> {
|
||||||
pub(super) fn len(&self) -> usize {
|
pub(super) 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 { usize::from((*Self::as_internal_ptr(self)).len) }
|
unsafe { usize::from((*Self::as_leaf_ptr(self)).len) }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(super) fn capacity(&self) -> usize {
|
||||||
|
unsafe { usize::from((*Self::as_leaf_ptr(self)).len) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<BorrowType, K, V, Type> NodeRef<BorrowType, K, V, Type> {
|
impl<BorrowType, K, V, Type> NodeRef<BorrowType, K, V, Type> {
|
||||||
pub(super) fn is_leaf(&self) -> bool {
|
pub(super) fn is_leaf(&self) -> bool {
|
||||||
unsafe { (*Self::as_leaf_ptr(self)).leaf }
|
unsafe { (*Self::as_leaf_ptr(self)).len == 0 }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Temporarily takes out another, immutable reference to the same node.
|
/// Temporarily takes out another, immutable reference to the same node.
|
||||||
|
|
@ -555,6 +510,11 @@ impl<BorrowType, K, V, Type> NodeRef<BorrowType, K, V, Type> {
|
||||||
this.node.as_ptr()
|
this.node.as_ptr()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn as_leaf(&self) -> &LeafNode<K, V> {
|
||||||
|
// SAFETY: the static node type is `Leaf`.
|
||||||
|
unsafe { &*Self::as_leaf_ptr(self) }
|
||||||
|
}
|
||||||
|
|
||||||
fn as_leaf_non_null(this: &Self) -> NonNull<LeafNode<K, V>> {
|
fn as_leaf_non_null(this: &Self) -> NonNull<LeafNode<K, V>> {
|
||||||
// SAFETY: the static node type is `Leaf`.
|
// SAFETY: the static node type is `Leaf`.
|
||||||
unsafe { NonNull::new_unchecked(Self::as_leaf_ptr(this)) }
|
unsafe { NonNull::new_unchecked(Self::as_leaf_ptr(this)) }
|
||||||
|
|
@ -562,38 +522,13 @@ impl<BorrowType, K, V, Type> NodeRef<BorrowType, K, V, Type> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, K: 'a, V: 'a> NodeRef<marker::Immut<'a>, K, V, marker::Internal> {
|
impl<'a, K: 'a, V: 'a> NodeRef<marker::Immut<'a>, K, V, marker::Internal> {
|
||||||
fn into_internal(self) -> &'a InternalNode<K, V> {
|
|
||||||
// SAFETY: the static node type is `Internal`.
|
|
||||||
unsafe { &*Self::as_internal_ptr(&self) }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Borrows a view into the keys stored in the node.
|
/// Borrows a view into the keys stored in the node.
|
||||||
pub(super) fn keys(&self) -> &[K] {
|
pub(super) fn keys(&self) -> &[K] {
|
||||||
let internal = self.into_internal();
|
unsafe { self.key_area(..self.len()).assume_init_ref() }
|
||||||
unsafe {
|
|
||||||
internal
|
|
||||||
.keys
|
|
||||||
.get_unchecked(..usize::from(internal.len))
|
|
||||||
.assume_init_ref()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn edges(&self) -> &[BoxedNode<K, V>] {
|
pub(super) fn edges(&self) -> &[BoxedNode<K, V>] {
|
||||||
let internal = self.into_internal();
|
unsafe { self.edge_area(..self.len()).assume_init_ref() }
|
||||||
unsafe {
|
|
||||||
internal
|
|
||||||
.edges
|
|
||||||
.get_unchecked(..usize::from(internal.len + 1))
|
|
||||||
.assume_init_ref()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(super) fn next(&self) -> Option<NodeRef<marker::Immut<'a>, K, V, marker::Internal>> {
|
|
||||||
let internal = self.into_internal();
|
|
||||||
internal.next.map(|next| NodeRef {
|
|
||||||
node: next.cast(),
|
|
||||||
_marker: PhantomData,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -746,43 +681,73 @@ impl<BorrowType, K, V, Type> NodeRef<BorrowType, K, V, Type> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, K, V> NodeRef<marker::Mut<'a>, K, V, marker::Leaf> {
|
impl<'a, K, V, Type> NodeRef<marker::Mut<'a>, K, V, Type> {
|
||||||
/// node must have parent/ be a leaf node.
|
pub(super) fn grow_node(&mut self) {
|
||||||
pub(super) unsafe fn make_internal_node(
|
// grow the node
|
||||||
self,
|
let Some(new_capacity) = self.capacity_mut().checked_mul(2) else {
|
||||||
) -> NodeRef<marker::Mut<'a>, K, V, marker::Internal> {
|
panic!("Node capacity overflow");
|
||||||
let leaf = self.node;
|
|
||||||
|
|
||||||
let mut parent = self.ascend().ok().unwrap();
|
|
||||||
|
|
||||||
let mut internal = unsafe {
|
|
||||||
NodeRef::from_new_internal(InternalNode::new_with_leaf(Box::from_non_null(leaf)))
|
|
||||||
};
|
};
|
||||||
|
|
||||||
parent.node.as_internal_mut().edges[parent.idx].write(NodeRef::as_leaf_non_null(&internal));
|
// Ensure the new capacity is at least 16.
|
||||||
|
// capacity starts off at 0, so the first time it will grow to 16.
|
||||||
|
let new_capacity = new_capacity.max(16) as usize;
|
||||||
|
|
||||||
unsafe { internal.borrow_mut().dormant().awaken() }
|
// Allocate new keys and edges.
|
||||||
|
let new_keys = Box::into_non_null(Box::new_uninit_slice(new_capacity));
|
||||||
|
let new_edges = Box::into_non_null(Box::new_uninit_slice(new_capacity));
|
||||||
|
|
||||||
|
let leaf = self.as_leaf_mut();
|
||||||
|
|
||||||
|
let old_keys = core::mem::replace(&mut leaf.keys, new_keys.as_non_null_ptr());
|
||||||
|
let old_edges = core::mem::replace(&mut leaf.edges, new_edges.as_non_null_ptr());
|
||||||
|
|
||||||
|
// we don't want to copy and deallocate the old keys & edges if the
|
||||||
|
// capacity was 0, because then the old pointers are dangling.
|
||||||
|
if leaf.capacity > 0 {
|
||||||
|
unsafe {
|
||||||
|
let len = leaf.len as usize;
|
||||||
|
|
||||||
|
core::ptr::copy_nonoverlapping(old_keys.as_ptr(), new_keys.as_mut_ptr(), len);
|
||||||
|
core::ptr::copy_nonoverlapping(old_edges.as_ptr(), new_edges.as_mut_ptr(), len);
|
||||||
|
|
||||||
|
// dealloc old keys and edges.
|
||||||
|
// This doesn't drop because the keys and edges were moved.
|
||||||
|
_ = Box::from_non_null(old_keys);
|
||||||
|
_ = Box::from_non_null(old_edges);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// SAFETY: new_capacity fits in a u16.
|
||||||
|
leaf.capacity = new_capacity as u16;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<K, V, Type> NodeRef<marker::Owned, K, V, Type> {
|
impl<K, V, Type> NodeRef<marker::Owned, K, V, Type> {
|
||||||
pub(super) fn reparent<'a>(
|
pub(super) fn reparent<'a, NodeType>(
|
||||||
mut self,
|
mut self,
|
||||||
mut parent: Handle<NodeRef<marker::Mut<'a>, K, V, marker::Internal>, marker::Edge>,
|
mut parent: Handle<NodeRef<marker::Mut<'a>, K, V, NodeType>, marker::Edge>,
|
||||||
key: K,
|
key: K,
|
||||||
) -> NodeRef<marker::Mut<'a>, K, V, Type>
|
) -> NodeRef<marker::Mut<'a>, K, V, Type>
|
||||||
where
|
where
|
||||||
K: 'a,
|
K: 'a,
|
||||||
V: 'a,
|
V: 'a,
|
||||||
{
|
{
|
||||||
self.borrow_mut().as_leaf_mut().parent = Some(NodeRef::as_internal_non_null(&parent.node));
|
self.borrow_mut().as_leaf_mut().parent = Some(NodeRef::as_leaf_non_null(&parent.node));
|
||||||
self.borrow_mut()
|
self.borrow_mut()
|
||||||
.as_leaf_mut()
|
.as_leaf_mut()
|
||||||
.parent_idx
|
.parent_idx
|
||||||
.write(parent.idx as u16);
|
.write(parent.idx as u16);
|
||||||
|
|
||||||
let new_len = parent.node.len() + 1;
|
let old_capacity = parent.node.capacity();
|
||||||
|
let old_len = parent.node.len();
|
||||||
|
let new_len = old_len + 1;
|
||||||
|
|
||||||
|
if new_len > old_capacity {
|
||||||
|
parent.node.grow_node();
|
||||||
|
}
|
||||||
|
|
||||||
|
// insert new key and child node.
|
||||||
|
// SAFETY: we just grew the allocations.
|
||||||
unsafe {
|
unsafe {
|
||||||
slice_insert(parent.node.key_area_mut(..new_len), parent.idx, key);
|
slice_insert(parent.node.key_area_mut(..new_len), parent.idx, key);
|
||||||
slice_insert(parent.node.edge_area_mut(..new_len), parent.idx, self.node);
|
slice_insert(parent.node.edge_area_mut(..new_len), parent.idx, self.node);
|
||||||
|
|
@ -794,19 +759,6 @@ impl<K, V, Type> NodeRef<marker::Owned, K, V, Type> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, K, V, Type> Handle<NodeRef<marker::Mut<'a>, K, V, marker::Leaf>, Type> {
|
|
||||||
/// node must have parent/ be a leaf node.
|
|
||||||
pub(super) unsafe fn make_internal_node(
|
|
||||||
self,
|
|
||||||
) -> Handle<NodeRef<marker::Mut<'a>, K, V, marker::Internal>, Type> {
|
|
||||||
Handle {
|
|
||||||
node: unsafe { self.node.make_internal_node() },
|
|
||||||
idx: self.idx,
|
|
||||||
_marker: PhantomData,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<BorrowType, K, V> Handle<NodeRef<BorrowType, K, V, marker::LeafOrInternal>, marker::Edge> {
|
impl<BorrowType, K, V> Handle<NodeRef<BorrowType, K, V, marker::LeafOrInternal>, marker::Edge> {
|
||||||
/// Converts this edge handle into a value handle.
|
/// Converts this edge handle into a value handle.
|
||||||
pub(super) fn into_value(
|
pub(super) fn into_value(
|
||||||
|
|
@ -854,50 +806,8 @@ impl<'a, K: 'a, V: 'a, Type> Handle<NodeRef<marker::Mut<'a>, K, V, Type>, marker
|
||||||
return unsafe { Handle::new_value(self.node.as_leaf_or_internal()) };
|
return unsafe { Handle::new_value(self.node.as_leaf_or_internal()) };
|
||||||
};
|
};
|
||||||
|
|
||||||
let idx = self.idx;
|
|
||||||
let mut internal = match self.force() {
|
|
||||||
ForceResult::Leaf(leaf) => {
|
|
||||||
// need to turn the leaf into an internal node.
|
|
||||||
|
|
||||||
// SAFETY: root is allocated as an internal node.
|
|
||||||
// the only node that doesn't have a parent is the root node,
|
|
||||||
// all parent nodes are internal nodes.
|
|
||||||
let internal = unsafe { leaf.make_internal_node() };
|
|
||||||
|
|
||||||
internal
|
|
||||||
}
|
|
||||||
ForceResult::Internal(mut internal) => {
|
|
||||||
if idx >= CAPACITY {
|
|
||||||
// create a sibling node
|
|
||||||
let mut sibling = NodeRef::new_internal();
|
|
||||||
let mut sibling = sibling.borrow_mut();
|
|
||||||
// let sibling = Box::into_non_null(InternalNode::new());
|
|
||||||
// set parent link
|
|
||||||
unsafe {
|
|
||||||
core::ptr::copy_nonoverlapping(
|
|
||||||
&raw mut internal.node.as_leaf_mut().parent,
|
|
||||||
&raw mut sibling.as_leaf_mut().parent,
|
|
||||||
1,
|
|
||||||
);
|
|
||||||
core::ptr::copy_nonoverlapping(
|
|
||||||
&raw mut internal.node.as_leaf_mut().parent_idx,
|
|
||||||
&raw mut sibling.as_leaf_mut().parent_idx,
|
|
||||||
1,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
internal.node.as_internal_mut().next =
|
|
||||||
Some(NodeRef::as_internal_non_null(&sibling));
|
|
||||||
|
|
||||||
unsafe { Handle::new_edge(sibling.dormant(), 0).awaken() }
|
|
||||||
} else {
|
|
||||||
internal
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let last = unsafe {
|
let last = unsafe {
|
||||||
let child = NodeRef::new_leaf().reparent(internal, key);
|
let child = NodeRef::new_leaf().reparent(self, key);
|
||||||
|
|
||||||
Handle::new_edge(child, 0)
|
Handle::new_edge(child, 0)
|
||||||
.insert_recursing(key_seq, val)
|
.insert_recursing(key_seq, val)
|
||||||
|
|
@ -1073,6 +983,8 @@ enum HandleOrTree<'a, BorrowType, K, V, NodeType, HandleType> {
|
||||||
mod entry {
|
mod entry {
|
||||||
use core::marker::PhantomData;
|
use core::marker::PhantomData;
|
||||||
|
|
||||||
|
use crate::tree::LeafNode;
|
||||||
|
|
||||||
use super::{Handle, NodeRef, Tree, borrow::DormantMutRef, marker};
|
use super::{Handle, NodeRef, Tree, borrow::DormantMutRef, marker};
|
||||||
|
|
||||||
pub enum Entry<'a, Q: 'a, K: 'a, V: 'a>
|
pub enum Entry<'a, Q: 'a, K: 'a, V: 'a>
|
||||||
|
|
@ -1172,7 +1084,11 @@ mod entry {
|
||||||
HandleOrTree::Tree(mut tree) => {
|
HandleOrTree::Tree(mut tree) => {
|
||||||
// SAFETY: there are no nodes in the tree yet
|
// SAFETY: there are no nodes in the tree yet
|
||||||
let tree = unsafe { tree.reborrow() };
|
let tree = unsafe { tree.reborrow() };
|
||||||
let root = tree.root.insert(NodeRef::new_internal());
|
let root =
|
||||||
|
tree.root
|
||||||
|
.insert(NodeRef::new_internal(alloc::boxed::Box::into_non_null(
|
||||||
|
LeafNode::new(),
|
||||||
|
)));
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
Handle::new_edge(root.borrow_mut(), 0).insert_recursing(self.key, value)
|
Handle::new_edge(root.borrow_mut(), 0).insert_recursing(self.key, value)
|
||||||
|
|
@ -1200,6 +1116,7 @@ mod subtree {
|
||||||
marker,
|
marker,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// BorrowType may be one of `Immut`, `Mut`.
|
||||||
pub struct Subtree<K, V, BorrowType> {
|
pub struct Subtree<K, V, BorrowType> {
|
||||||
pub(super) root: NodeRef<BorrowType, K, V, marker::LeafOrInternal>,
|
pub(super) root: NodeRef<BorrowType, K, V, marker::LeafOrInternal>,
|
||||||
}
|
}
|
||||||
|
|
@ -1578,12 +1495,10 @@ mod tests {
|
||||||
|
|
||||||
let mut leaf = NodeRef::<_, (), Test, _>::new_leaf();
|
let mut leaf = NodeRef::<_, (), Test, _>::new_leaf();
|
||||||
leaf.borrow_mut().as_leaf_mut().value = Some(Test("test"));
|
leaf.borrow_mut().as_leaf_mut().value = Some(Test("test"));
|
||||||
let mut root = NodeRef::new_internal();
|
let mut root = NodeRef::new_leaf();
|
||||||
|
|
||||||
let leaf = leaf.reparent(unsafe { Handle::new_edge(root.borrow_mut(), 0) }, ());
|
let mut leaf = leaf.reparent(unsafe { Handle::new_edge(root.borrow_mut(), 0) }, ());
|
||||||
|
|
||||||
let mut internal = unsafe { leaf.make_internal_node() };
|
assert_eq!(leaf.as_leaf_mut().value, Some(Test("test")));
|
||||||
|
|
||||||
assert_eq!(internal.as_leaf_mut().value, Some(Test("test")));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue