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
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 (anything where the optimizer relies on a forbidden-bit-pattern invariant).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.Zeroableis 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.
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.