Struct sharded_slab::Slab

source ·
pub struct Slab<T, C: Config = DefaultConfig> { /* private fields */ }
Expand description

A sharded slab.

See the crate-level documentation for details on using this type.

Implementations§

source§

impl<T> Slab<T>

source

pub fn new() -> Self

Returns a new slab with the default configuration parameters.

source

pub fn new_with_config<C: Config>() -> Slab<T, C>

Returns a new slab with the provided configuration parameters.

source§

impl<T, C: Config> Slab<T, C>

source

pub const USED_BITS: usize = C::USED_BITS

The number of bits in each index which are used by the slab.

If other data is packed into the usize indices returned by Slab::insert, user code is free to use any bits higher than the USED_BITS-th bit freely.

This is determined by the Config type that configures the slab’s parameters. By default, all bits are used; this can be changed by overriding the Config::RESERVED_BITS constant.

source

pub fn insert(&self, value: T) -> Option<usize>

Inserts a value into the slab, returning the integer index at which that value was inserted. This index can then be used to access the entry.

If this function returns None, then the shard for the current thread is full and no items can be added until some are removed, or the maximum number of shards has been reached.

Examples
let slab = Slab::new();

let key = slab.insert("hello world").unwrap();
assert_eq!(slab.get(key).unwrap(), "hello world");
source

pub fn vacant_entry(&self) -> Option<VacantEntry<'_, T, C>>

Return a handle to a vacant entry allowing for further manipulation.

This function is useful when creating values that must contain their slab index. The returned VacantEntry reserves a slot in the slab and is able to return the index of the entry.

Examples
let mut slab = Slab::new();

let hello = {
    let entry = slab.vacant_entry().unwrap();
    let key = entry.key();

    entry.insert((key, "hello"));
    key
};

assert_eq!(hello, slab.get(hello).unwrap().0);
assert_eq!("hello", slab.get(hello).unwrap().1);
source

pub fn remove(&self, idx: usize) -> bool

Remove the value at the given index in the slab, returning true if a value was removed.

Unlike take, this method does not block the current thread until the value can be removed. Instead, if another thread is currently accessing that value, this marks it to be removed by that thread when it finishes accessing the value.

Examples
let slab = sharded_slab::Slab::new();
let key = slab.insert("hello world").unwrap();

// Remove the item from the slab.
assert!(slab.remove(key));

// Now, the slot is empty.
assert!(!slab.contains(key));
use std::sync::Arc;

let slab = Arc::new(sharded_slab::Slab::new());
let key = slab.insert("hello world").unwrap();

let slab2 = slab.clone();
let thread2 = std::thread::spawn(move || {
    // Depending on when this thread begins executing, the item may
    // or may not have already been removed...
    if let Some(item) = slab2.get(key) {
        assert_eq!(item, "hello world");
    }
});

// The item will be removed by thread2 when it finishes accessing it.
assert!(slab.remove(key));

thread2.join().unwrap();
assert!(!slab.contains(key));
source

pub fn take(&self, idx: usize) -> Option<T>

Removes the value associated with the given key from the slab, returning it.

If the slab does not contain a value for that key, None is returned instead.

If the value associated with the given key is currently being accessed by another thread, this method will block the current thread until the item is no longer accessed. If this is not desired, use remove instead.

Note: This method blocks the calling thread by spinning until the currently outstanding references are released. Spinning for long periods of time can result in high CPU time and power consumption. Therefore, take should only be called when other references to the slot are expected to be dropped soon (e.g., when all accesses are relatively short).

Examples
let slab = sharded_slab::Slab::new();
let key = slab.insert("hello world").unwrap();

// Remove the item from the slab, returning it.
assert_eq!(slab.take(key), Some("hello world"));

// Now, the slot is empty.
assert!(!slab.contains(key));
use std::sync::Arc;

let slab = Arc::new(sharded_slab::Slab::new());
let key = slab.insert("hello world").unwrap();

let slab2 = slab.clone();
let thread2 = std::thread::spawn(move || {
    // Depending on when this thread begins executing, the item may
    // or may not have already been removed...
    if let Some(item) = slab2.get(key) {
        assert_eq!(item, "hello world");
    }
});

// The item will only be removed when the other thread finishes
// accessing it.
assert_eq!(slab.take(key), Some("hello world"));

thread2.join().unwrap();
assert!(!slab.contains(key));
source

pub fn get(&self, key: usize) -> Option<Entry<'_, T, C>>

Return a reference to the value associated with the given key.

If the slab does not contain a value for the given key, or if the maximum number of concurrent references to the slot has been reached, None is returned instead.

Examples
let slab = sharded_slab::Slab::new();
let key = slab.insert("hello world").unwrap();

assert_eq!(slab.get(key).unwrap(), "hello world");
assert!(slab.get(12345).is_none());
source

pub fn get_owned(self: Arc<Self>, key: usize) -> Option<OwnedEntry<T, C>>

Return an owned reference to the value at the given index.

If the slab does not contain a value for the given key, None is returned instead.

Unlike get, which borrows the slab, this method clones the Arc around the slab. This means that the returned OwnedEntry can be held for an arbitrary lifetime. However, this method requires that the slab itself be wrapped in an Arc.

Examples
use std::sync::Arc;

let slab: Arc<Slab<&'static str>> = Arc::new(Slab::new());
let key = slab.insert("hello world").unwrap();

// Look up the created key, returning an `OwnedEntry`.
let value = slab.clone().get_owned(key).unwrap();

// Now, the original `Arc` clone of the slab may be dropped, but the
// returned `OwnedEntry` can still access the value.
assert_eq!(value, "hello world");

Unlike Entry, an OwnedEntry may be stored in a struct which must live for the 'static lifetime:

use sharded_slab::OwnedEntry;
use std::sync::Arc;

pub struct MyStruct {
    entry: OwnedEntry<&'static str>,
    // ... other fields ...
}

// Suppose this is some arbitrary function which requires a value that
// lives for the 'static lifetime...
fn function_requiring_static<T: 'static>(t: &T) {
    // ... do something extremely important and interesting ...
}

let slab: Arc<Slab<&'static str>> = Arc::new(Slab::new());
let key = slab.insert("hello world").unwrap();

// Look up the created key, returning an `OwnedEntry`.
let entry = slab.clone().get_owned(key).unwrap();
let my_struct = MyStruct {
    entry,
    // ...
};

// We can use `my_struct` anywhere where it is required to have the
// `'static` lifetime:
function_requiring_static(&my_struct);

OwnedEntrys may be sent between threads:

use std::{thread, sync::Arc};

let slab: Arc<Slab<&'static str>> = Arc::new(Slab::new());
let key = slab.insert("hello world").unwrap();

// Look up the created key, returning an `OwnedEntry`.
let value = slab.clone().get_owned(key).unwrap();

thread::spawn(move || {
    assert_eq!(value, "hello world");
    // ...
}).join().unwrap();
source

pub fn contains(&self, key: usize) -> bool

Returns true if the slab contains a value for the given key.

Examples
let slab = sharded_slab::Slab::new();

let key = slab.insert("hello world").unwrap();
assert!(slab.contains(key));

slab.take(key).unwrap();
assert!(!slab.contains(key));
source

pub fn unique_iter(&mut self) -> UniqueIter<'_, T, C>

Returns an iterator over all the items in the slab.

Trait Implementations§

source§

impl<T: Debug, C: Config> Debug for Slab<T, C>

source§

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

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

impl<T> Default for Slab<T>

source§

fn default() -> Self

Returns the “default value” for a type. Read more
source§

impl<T: Send, C: Config> Send for Slab<T, C>

source§

impl<T: Sync, C: Config> Sync for Slab<T, C>

Auto Trait Implementations§

§

impl<T, C> RefUnwindSafe for Slab<T, C>where C: RefUnwindSafe,

§

impl<T, C> Unpin for Slab<T, C>where C: Unpin,

§

impl<T, C = DefaultConfig> !UnwindSafe for Slab<T, C>

Blanket Implementations§

source§

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

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

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

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

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

source§

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

Mutably borrows from an owned value. 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 Twhere 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, U> TryFrom<U> for Twhere U: Into<T>,

§

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 Twhere U: TryFrom<T>,

§

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.