pub struct Arena { /* private fields */ }Expand description
One leased buffer from a ArenaPool. Send + Sync.
Allocations are bump-pointer on an atomic cursor: each call to
Arena::alloc CAS-advances the cursor and returns a fresh
aligned slice carved out of the buffer at the old position. 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.
Concurrent calls to Arena::alloc on the same &Arena are
supported and produce disjoint slices (the CAS loser retries
against the new cursor). See the module docs for the full
concurrency contract.
Implementations§
Source§impl Arena
impl Arena
Sourcepub fn alloc_count(&self) -> u32
pub fn alloc_count(&self) -> u32
Number of allocations performed so far.
Sourcepub fn alloc_count_exceeded(&self) -> bool
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.
Sourcepub fn alloc<T>(&self, count: usize) -> Result<&mut [T]>where
T: Zeroable,
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 forT. This rules outNonZeroU8/NonZeroU16/…/references/function pointers/ niche-optimised enums.align_of::<T>() <= MAX_ALIGN— checked at compile time via aconstassertion. The pool buffer’s base pointer is aligned to [MAX_ALIGN] (= 64 bytes); per-Talignment is then a relative-offset adjustment of the bump cursor.- The arena does not run destructors on allocated values, so
Tshould not have meaningfulDropglue.
Concurrency: the bump cursor is advanced via a CAS loop,
so concurrent alloc calls on the same &Arena produce
disjoint slices. The CAS loser retries against the new
cursor; in the uncontended case the cost is a single relaxed
load plus one successful CAS. Crucially, no alloc call
re-borrows the whole buffer (the typed pointer is derived
from the cached raw base pointer), so concurrent allocators
cannot invalidate each other’s previously-returned slices
under stacked borrows.
Sourcepub fn reset(&mut self)
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.