Skip to main content

Arena

Struct Arena 

Source
pub struct Arena { /* private fields */ }
Expand description

One leased buffer from an ArenaPool.

Allocations are bump-pointer: each call to Arena::alloc carves out a fresh aligned slice from the head of the buffer. There is no per-allocation header and no individual free — the entire arena is reset (returned to the pool) only when the Arena is dropped.

Arena is !Send + !Sync because its bump cursor is a Cell and its buffer cell is Cell<Option<Buffer>> (not synchronised). This is fine for the round-1 single-threaded decoder path. The sibling sync::Arena uses AtomicUsize for the cursor and a Mutex around the buffer slot to regain Send + Sync.

Implementations§

Source§

impl Arena

Source

pub fn capacity(&self) -> usize

Capacity of this arena in bytes.

Source

pub fn used(&self) -> usize

Bytes consumed by allocations so far.

Source

pub fn alloc_count(&self) -> u32

Number of allocations performed so far.

Source

pub fn alloc_count_exceeded(&self) -> bool

true once the per-arena allocation-count cap has been reached. Decoders that produce many small allocations should poll this and bail with Error::ResourceExhausted when it flips, instead of waiting for the next Arena::alloc call to fail.

Source

pub fn alloc<T>(&self, count: usize) -> Result<&mut [T]>
where T: Zeroable,

Allocate count Ts out of this arena. Returns a borrowed &mut [T] (lifetime bounded by the borrow of self).

The returned slice points at zero-filled bytes (the pool zero-fills on initial allocation and again whenever a buffer is returned). The Zeroable bound on T guarantees that an all-zero bit pattern is a valid value for T, so reading the slice without first writing it is sound. The intended pattern is still “decoder fills the slice, then reads back what it wrote” — but unwritten bytes will read back as T::zeroed() rather than as UB.

Returns Error::ResourceExhausted if either the per-arena byte cap or the per-arena allocation-count cap would be exceeded.

§Type bounds
  • T: bytemuck::Zeroable — pool buffers are zero-filled, so handing back &mut [T] over those bytes is only sound when the all-zero bit pattern is valid for T. This rules out NonZeroU8/NonZeroU16/…/references/function pointers/ niche-optimised enums (anything where the optimizer relies on a forbidden-bit-pattern invariant).
  • align_of::<T>() <= MAX_ALIGN — checked at compile time via a const assertion. The pool buffer’s base pointer is aligned to [MAX_ALIGN] (= 64 bytes); per-T alignment is then a relative-offset adjustment of the bump cursor.
  • The arena does not run destructors on allocated values, so T should not have meaningful Drop glue. Zeroable is automatically implemented only for types where this is the case (primitives, [T; N] of zeroable, #[derive(Zeroable)] on POD structs).

Aliasing model: the bump cursor is monotonically non-decreasing, so successive alloc calls return slices covering disjoint regions of the underlying buffer. The returned typed pointer is derived from the arena’s cached raw base pointer (base.as_ptr().add(offset)), never from a re-borrow of the whole buffer — that’s what keeps previously returned &mut [T] slices valid under stacked borrows. This is the standard arena-allocator pattern (cf. bumpalo::Bump::alloc_slice_*) and is the reason this method takes &self rather than &mut self.

Source

pub fn reset(&mut self)

Reset the arena to empty without releasing its buffer to the pool. Useful for a decoder that wants to reuse the same arena across several intermediate stages of the same frame. Callers must ensure no slice previously returned from Arena::alloc is still in use — Rust’s borrow checker enforces this, since reset takes &mut self.

Trait Implementations§

Source§

impl Drop for Arena

Source§

fn drop(&mut self)

Executes the destructor for this type. Read more

Auto Trait Implementations§

§

impl !Freeze for Arena

§

impl !RefUnwindSafe for Arena

§

impl !Send for Arena

§

impl !Sync for Arena

§

impl Unpin for Arena

§

impl UnsafeUnpin for Arena

§

impl UnwindSafe for Arena

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.