Skip to main content

UnboundedSlab

Struct UnboundedSlab 

Source
pub struct UnboundedSlab<T> { /* private fields */ }
Expand description

Growable slab allocator.

Uses independent chunks for growth — no copying when the slab grows.

§Drop Behavior

Dropping a Slab does not drop values in occupied slots. SlotCell is a union, so the compiler cannot know which slots contain live values. The caller must free all outstanding RawSlot handles before dropping the slab, or the values will be leaked.

This is acceptable for the primary use case (TLS via thread_local!) where thread exit leaks all TLS storage anyway.

§Const Construction

Supports const construction via new() followed by runtime initialization via init(). This enables use with thread_local! using the const { } block syntax for zero-overhead TLS access.

thread_local! {
    static SLAB: Slab<MyType> = const { Slab::new() };
}

// Later, at runtime:
SLAB.with(|s| s.init(4096));

For direct usage, prefer with_chunk_capacity().

Implementations§

Source§

impl<const N: usize> Slab<AlignedBytes<N>>

Source

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

Inserts a value into the slab, returning a Slot handle.

Always succeeds — grows the slab if needed.

§Compile-Time Checks

Fails to compile if T is too large or too aligned for the slot.

Source

pub unsafe fn remove<T>(&self, slot: Slot<T>)
where T: ?Sized,

Drops the value and frees the slot.

Handles both thin and fat pointers: extracts the data pointer for freeing regardless of whether T is Sized or dyn Trait.

§Safety
  • slot must have been allocated from this slab
Source

pub unsafe fn take_value<T>(&self, slot: Slot<T>) -> T

Extracts the value and frees the slot (Sized only).

§Safety
  • slot must have been allocated from this slab
Source

pub unsafe fn reclaim<T>(&self, slot: Slot<T>)
where T: ?Sized,

Frees the slot without dropping the value.

Use when the value has already been moved out or dropped.

§Safety
  • slot must have been allocated from this slab
  • The value must already be dropped or moved out
Source§

impl<T> Slab<T>

Source

pub const fn new() -> Slab<T>

Creates an empty, uninitialized slab.

This is a const function that performs no allocation. Call init() to configure chunk capacity before use.

For direct usage, prefer with_chunk_capacity().

§Example
// For use with thread_local! const initialization
thread_local! {
    static SLAB: Slab<u64> = const { Slab::new() };
}
Source

pub fn with_chunk_capacity(chunk_capacity: usize) -> Slab<T>

Creates a new slab with the given chunk capacity.

Chunks are allocated on-demand when slots are requested.

§Panics

Panics if chunk_capacity is zero.

Source

pub fn init(&self, chunk_capacity: usize)

Initializes the slab with the given chunk capacity.

This configures the chunk parameters. Chunks are allocated on-demand when slots are requested. Must be called exactly once before any allocations.

§Panics
  • Panics if the slab is already initialized (chunk_capacity > 0)
  • Panics if chunk_capacity is zero
Source

pub fn is_initialized(&self) -> bool

Returns true if the slab has been initialized.

Source

pub fn capacity(&self) -> usize

Returns the total capacity across all chunks.

Source

pub fn chunk_capacity(&self) -> usize

Returns the chunk capacity.

Source

pub fn chunk_count(&self) -> usize

Returns the number of allocated chunks.

Source

pub fn reserve_chunks(&self, count: usize)

Ensures at least count chunks are allocated.

No-op if the slab already has count or more chunks. Only allocates the difference.

Source

pub fn claim(&self) -> Claim<'_, T>

Claims a slot from the freelist without writing a value.

Always succeeds — grows the slab if needed. The returned Claim must be consumed via Claim::write() to complete the allocation.

This two-phase allocation enables placement new optimization: the value can be constructed directly into the slot memory.

§Example
use nexus_slab::unbounded::Slab;

let slab = Slab::with_chunk_capacity(16);
let claim = slab.claim();
let slot = claim.write(42u64);
assert_eq!(*slot, 42);
// SAFETY: slot was allocated from this slab
unsafe { slab.free(slot) };
Source

pub fn alloc(&self, value: T) -> RawSlot<T>

Allocates a slot and writes the value.

Always succeeds — grows the slab if needed.

Source

pub unsafe fn free(&self, slot: RawSlot<T>)

Frees a slot, dropping the value and returning storage to the freelist.

§Performance

O(n) where n = chunk count, due to chunk lookup. Typically 1-5 chunks.

§Safety
  • slot must have been allocated from this slab
  • No references to the slot’s value may exist
Source

pub unsafe fn take(&self, slot: RawSlot<T>) -> T

Frees a slot and returns the value without dropping it.

§Performance

O(n) where n = chunk count, due to chunk lookup. Typically 1-5 chunks.

§Safety
  • slot must have been allocated from this slab
  • No references to the slot’s value may exist

Trait Implementations§

Source§

impl<T> Debug for Slab<T>

Source§

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

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

impl<T> Default for Slab<T>

Source§

fn default() -> Slab<T>

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

impl<T> SlabStore for Slab<T>

Source§

type Item = T

The type stored in each slot.
Source§

fn alloc(&self, value: T) -> RawSlot<T>

Allocates a slot with the given value. Read more
Source§

unsafe fn free(&self, slot: RawSlot<T>)

Drops the value and returns the slot to the freelist. Read more
Source§

unsafe fn take(&self, slot: RawSlot<T>) -> T

Moves the value out and returns the slot to the freelist. Read more
Source§

unsafe fn free_ptr(&self, ptr: *mut SlotCell<T>)

Returns a slot to the freelist by raw pointer. Read more

Auto Trait Implementations§

§

impl<T> !Freeze for Slab<T>

§

impl<T> !RefUnwindSafe for Slab<T>

§

impl<T> !Send for Slab<T>

§

impl<T> !Sync for Slab<T>

§

impl<T> Unpin for Slab<T>

§

impl<T> UnsafeUnpin for Slab<T>

§

impl<T> UnwindSafe for Slab<T>

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> 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, 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.