From daab6703d127588c2167a512583423e17bd7670a Mon Sep 17 00:00:00 2001 From: Xiangpeng Hao Date: Wed, 20 Nov 2024 21:35:23 -0600 Subject: [PATCH] add is_empty --- src/base_node.rs | 48 ++++++++++++++++++++++++++++++++++++++++-------- src/lib.rs | 16 ++++++++++++++++ src/lock.rs | 1 - src/node_4.rs | 17 +++++------------ src/tree.rs | 11 +++++++++++ 5 files changed, 72 insertions(+), 21 deletions(-) diff --git a/src/base_node.rs b/src/base_node.rs index 6880e43..6f2439e 100644 --- a/src/base_node.rs +++ b/src/base_node.rs @@ -120,19 +120,19 @@ macro_rules! gen_method { pub(crate) fn $method_name(&self, $($arg_n : $args),*) -> $return { match self.get_type() { NodeType::N4 => { - let node = unsafe{&* (self as *const BaseNode as *const Node4)}; + let node = self.as_n4(); node.$method_name($($arg_n),*) }, NodeType::N16 => { - let node = unsafe{&* (self as *const BaseNode as *const Node16)}; + let node = self.as_n16(); node.$method_name($($arg_n),*) }, NodeType::N48 => { - let node = unsafe{&* (self as *const BaseNode as *const Node48)}; + let node = self.as_n48(); node.$method_name($($arg_n),*) }, NodeType::N256 => { - let node = unsafe{&* (self as *const BaseNode as *const Node256)}; + let node = self.as_n256(); node.$method_name($($arg_n),*) }, } @@ -147,19 +147,19 @@ macro_rules! gen_method_mut { pub(crate) fn $method_name(&mut self, $($arg_n : $args),*) -> $return { match self.get_type() { NodeType::N4 => { - let node = unsafe{&mut * (self as *mut BaseNode as *mut Node4)}; + let node = self.as_n4_mut(); node.$method_name($($arg_n),*) }, NodeType::N16 => { - let node = unsafe{&mut * (self as *mut BaseNode as *mut Node16)}; + let node = self.as_n16_mut(); node.$method_name($($arg_n),*) }, NodeType::N48 => { - let node = unsafe{&mut * (self as *mut BaseNode as *mut Node48)}; + let node = self.as_n48_mut(); node.$method_name($($arg_n),*) }, NodeType::N256 => { - let node = unsafe{&mut * (self as *mut BaseNode as *mut Node256)}; + let node = self.as_n256_mut(); node.$method_name($($arg_n),*) }, } @@ -231,6 +231,38 @@ impl BaseNode { self.meta.node_type } + pub(crate) fn as_n4(&self) -> &Node4 { + unsafe { &*(self as *const BaseNode as *const Node4) } + } + + pub(crate) fn as_n16(&self) -> &Node16 { + unsafe { &*(self as *const BaseNode as *const Node16) } + } + + pub(crate) fn as_n48(&self) -> &Node48 { + unsafe { &*(self as *const BaseNode as *const Node48) } + } + + pub(crate) fn as_n256(&self) -> &Node256 { + unsafe { &*(self as *const BaseNode as *const Node256) } + } + + pub(crate) fn as_n4_mut(&mut self) -> &mut Node4 { + unsafe { &mut *(self as *mut BaseNode as *mut Node4) } + } + + pub(crate) fn as_n16_mut(&mut self) -> &mut Node16 { + unsafe { &mut *(self as *mut BaseNode as *mut Node16) } + } + + pub(crate) fn as_n48_mut(&mut self) -> &mut Node48 { + unsafe { &mut *(self as *mut BaseNode as *mut Node48) } + } + + pub(crate) fn as_n256_mut(&mut self) -> &mut Node256 { + unsafe { &mut *(self as *mut BaseNode as *mut Node256) } + } + fn read_lock_inner<'a>(node: NonNull) -> Result, ArtError> { let version = unsafe { &*node.as_ptr() } .type_version_lock_obsolete diff --git a/src/lib.rs b/src/lib.rs index 8ee45aa..a652a64 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -207,6 +207,22 @@ where } } + /// Returns if the tree is empty. + /// + /// # Examples + /// + /// ``` + /// use congee::Congee; + /// let tree = Congee::default(); + /// let guard = tree.pin(); + /// assert!(tree.is_empty(&guard)); + /// tree.insert(1, 42, &guard); + /// assert!(!tree.is_empty(&guard)); + /// ``` + pub fn is_empty(&self, guard: &epoch::Guard) -> bool { + self.inner.is_empty(guard) + } + /// Removes key-value pair from the tree, returns the value if the key was found. /// /// # Examples diff --git a/src/lock.rs b/src/lock.rs index 3e37d0e..f5dc636 100644 --- a/src/lock.rs +++ b/src/lock.rs @@ -29,7 +29,6 @@ impl<'a, T: Node> TypedReadGuard<'a, T> { Ordering::Relaxed, ) { Ok(_) => Ok(TypedWriteGuard { - // SAFETY: this is seems to be unsound, but we (1) acquired write lock, (2) has the right memory ordering. node: unsafe { &mut *(self.node as *mut T) }, }), Err(_v) => Err((self, ArtError::VersionNotMatch)), diff --git a/src/node_4.rs b/src/node_4.rs index 9ebc15d..89377a1 100644 --- a/src/node_4.rs +++ b/src/node_4.rs @@ -107,18 +107,11 @@ impl Node for Node4 { } } - unsafe { - std::ptr::copy( - self.keys.as_ptr().add(pos), - self.keys.as_mut_ptr().add(pos + 1), - self.base.meta.count as usize - pos, - ); - - std::ptr::copy( - self.children.as_ptr().add(pos), - self.children.as_mut_ptr().add(pos + 1), - self.base.meta.count as usize - pos, - ); + if pos < self.base.meta.count as usize { + self.keys + .copy_within(pos..self.base.meta.count as usize, pos + 1); + self.children + .copy_within(pos..self.base.meta.count as usize, pos + 1); } self.keys[pos] = key; diff --git a/src/tree.rs b/src/tree.rs index 34e4c17..6bd7248 100644 --- a/src/tree.rs +++ b/src/tree.rs @@ -74,6 +74,17 @@ impl RawCongee { } impl RawCongee { + pub(crate) fn is_empty(&self, _guard: &Guard) -> bool { + loop { + if let Ok(node) = BaseNode::read_lock_root(self.root) { + let is_empty = node.as_ref().meta.count == 0; + if node.check_version().is_ok() { + return is_empty; + } + } + } + } + #[inline] pub(crate) fn get(&self, key: &[u8; K_LEN], _guard: &Guard) -> Option { 'outer: loop {