Module arena
A bump arena: an explicit Allocator over one region.
{ Arena } :: import("std/arena");
arena := Arena.new(usize(1024) * usize(1024));
a := arena.allocator();
// … hand `a` to anything that takes an Allocator …
arena.deinit(); // PANICS if a block is still live
Placement, not lifetime: under reference counting every block still dies
when its last reference goes away, and its release is routed back here by
the owner prefix (std/allocator.yo). What the arena adds is where the
bytes live — one contiguous region — and a checked end: deinit (and the
arena handle's own dispose) panics while any block is live, so "the arena
died under a live block" is a loud, defined failure instead of the
use-after-free it is in Zig. A process-lifetime arena calls abandon()
instead: tracking stops and the region is never released.
Freeing a block reclaims its bytes only when it is the most recent
allocation; everything else is reclaimed by deinit. realloc grows the
most recent block in place when the region has room.
Thread-safe: every operation takes the arena's spinlock, so blocks may be freed on any thread.
Under --debug-heap the exit report lists every arena still live (never
deinit) or abandoned at exit, with its live blocks and bytes in use.
Stability
stable — new, allocator, scoped, deinit, abandon, live_blocks,
used_bytes, capacity and is_released, frozen with the Allocator
vtable (plans/archive/EXPLICIT_ALLOCATORS.md).
Types
A bump arena over one region. See the module notes.
Fields
| Name | Type | Description |
|---|---|---|
_state | *(_ArenaState) |
Trait Implementations
impl(Arena, ...)
new : (Arena) fn(capacity : usize) -> ArenaAn arena over a region of capacity bytes (rounded up to 16). Panics
when the region cannot be allocated.
Parameters
| Name | Type | Notes | Description |
|---|---|---|---|
capacity | usize | The region's size in bytes. |
Returns: Arena
allocator : (Arena) fn(self : Arena) -> Allocatorscoped : (Arena) fn(generic(T) self : Arena, f : Impl(Fn() -> T)) -> Twith_allocator(self.allocator(), f): evaluate f() with this arena as
the current allocator.
Parameters
| Name | Type | Notes |
|---|---|---|
self | Arena | |
f | Impl(Fn() -> T) |
Returns: T
live_blocks : (Arena) fn(self : Arena) -> usizeused_bytes : (Arena) fn(self : Arena) -> usizecapacity : (Arena) fn(self : Arena) -> usizeis_released : (Arena) fn(self : Arena) -> booldeinit : (Arena) fn(self : Arena) -> unitRelease the region. PANICS if any block is still live. A second call, or
a call after abandon, is a no-op. Also runs when the last Arena
handle dies.
Parameters
| Name | Type | Notes |
|---|---|---|
self | Arena |
Returns: unit
abandon : (Arena) fn(self : Arena) -> unitStop tracking and never release the region: for an arena that lives as
long as the process (startup tables, interners). Blocks may still be
freed into it; deinit becomes a no-op.
Parameters
| Name | Type | Notes |
|---|---|---|
self | Arena |
Returns: unit
impl(Arena, Dispose(...))
dispose : (Arena) fn(self : Arena) -> unitRelease the resources self owns — a file descriptor, a socket, a lock,
a buffer the allocator handed out. Called automatically when the value's
owner drops it (a value type) or the last reference to it goes away (a
reference type), so an implementor never calls it directly and must
tolerate being the only one who ever does.
It must be safe to run exactly once, and a type that also exposes an
explicit close/release is responsible for making the second call a
no-op.
Parameters
| Name | Type | Notes |
|---|---|---|
self | Arena |
Returns: unit