alloc_fixed.Chunks
Internal implementation documentation
Defined in alloc_fixed.
A chunked allocator that builds a result across several allocations and then either commits backing chunks to an outer owner through retain() or invokes upstream frees for rollback through discard().
API (7)
Actions
Public operations.
allocator: Returns a borrowedstd.mem.Allocatorhandle pointing atselfto pass to code that allocates.discard: Rolls back an uncommitted transaction after failure by freeing all tracked chunks to the backing allocator in reverse order.init: Starts aChunksinstance to open an allocation transaction over an allocator the caller already has.isAllocator: Reports whether a given handle came from aChunksinstance, allowing a caller to allocate straight into an open transaction when handed one.retain: Commits every tracked chunk to the upstream backing owner and clears tracking metadata when work succeeds.
Types and contracts
Public types and contracts.
maximum_chunk_count: Number of chunk descriptors tracked at one time, fixed at 64 to cap how many chunks one instance holds at a time.
Fields and members
Public fields and members.
Source
Source: lib/alloc/fixed/src/fixed.zig:286
zig
/// A chunked allocator that builds a result across several allocations and/// then either commits backing chunks to an outer owner through `retain()` or/// invokes upstream frees for rollback through `discard()`. It requests/// chunks from an upstream backing allocator as needed, tracking at most 64/// chunk descriptors simultaneously in an array fixed at compile time./// Initializing an instance performs no initial backing allocation, acquiring/// chunks only as requests demand them.////// ### Growth schedule and capacity bounds/// Fresh chunks follow a growth schedule that starts at `initial_capacity`,/// doubles after each successful fresh chunk, and stops growing at/// `maximum_capacity`. Each fresh chunk has `@max(scheduled_capacity, len)`/// bytes, so requests larger than `maximum_capacity` are allowed but need/// both a free descriptor and a successful backing allocation. Because/// doubling calculations use the scheduled capacity rather than the actual/// requested length, oversized requests do not advance the growth progression/// faster. The `maximum_capacity` parameter caps the growth schedule itself/// rather than limiting individual request sizes or total storage.////// Calling `retain()` clears this descriptor table without freeing backing/// memory, so committed chunks no longer occupy slots in the table and more/// than 64 total chunks can be allocated across successive retain cycles. The/// upstream lifetime owner must reclaim that committed memory. When an/// allocation fails, the failure stems either from the backing allocator/// returning `null` or from exhausting the 64 descriptor slots. Both/// conditions return an allocation failure to the caller.////// ### Transaction discipline/// - Calling `retain()` commits every chunk it holds to the backing lifetime/// owner, such as an enclosing `std.heap.ArenaAllocator`./// - Calling `retain()` clears the descriptor tracking without freeing the/// backing memory./// - A chunk that was retained can no longer be freed through/// `Chunks.discard()`./// - Calling `discard()` frees every tracked chunk in reverse order back to the/// upstream allocator and puts the growth schedule back at/// `initial_capacity`.////// ### Resize behavior/// In `rawResize`, shrinking returns `true` at once without consulting the/// active chunk buffer, leaving the bump frontier where it was. Growing in/// place looks at the active tail chunk alone, `self.current()`. A slice/// allocated in an earlier chunk cannot grow in place.pub const Chunks = struct { /// Internal chunk storage holding the buffer descriptors and the growth /// state that the methods work through. The owner maintains it, so a caller /// accesses storage through `retain` and `discard` and takes no copy of it /// and makes no direct changes. inner: ChunkStorage, const Self = @This(); /// Number of chunk descriptors tracked at one time, fixed at 64 to cap how /// many chunks one instance holds at a time. pub const maximum_chunk_count = ChunkStorage.maximum_chunk_count; /// Starts a `Chunks` instance to open an allocation transaction over an /// allocator the caller already has. It asserts that `initial_capacity > 0` /// and that `maximum_capacity >= initial_capacity`. It allocates nothing /// here: chunks are requested from the backing allocator as they are /// needed. pub fn init( backing: Allocator, initial_capacity: usize, maximum_capacity: usize, ) Self { return .{ .inner = .init( backing, initial_capacity, maximum_capacity, ) }; } /// Returns a borrowed `std.mem.Allocator` handle pointing at `self` to pass /// to code that allocates. The `self` instance stays alive at one memory /// address while the handle is in use. pub fn allocator(self: *Self) Allocator { return .{ .ptr = self, .vtable = &vtable }; } /// Reports whether a given handle came from a `Chunks` instance, allowing a /// caller to allocate straight into an open transaction when handed one. It /// compares the candidate's vtable pointer against the `Chunks` vtable. pub fn isAllocator(candidate: Allocator) bool { return candidate.vtable == &vtable; } /// Commits every tracked chunk to the upstream backing owner and clears /// tracking metadata when work succeeds. It sets the chunk descriptor count /// to zero without freeing any backing memory. It leaves the current growth /// schedule, `next_capacity`, as it is. Once retained, the backing memory /// can no longer be freed through `Chunks.discard()`, and reclaiming it /// belongs to the upstream backing owner. pub fn retain(self: *Self) void { self.inner.retain(); } /// Rolls back an uncommitted transaction after failure by freeing all /// tracked chunks to the backing allocator in reverse order. This /// invalidates any allocations residing in those chunks and resets /// `next_capacity` to `initial_capacity`. Chunks committed by an earlier /// call to `retain()` are untouched and remain allocated. Actual physical /// reuse of the freed memory depends on the free policy of the backing /// allocator. pub fn discard(self: *Self) void { self.inner.discard(); } fn rawAlloc( context: *anyopaque, len: usize, alignment: Alignment, return_address: usize, ) ?[*]u8 { const self: *Self = @ptrCast(@alignCast(context)); return self.inner.allocate(.retained, len, alignment, return_address); } fn rawResize( context: *anyopaque, memory: []u8, alignment: Alignment, new_len: usize, return_address: usize, ) bool { const self: *Self = @ptrCast(@alignCast(context)); return self.inner.resize(memory, alignment, new_len, return_address); } fn rawRemap( context: *anyopaque, memory: []u8, alignment: Alignment, new_len: usize, return_address: usize, ) ?[*]u8 { const self: *Self = @ptrCast(@alignCast(context)); return self.inner.remap( .retained, memory, alignment, new_len, return_address, ); } fn rawFree( context: *anyopaque, memory: []u8, alignment: Alignment, return_address: usize, ) void { const self: *Self = @ptrCast(@alignCast(context)); self.inner.free(.retained, memory, alignment, return_address); } const vtable: Allocator.VTable = .{ .alloc = rawAlloc, .resize = rawResize, .remap = rawRemap, .free = rawFree, };};Source: lib/alloc/fixed/src/root.zig:407
zig
/// `Chunks` builds a result across several allocations, committing backing/// chunks to an outer owner through `retain()` or invoking upstream frees for/// rollback through `discard()`.////// Fresh chunks requested from the backing allocator follow a growth schedule/// that starts at `initial_capacity`, doubles after each successful fresh/// chunk, and stops growing at `maximum_capacity`, with each fresh chunk/// sized to `@max(scheduled_capacity, len)`. Requests larger than the/// scheduled size are permitted without altering the doubling calculation,/// but can fail from exhausted descriptor slots or backing allocation/// failure.////// The owner tracks at most 64 chunk descriptors simultaneously. Calling/// `retain()` clears the descriptor table without freeing backing memory,/// leaving committed storage for the upstream lifetime owner to reclaim.pub const Chunks = fixed.Chunks;Audit
| Definitions | 7 |
|---|---|
| Public names | 7 |
| Members | 1 |
| Version | 26.7.0 |
| Revision | daab053ee433 |