scc::tree_index

Struct TreeIndex

Source
pub struct TreeIndex<K, V> { /* private fields */ }
Expand description

Scalable concurrent B-plus tree.

TreeIndex is a concurrent and asynchronous B-plus tree variant that is optimized for read operations. Read operations, such as read, iteration over entries, are neither blocked nor interrupted by other threads or tasks. Write operations, such as insert, remove, do not block if structural changes are not required.

§Notes

TreeIndex methods are linearizable, however its iterator methods are not; Iter and Range are only guaranteed to observe events happened before the first call to Iterator::next.

§The key features of TreeIndex

  • Lock-free-read: read and scan operations do not modify shared data and are never blocked.
  • Near lock-free write: write operations do not block unless a structural change is needed.
  • No busy waiting: each node has a wait queue to avoid spinning.
  • Immutability: the data in the container is immutable until it becomes unreachable.

§The key statistics for TreeIndex

  • The maximum number of entries that a leaf can contain: 14.
  • The maximum number of leaves or child nodes that a node can point to: 15.

§Locking behavior

Read access is always lock-free and non-blocking. Write access to an entry is also lock-free and non-blocking as long as no structural changes are required. However, when nodes are being split or merged by a write operation, other write operations on keys in the affected range are blocked.

§Unwind safety

TreeIndex is impervious to out-of-memory errors and panics in user specified code on one condition; K::drop and V::drop must not panic.

Implementations§

Source§

impl<K, V> TreeIndex<K, V>

Source

pub const fn new() -> Self

Creates an empty TreeIndex.

§Examples
use scc::TreeIndex;

let treeindex: TreeIndex<u64, u32> = TreeIndex::new();
Source

pub fn clear(&self)

Clears the TreeIndex.

§Examples
use scc::TreeIndex;

let treeindex: TreeIndex<u64, u32> = TreeIndex::new();

treeindex.clear();
assert_eq!(treeindex.len(), 0);
Source

pub fn depth(&self) -> usize

Returns the depth of the TreeIndex.

§Examples
use scc::TreeIndex;

let treeindex: TreeIndex<u64, u32> = TreeIndex::new();
assert_eq!(treeindex.depth(), 0);
Source§

impl<K, V> TreeIndex<K, V>
where K: 'static + Clone + Ord, V: 'static + Clone,

Source

pub fn insert(&self, key: K, val: V) -> Result<(), (K, V)>

Inserts a key-value pair.

§Errors

Returns an error along with the supplied key-value pair if the key exists.

§Examples
use scc::TreeIndex;

let treeindex: TreeIndex<u64, u32> = TreeIndex::new();

assert!(treeindex.insert(1, 10).is_ok());
assert_eq!(treeindex.insert(1, 11).err().unwrap(), (1, 11));
assert_eq!(treeindex.peek_with(&1, |k, v| *v).unwrap(), 10);
Source

pub async fn insert_async(&self, key: K, val: V) -> Result<(), (K, V)>

Inserts a key-value pair.

It is an asynchronous method returning an impl Future for the caller to await.

§Errors

Returns an error along with the supplied key-value pair if the key exists.

§Examples
use scc::TreeIndex;

let treeindex: TreeIndex<u64, u32> = TreeIndex::new();
let future_insert = treeindex.insert_async(1, 10);
Source

pub fn remove<Q>(&self, key: &Q) -> bool
where Q: Comparable<K> + ?Sized,

Removes a key-value pair.

Returns false if the key does not exist.

Returns true if the key existed and the condition was met after marking the entry unreachable; the memory will be reclaimed later.

§Examples
use scc::TreeIndex;

let treeindex: TreeIndex<u64, u32> = TreeIndex::new();

assert!(!treeindex.remove(&1));
assert!(treeindex.insert(1, 10).is_ok());
assert!(treeindex.remove(&1));
Source

pub async fn remove_async<Q>(&self, key: &Q) -> bool
where Q: Comparable<K> + ?Sized,

Removes a key-value pair.

Returns false if the key does not exist. It is an asynchronous method returning an impl Future for the caller to await.

Returns true if the key existed and the condition was met after marking the entry unreachable; the memory will be reclaimed later.

§Examples
use scc::TreeIndex;

let treeindex: TreeIndex<u64, u32> = TreeIndex::new();
let future_remove = treeindex.remove_async(&1);
Source

pub fn remove_if<Q, F: FnMut(&V) -> bool>(&self, key: &Q, condition: F) -> bool
where Q: Comparable<K> + ?Sized,

Removes a key-value pair if the given condition is met.

Returns false if the key does not exist or the condition was not met.

Returns true if the key existed and the condition was met after marking the entry unreachable; the memory will be reclaimed later.

§Examples
use scc::TreeIndex;

let treeindex: TreeIndex<u64, u32> = TreeIndex::new();

assert!(treeindex.insert(1, 10).is_ok());
assert!(!treeindex.remove_if(&1, |v| *v == 0));
assert!(treeindex.remove_if(&1, |v| *v == 10));
Source

pub async fn remove_if_async<Q, F: FnMut(&V) -> bool>( &self, key: &Q, condition: F, ) -> bool
where Q: Comparable<K> + ?Sized,

Removes a key-value pair if the given condition is met.

Returns false if the key does not exist or the condition was not met. It is an asynchronous method returning an impl Future for the caller to await.

Returns true if the key existed and the condition was met after marking the entry unreachable; the memory will be reclaimed later.

§Examples
use scc::TreeIndex;

let treeindex: TreeIndex<u64, u32> = TreeIndex::new();
let future_remove = treeindex.remove_if_async(&1, |v| *v == 0);
Source

pub fn remove_range<Q, R: RangeBounds<Q>>(&self, range: R)
where Q: Comparable<K> + ?Sized,

Removes keys in the specified range.

This method removes internal nodes that are definitely contained in the specified range first, and then removes remaining entries individually.

§Notes

Internally, multiple internal node locks need to be acquired, thus making this method susceptible to lock starvation.

§Examples
use scc::TreeIndex;

let treeindex: TreeIndex<u64, u32> = TreeIndex::new();

for k in 2..8 {
    assert!(treeindex.insert(k, 1).is_ok());
}

treeindex.remove_range(3..8);

assert!(treeindex.contains(&2));
assert!(!treeindex.contains(&3));
Source

pub async fn remove_range_async<Q, R: RangeBounds<Q>>(&self, range: R)
where Q: Comparable<K> + ?Sized,

Removes keys in the specified range.

This method removes internal nodes that are definitely contained in the specified range first, and then removes remaining entries individually.

It is an asynchronous method returning an impl Future for the caller to await.

§Notes

Internally, multiple internal node locks need to be acquired, thus making this method susceptible to lock starvation.

§Examples
use scc::TreeIndex;

let treeindex: TreeIndex<u64, u32> = TreeIndex::new();

for k in 2..8 {
    assert!(treeindex.insert(k, 1).is_ok());
}

let future_remove_range = treeindex.remove_range_async(3..8);
Source

pub fn peek<'g, Q>(&self, key: &Q, guard: &'g Guard) -> Option<&'g V>
where Q: Comparable<K> + ?Sized,

Returns a guarded reference to the value for the specified key without acquiring locks.

Returns None if the key does not exist. The returned reference can survive as long as the associated Guard is alive.

§Examples
use scc::ebr::Guard;
use std::sync::Arc;
use scc::TreeIndex;

let treeindex: TreeIndex<Arc<str>, u32> = TreeIndex::new();

let guard = Guard::new();
assert!(treeindex.peek("foo", &guard).is_none());

treeindex.insert("foo".into(), 1).expect("insert in empty TreeIndex");
Source

pub fn peek_with<Q, R, F: FnOnce(&K, &V) -> R>( &self, key: &Q, reader: F, ) -> Option<R>
where Q: Comparable<K> + ?Sized,

Peeks a key-value pair without acquiring locks.

Returns None if the key does not exist.

§Examples
use std::sync::Arc;
use scc::TreeIndex;

let treeindex: TreeIndex<Arc<str>, u32> = TreeIndex::new();

assert!(treeindex.peek_with("foo", |k, v| *v).is_none());

treeindex.insert("foo".into(), 1).expect("insert in empty TreeIndex");

let key: Arc<str> = treeindex
    .peek_with("foo", |k, _v| Arc::clone(k))
    .expect("peek_with by borrowed key");
Source

pub fn peek_entry<'g, Q>( &self, key: &Q, guard: &'g Guard, ) -> Option<(&'g K, &'g V)>
where Q: Comparable<K> + ?Sized,

Returns a guarded reference to the key-value pair for the specified key without acquiring locks.

Returns None if the key does not exist. The returned reference can survive as long as the associated Guard is alive.

§Examples
use scc::ebr::Guard;
use std::sync::Arc;
use scc::TreeIndex;

let treeindex: TreeIndex<Arc<str>, u32> = TreeIndex::new();

let guard = Guard::new();
assert!(treeindex.peek_entry("foo", &guard).is_none());

treeindex.insert("foo".into(), 1).expect("insert in empty TreeIndex");

let key: Arc<str> = treeindex
    .peek_entry("foo", &guard)
    .map(|(k, _v)| Arc::clone(k))
    .expect("peek_entry by borrowed key");
Source

pub fn contains<Q>(&self, key: &Q) -> bool
where Q: Comparable<K> + ?Sized,

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));
Source

pub fn len(&self) -> usize

Returns the size of the TreeIndex.

It internally scans all the leaf nodes, and therefore the time complexity is O(N).

§Examples
use scc::TreeIndex;

let treeindex: TreeIndex<u64, u32> = TreeIndex::new();
assert_eq!(treeindex.len(), 0);
Source

pub fn is_empty(&self) -> bool

Returns true if the TreeIndex is empty.

§Examples
use scc::TreeIndex;

let treeindex: TreeIndex<u64, u32> = TreeIndex::new();

assert!(treeindex.is_empty());
Source

pub fn iter<'t, 'g>(&'t self, guard: &'g Guard) -> Iter<'t, 'g, K, V>

Returns an Iter.

The returned Iter starts scanning from the minimum key-value pair. Key-value pairs are scanned in ascending order, and key-value pairs that have existed since the invocation of the method are guaranteed to be visited if they are not removed. However, it is possible to visit removed key-value pairs momentarily.

§Examples
use scc::TreeIndex;
use scc::ebr::Guard;

let treeindex: TreeIndex<u64, u32> = TreeIndex::new();

let guard = Guard::new();
let mut iter = treeindex.iter(&guard);
assert!(iter.next().is_none());
Source

pub fn range<'t, 'g, Q, R: RangeBounds<Q>>( &'t self, range: R, guard: &'g Guard, ) -> Range<'t, 'g, K, V, Q, R>
where Q: Comparable<K> + ?Sized,

Returns a Range that scans keys in the given range.

Key-value pairs in the range are scanned in ascending order, and key-value pairs that have existed since the invocation of the method are guaranteed to be visited if they are not removed. However, it is possible to visit removed key-value pairs momentarily.

§Examples
use scc::TreeIndex;
use scc::ebr::Guard;

let treeindex: TreeIndex<u64, u32> = TreeIndex::new();

let guard = Guard::new();
assert_eq!(treeindex.range(4..=8, &guard).count(), 0);

Trait Implementations§

Source§

impl<K, V> Clone for TreeIndex<K, V>
where K: 'static + Clone + Ord, V: 'static + Clone,

Source§

fn clone(&self) -> Self

Returns a copy of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl<K, V> Debug for TreeIndex<K, V>
where K: 'static + Clone + Debug + Ord, V: 'static + Clone + Debug,

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl<K, V> Default for TreeIndex<K, V>

Source§

fn default() -> Self

Creates a TreeIndex with the default parameters.

§Examples
use scc::TreeIndex;

let treeindex: TreeIndex<u64, u32> = TreeIndex::default();
Source§

impl<K, V> Drop for TreeIndex<K, V>

Source§

fn drop(&mut self)

Executes the destructor for this type. Read more
Source§

impl<K, V> PartialEq for TreeIndex<K, V>
where K: 'static + Clone + Ord, V: 'static + Clone + PartialEq,

Source§

fn eq(&self, other: &Self) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 · Source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
Source§

impl<K, V> UnwindSafe for TreeIndex<K, V>

Auto Trait Implementations§

§

impl<K, V> !Freeze for TreeIndex<K, V>

§

impl<K, V> RefUnwindSafe for TreeIndex<K, V>

§

impl<K, V> Send for TreeIndex<K, V>
where K: Send, V: Send,

§

impl<K, V> Sync for TreeIndex<K, V>
where K: Sync, V: Sync,

§

impl<K, V> Unpin for TreeIndex<K, V>

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dst: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dst. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.