Skip to content

Commit

Permalink
feat(#112, tree_index): refine API
Browse files Browse the repository at this point in the history
- add `contains`.
- `remove_range` does not return the count of removed entries as it
requires O(N) code.
  • Loading branch information
wvwwvwwv committed Jan 7, 2024
1 parent 2415ce9 commit 420797a
Show file tree
Hide file tree
Showing 7 changed files with 82 additions and 10 deletions.
1 change: 1 addition & 0 deletions .config/glossary.txt
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ scalability
Scalable
Serde
SIMD
TODO
TreeIndex
Unlinking
unlinking
Expand Down
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

## Version 2

2.0.9

* Add `TreeIndex::contains` and `TreeIndex::remove_range`; `TreeIndex::remove_range` is experimental and will be stabilized later ([#120](https://github.com/wvwwvwwv/scalable-concurrent-containers/issues/120)).

2.0.8

* Add support for old Rust versions >= 1.65.0.
Expand Down
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
name = "scc"
description = "High performance containers and utilities for concurrent and asynchronous programming"
documentation = "https://docs.rs/scc"
version = "2.0.8"
version = "2.0.9"
authors = ["wvwwvwwv <[email protected]>"]
edition = "2021"
rust-version = "1.65.0"
Expand Down
42 changes: 33 additions & 9 deletions src/tree_index.rs
Original file line number Diff line number Diff line change
Expand Up @@ -442,7 +442,7 @@ where

/// Removes keys in the specified range.
///
/// Returns the count of removed entries.
/// Experimental: [`issue 120`](https://github.com/wvwwvwwv/scalable-concurrent-containers/issues/120).
///
/// # Examples
///
Expand All @@ -454,20 +454,22 @@ where
/// for k in 2..8 {
/// assert!(treeindex.insert(k, 1).is_ok());
/// }
/// assert_eq!(treeindex.remove_range(3..8), 5);
///
/// treeindex.remove_range(3..8);
///
/// assert!(treeindex.contains(&2));
/// assert!(!treeindex.contains(&3));
/// ```
// TODO: #120 - implement an asynchronous version of this method.
#[inline]
pub fn remove_range<R: RangeBounds<K>>(&self, range: R) -> usize {
// TODO: #120 - implement O(1) bulk removal without using `Range`.
let mut count = 0;
pub fn remove_range<R: RangeBounds<K>>(&self, range: R) {
let guard = Guard::new();
if let Some(root_ref) = self.root.load(Acquire, &guard).as_ref() {
root_ref.remove_range(&range, &mut (), &guard); // TODO: #120 - implement O(1) bulk removal without using `Range`.
}
for (k, _) in self.range(range, &guard) {
if self.remove(k) {
count += 1;
}
self.remove(k);
}
count
}

/// Returns a guarded reference to the value for the specified key without acquiring locks.
Expand Down Expand Up @@ -520,6 +522,28 @@ where
self.peek(key, &guard).map(|v| reader(key, v))
}

/// Returns `true` if the [`TreeIndex`] contains the key.
///
/// # Examples
///
/// ```
/// use scc::TreeIndex;
///
/// let treeindex: TreeIndex<u64, u32> = TreeIndex::default();
///
/// assert!(!treeindex.contains(&1));
/// assert!(treeindex.insert(1, 0).is_ok());
/// assert!(treeindex.contains(&1));
/// ```
#[inline]
pub fn contains<Q>(&self, key: &Q) -> bool
where
K: Borrow<Q>,
Q: Ord + ?Sized,
{
self.peek(key, &Guard::new()).is_some()
}

/// Clears the [`TreeIndex`].
///
/// # Examples
Expand Down
14 changes: 14 additions & 0 deletions src/tree_index/internal_node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use crate::exit_guard::ExitGuard;
use crate::wait_queue::{DeriveAsyncWait, WaitQueue};
use std::borrow::Borrow;
use std::cmp::Ordering::{Equal, Greater, Less};
use std::ops::RangeBounds;
use std::ptr;
use std::sync::atomic::Ordering::{self, Acquire, Relaxed, Release};
use std::sync::atomic::{AtomicPtr, AtomicU8};
Expand Down Expand Up @@ -363,6 +364,19 @@ where
}
}

/// Removes a range of entries.
#[allow(clippy::unused_self)]
#[inline]
pub(super) fn remove_range<R: RangeBounds<K>, D: DeriveAsyncWait>(
&self,
_range: &R,
_async_wait: &mut D,
_guard: &Guard,
) -> bool {
// TODO: #120 - implement O(1) bulk removal without using `Range`.
true
}

/// Splits a full node.
///
/// # Errors
Expand Down
14 changes: 14 additions & 0 deletions src/tree_index/leaf_node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use crate::wait_queue::{DeriveAsyncWait, WaitQueue};
use crate::LinkedList;
use std::borrow::Borrow;
use std::cmp::Ordering::{Equal, Greater, Less};
use std::ops::RangeBounds;
use std::ptr;
use std::sync::atomic::Ordering::{self, AcqRel, Acquire, Relaxed, Release};
use std::sync::atomic::{AtomicPtr, AtomicU8};
Expand Down Expand Up @@ -351,6 +352,19 @@ where
}
}

/// Removes a range of entries.
#[allow(clippy::unused_self)]
#[inline]
pub(super) fn remove_range<R: RangeBounds<K>, D: DeriveAsyncWait>(
&self,
_range: &R,
_async_wait: &mut D,
_guard: &Guard,
) -> bool {
// TODO: #120 - implement O(1) bulk removal without using `Range`.
true
}

/// Splits itself into the given leaf nodes, and returns the middle key value.
#[allow(clippy::too_many_lines)]
pub(super) fn split_leaf_node<'g>(
Expand Down
15 changes: 15 additions & 0 deletions src/tree_index/node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ use crate::ebr::{AtomicShared, Guard, Shared, Tag};
use crate::wait_queue::DeriveAsyncWait;
use std::borrow::Borrow;
use std::fmt::{self, Debug};
use std::ops::RangeBounds;
use std::sync::atomic::Ordering::{self, Acquire, Relaxed, Release};

/// [`Node`] is either [`Self::Internal`] or [`Self::Leaf`].
Expand Down Expand Up @@ -134,6 +135,20 @@ where
}
}

/// Removes a range of entries.
#[inline]
pub(super) fn remove_range<R: RangeBounds<K>, D: DeriveAsyncWait>(
&self,
range: &R,
async_wait: &mut D,
guard: &Guard,
) -> bool {
match &self {
Self::Internal(internal_node) => internal_node.remove_range(range, async_wait, guard),
Self::Leaf(leaf_node) => leaf_node.remove_range(range, async_wait, guard),
}
}

/// Splits the current root node.
#[inline]
pub(super) fn split_root(
Expand Down

0 comments on commit 420797a

Please sign in to comment.