Landin library reference discuss source

core/arena

Shared: available on every enabled target.

A monotonic allocator over caller-supplied bytes.

over fills the caller's arena.space, declared zeroed beside the backing, and returns the handle, an arena.arena, from it; over_unchecked takes local backing with an explicit lifetime opt-out, and the caller ends every allocation before that backing ends. An individual free reclaims nothing, and reset gives every allocation back at once; used counts the bytes handed out, padding included. The arena resizes its latest block in place and moves any other. It allocates no backing of its own.

Items

Executable example

This complete program is maintained in the repository runtime tests. View source.

import core/arena
import core/mem

exercise: () -> (ok: bool) ! mem.out_of_memory =
    ok = false
    mut backing: [32]u8 = zeroed
    mut space: arena.space = zeroed
    memory := arena.over_unchecked(space, addr backing[0], 32)
    address := try mem.allocate(memory, usize(4), usize(1))
    address.val = 42
    return when address.val <> 42
    _ = mem.allocate(memory, usize(64), usize(1)) else (problem)
        _ = problem
        return when arena.used(memory) <> 4
        arena.reset(memory)
        again := try mem.allocate(memory, usize(32), usize(1))
        ok = arena.used(memory) == 32 and again == address
        return
    end
end exercise

public main: () -> (code: i32) =
    code = 1
    ok := exercise() else false
    if ok then
        code = 42
    end if
end main

arena type

public arena: type = arena_value

core/arena/arena.ldn:31

Monotonic allocator over caller-owned bytes, as a handle: copies share one arena. Individual frees do not reclaim space; only the most recent allocation can grow in place, or give back its tail when it is resized smaller, and a resize that cannot grow in place moves the block to a new allocation, leaving the old bytes spent. Zero-byte requests may consume alignment padding. reset gives every allocation back at once, the arena's one free that reclaims anything.

space type

public space: type = arena_state

core/arena/arena.ldn:17

Caller-owned state of an arena: its extent and the bytes it has handed out. Declare it zeroed beside the backing and give it to over, which fills it; it must outlive the arena handle.

over function

public over: (inout state: space, escaping base: ptr mut u8, size: usize)
             -> (handle: arena from state, base)

core/arena/arena.ldn:39

Fill state for an arena over retainable backing and return its handle, without allocating. The range must stay valid for the arena and all allocations made through it.

The independent allocator result may be retained after this call. Only backing which the caller may itself retain can enter the checked arena.

over_unchecked function

public over_unchecked: (inout state: space, base: ptr mut u8, size: usize)
                       -> (handle: arena from state, base)

core/arena/arena.ldn:52

Fill state for an arena over local backing with an explicit lifetime opt-out and return its handle. The caller must end every allocated view before that backing ends.

Explicit lifetime opt-out for a local extent. The handle still keeps its tracked origins, but allocations do not; users must end every allocation before the backing ends, including allocations retained by helpers.

reset function

public reset: (memory: arena) -> none

core/arena/arena.ldn:66

Give every allocation of the arena back at once: the next allocation starts at its base again. Every block it gave is then free, and a program that still uses one has the same obligation as after free.

used function

public used: (memory: arena) -> (count: usize)

core/arena/arena.ldn:59

Return consumed arena bytes, including alignment padding.