[−][src]Struct sharded_slab::Pool
A lock-free concurrent object pool.
Slabs provide pre-allocated storage for many instances of a single type. But, when working with heap allocated objects, the advantages of a slab are lost, as the memory allocated for the object is freed when the object is removed from the slab. With a pool, we can instead reuse this memory for objects being added to the pool in the future, therefore reducing memory fragmentation and avoiding additional allocations.
This type implements a lock-free concurrent pool, indexed by usize
s. The items stored in this
type need to implement Clear
and Default
.
The Pool
type shares similar semantics to Slab
when it comes to sharing across threads
and storing mutable shared data. The biggest difference is there are no Slab::insert
and
Slab::take
analouges for the Pool
type. Instead new items are added to the pool by using
the Pool::create
method, and marked for clearing by the Pool::clear
method.
Examples
Add an entry to the pool, returning an index:
let pool: Pool<String> = Pool::new(); let key = pool.create(|item| item.push_str("hello world")).unwrap(); assert_eq!(pool.get(key).unwrap(), String::from("hello world"));
Pool entries can be cleared either by manually calling Pool::clear
. This marks the entry to
be cleared when the guards referencing to it are dropped.
let pool: Pool<String> = Pool::new(); let key = pool.create(|item| item.push_str("hello world")).unwrap(); // Mark this entry to be cleared. pool.clear(key); // The cleared entry is no longer available in the pool assert!(pool.get(key).is_none());
Configuration
Both Pool
and Slab
share the same configuration mechanism. See crate level documentation
for more details.
Methods
impl<T> Pool<T> where
T: Clear + Default,
[src]
T: Clear + Default,
pub fn new() -> Self
[src]
pub fn new_with_config<C: Config>() -> Pool<T, C>
[src]
Returns a new Pool
with the provided configuration parameters.
impl<T, C> Pool<T, C> where
T: Clear + Default,
C: Config,
[src]
T: Clear + Default,
C: Config,
pub const USED_BITS: usize
[src]
The number of bits in each index which are used by the pool.
If other data is packed into the usize
indices returned by
Pool::create
, 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 pool's
parameters. By default, all bits are used; this can be changed by
overriding the Config::RESERVED_BITS
constant.
pub fn create(&self, initializer: impl FnOnce(&mut T)) -> Option<usize>
[src]
Creates a new object in the pool, returning a key that can be used to access it.
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 pool: Pool<String> = Pool::new(); let key = pool.create(|item| item.push_str("Hello")).unwrap(); assert_eq!(pool.get(key).unwrap(), String::from("Hello"));
pub fn get(&self, key: usize) -> Option<PoolGuard<T, C>>
[src]
Return a reference to the value associated with the given key.
If the pool does not contain a value for the given key, None
is returned instead.
Examples
let pool: Pool<String> = sharded_slab::Pool::new(); let key = pool.create(|item| item.push_str("hello world")).unwrap(); assert_eq!(pool.get(key).unwrap(), String::from("hello world")); assert!(pool.get(12345).is_none());
pub fn clear(&self, key: usize) -> bool
[src]
Remove the value using the storage associated with the given key from the pool, returning
true
if the value was removed.
This method does not block the current thread until the value can be cleared. Instead, if another thread is currently accessing that value, this marks it to be cleared by that thread when it is done accessing that value.
Examples
let pool: Pool<String> = Pool::new(); let key = pool.create(|item| item.push_str("hello world")).unwrap(); assert_eq!(pool.get(key).unwrap(), String::from("hello world")); pool.clear(key); assert!(pool.get(key).is_none());
let pool: Pool<String> = Pool::new(); let key = pool.create(|item| item.push_str("Hello world!")).unwrap(); // Clearing a key that doesn't exist in the `Pool` will return `false` assert_eq!(pool.clear(key + 69420), false); // Clearing a key that does exist returns `true` assert!(pool.clear(key)); // Clearing a key that has previously been cleared will return `false` assert_eq!(pool.clear(key), false);
Trait Implementations
impl<T, C> Debug for Pool<T, C> where
T: Debug + Clear + Default,
C: Config,
[src]
T: Debug + Clear + Default,
C: Config,
impl<T> Default for Pool<T> where
T: Clear + Default,
[src]
T: Clear + Default,
impl<T, C> Send for Pool<T, C> where
T: Send + Clear + Default,
C: Config,
[src]
T: Send + Clear + Default,
C: Config,
impl<T, C> Sync for Pool<T, C> where
T: Sync + Clear + Default,
C: Config,
[src]
T: Sync + Clear + Default,
C: Config,
Auto Trait Implementations
impl<T, C = DefaultConfig> !RefUnwindSafe for Pool<T, C>
impl<T, C> Unpin for Pool<T, C> where
C: Unpin,
C: Unpin,
impl<T, C> UnwindSafe for Pool<T, C> where
C: UnwindSafe,
T: UnwindSafe,
C: UnwindSafe,
T: UnwindSafe,
Blanket Implementations
impl<T> Any for T where
T: 'static + ?Sized,
[src]
T: 'static + ?Sized,
impl<T> Borrow<T> for T where
T: ?Sized,
[src]
T: ?Sized,
impl<T> BorrowMut<T> for T where
T: ?Sized,
[src]
T: ?Sized,
fn borrow_mut(&mut self) -> &mut T
[src]
impl<T> From<T> for T
[src]
impl<T, U> Into<U> for T where
U: From<T>,
[src]
U: From<T>,
impl<T, U> TryFrom<U> for T where
U: Into<T>,
[src]
U: Into<T>,
type Error = Infallible
The type returned in the event of a conversion error.
fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>
[src]
impl<T, U> TryInto<U> for T where
U: TryFrom<T>,
[src]
U: TryFrom<T>,