Skip to main content

BoundedSlab

Struct BoundedSlab 

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

Fixed-capacity slab allocator for manual memory management.

Uses pointer-based freelist for O(1) allocation. ~20-24 cycle operations.

§Safety Contract

Construction is unsafe because it opts you into manual memory management. By creating a slab, you accept these invariants:

  • Free from the correct slab. Passing a Slot to a different slab’s free() is undefined behavior — it corrupts the freelist. In debug builds, this is caught by debug_assert!.
  • Free everything you allocate. Dropping the slab does NOT drop values in occupied slots. Unfreed slots leak silently.
  • Single-threaded. The slab is !Send and !Sync.

§Why free() is safe

The safety contract is accepted once, at construction. After that:

  • Slot is move-only (no Copy, no Clone) — double-free is prevented by the type system.
  • free() consumes the Slot — the handle cannot be used after.
  • Cross-slab misuse is the only remaining hazard, and it was accepted as the caller’s responsibility at construction time.

Implementations§

Source§

impl<T> Slab<T>

Source

pub unsafe fn with_capacity(capacity: usize) -> Slab<T>

Creates a new slab with the given capacity.

§Safety

See struct-level safety contract.

§Panics

Panics if capacity is zero.

Source

pub fn capacity(&self) -> usize

Returns the capacity.

Source

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

Claims a slot from the freelist without writing a value.

Returns None if the slab is full. 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::bounded::Slab;

// SAFETY: caller guarantees slab contract (see struct docs)
let slab = unsafe { Slab::with_capacity(10) };
if let Some(claim) = slab.claim() {
    let slot = claim.write(42u64);
    assert_eq!(*slot, 42);
    slab.free(slot);
}
Source

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

Allocates a slot and writes the value.

§Panics

Panics if the slab is full.

Source

pub fn try_alloc(&self, value: T) -> Result<Slot<T>, Full<T>>

Tries to allocate a slot and write the value.

Returns Err(Full(value)) if the slab is at capacity.

Source

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

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

Consumes the handle — the slot cannot be used after this call. The caller’s safety obligation (free from the correct slab) was accepted at construction time.

Source

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

Frees a slot and returns the value without dropping it.

Consumes the handle — the slot cannot be used after this call.

Trait Implementations§

Source§

impl<T> BoundedStore for Slab<T>

Source§

fn try_alloc(&self, value: T) -> Result<Slot<T>, Full<T>>

Attempts to allocate a slot with the given value. Read more
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> SlabStore for Slab<T>

Source§

type Item = T

The type stored in each slot.
Source§

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

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

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

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

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

Moves the value out and returns the slot to the freelist.

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>
where T: Unpin,

§

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.