Skip to documentation
SLOP

alloc_fixed.Monotonic

Reference alloc_fixed Monotonic

Internal implementation documentation

Defined in alloc_fixed.

A stream allocator with a bypass for oversized allocations, used inside an arena that frees everything at once and keeps a large allocation from throwing away the chunk in use.

API (6)

Actions

Public operations.

Fields and members

Public fields and members.

No direct callersNo direct callsalloc_fixedMonotonic
Static calls · unresolved targets: unknown · external targets: unknown.

Source

Source: lib/alloc/fixed/src/fixed.zig:842

zig
/// A stream allocator with a bypass for oversized allocations, used inside an/// arena that frees everything at once and keeps a large allocation from/// throwing away the chunk in use. It refills fixed-capacity chunks of/// `chunk_capacity` bytes from an upstream allocator for ordinary allocations./// A request longer than `chunk_capacity` goes straight to the backing/// allocator, and the active tail chunk stays where it is.////// ### Reclamation and lifetime/// It keeps metadata for the chunk in `current` alone. It has no `reset`,/// `deinit`, or `discard` method. The backing allocator, typically an enclosing/// `std.heap.ArenaAllocator`, reclaims the chunk memory when the owner around/// it is torn down.////// ### Resize behavior/// Shrinking returns `true` at once, leaving the frontier where it was. Growing/// in place looks at `current` alone. Growth returns `false` for memory that/// sits in an earlier chunk or came from the oversized bypass.pub const Monotonic = struct {    /// Upstream allocator that provides the memory for chunks and for oversized    /// allocations.    backing: Allocator,    /// Fixed byte capacity of an ordinary chunk, which sets the length above    /// which a request bypasses the chunk.    chunk_capacity: usize,    /// The fixed buffer chunk in use that ordinary allocations are cut from,    /// which is `null` before the first allocation.    current: ?FixedBuffer = null,    const Self = @This();    /// Starts a `Monotonic` instance with a fixed chunk size to open a stream    /// allocator over an arena the caller already has. It asserts that    /// `chunk_capacity > 0`. It allocates nothing here.    pub fn init(backing: Allocator, chunk_capacity: usize) Self {        std.debug.assert(chunk_capacity > 0);        return .{            .backing = backing,            .chunk_capacity = chunk_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 };    }    /// Confirms whether a given handle is this instance's backing allocator so    /// a caller knows the allocator hands memory to the arena expected to free    /// it. It checks the type-erased state pointer and the vtable pointer,    /// both.    pub fn isBackedBy(self: *const Self, candidate: Allocator) bool {        return self.backing.ptr == candidate.ptr and            self.backing.vtable == candidate.vtable;    }    fn rawAlloc(        context: *anyopaque,        len: usize,        alignment: Alignment,        return_address: usize,    ) ?[*]u8 {        const self: *Self = @ptrCast(@alignCast(context));        if (self.current) |*current| {            if (fits(current, len, alignment)) {                return current.allocator().rawAlloc(                    len,                    alignment,                    return_address,                ) orelse unreachable;            }        }        if (len > self.chunk_capacity) {            return self.backing.rawAlloc(                len,                alignment,                @returnAddress(),            );        }        const chunk_alignment = Alignment.max(alignment, .@"16");        const pointer = self.backing.rawAlloc(            self.chunk_capacity,            chunk_alignment,            @returnAddress(),        ) orelse return null;        self.current = FixedBuffer.init(pointer[0..self.chunk_capacity]);        return self.current.?.allocator().rawAlloc(            len,            alignment,            return_address,        ) orelse unreachable;    }    fn rawResize(        context: *anyopaque,        memory: []u8,        alignment: Alignment,        new_len: usize,        return_address: usize,    ) bool {        if (new_len <= memory.len) return true;        const self: *Self = @ptrCast(@alignCast(context));        if (self.current) |*current| {            if (current.ownsSlice(memory)) {                return current.allocator().rawResize(                    memory,                    alignment,                    new_len,                    return_address,                );            }        }        return false;    }    fn rawRemap(        context: *anyopaque,        memory: []u8,        alignment: Alignment,        new_len: usize,        return_address: usize,    ) ?[*]u8 {        if (new_len <= memory.len) return memory.ptr;        const self: *Self = @ptrCast(@alignCast(context));        if (self.current) |*current| {            if (current.ownsSlice(memory)) {                if (current.allocator().rawRemap(                    memory,                    alignment,                    new_len,                    return_address,                )) |result| return result;            }        }        const result = rawAlloc(            self,            new_len,            alignment,            return_address,        ) orelse return null;        @memcpy(result[0..memory.len], memory);        return result;    }    fn rawFree(        context: *anyopaque,        memory: []u8,        alignment: Alignment,        return_address: usize,    ) void {        const self: *Self = @ptrCast(@alignCast(context));        if (self.current) |*current| {            if (current.ownsSlice(memory)) {                current.allocator().rawFree(                    memory,                    alignment,                    return_address,                );            }        }    }    const vtable: Allocator.VTable = .{        .alloc = rawAlloc,        .resize = rawResize,        .remap = rawRemap,        .free = rawFree,    };};

Source: lib/alloc/fixed/src/root.zig:429

zig
/// To stream allocations inside an arena that will free everything at once,/// `Monotonic` refills fixed-capacity chunks from a backing allocator. An/// oversized allocation bypasses the chunk chain straight to backing storage,/// leaving the active tail chunk in place. Built for growth inside an enclosing/// arena lifetime, the owner has no `reset` and no `discard`, so the arena/// behind it reclaims the memory.pub const Monotonic = fixed.Monotonic;
Called byCallsNo direct callsprivate sourcelib.accy.src.preparation.backendcheckBackendStorageprivate sourcelib.accy.src.preparation.bufferization.passcheckBufferStorageprivate sourcelib.accy.src.preparation.kernelization.loweri...checkBuilderStorageprivate sourcelib.accy.src.preparation.layoutcheckLayoutStorageprivate sourcelib.accy.src.preparation.memorycheckMemoryFailureStorage+6 moreMonotonicallocator
Static calls · unresolved targets: 0 · external targets: 0.
Called byCallsNo direct callsprivate sourcelib.accy.src.preparation.backendcheckBackendStorageprivate sourcelib.accy.src.preparation.bufferization.passcheckBufferStorageprivate sourcelib.accy.src.preparation.kernelization.loweri...checkBuilderStorageprivate sourcelib.accy.src.preparation.layoutcheckLayoutStorageprivate sourcelib.accy.src.preparation.memorycheckMemoryFailureStorage+6 moreMonotonicinit
Static calls · unresolved targets: 0 · external targets: 0.

Complete caller list for Monotonic.allocator

11 direct callers.

Complete caller list for Monotonic.init

11 direct callers.

Audit

Definitions4
Public names4
Members3
Version26.7.0
Revisiondaab053ee433