Skip to documentation
SLOP

alloc_phase

Reference alloc_phase

Internal implementation documentation

Overview · API · Code relationships · Verification · Audit

Overview

Package overview

When we design a program that obtains storage before executing recurring work, we must answer three separate concerns: which allocator operations still occur during that work, how bounded input can reuse storage, and what capacity or ownership assumptions are declared and structurally checked. The alloc_phase package supplies independent tools for those questions: runtime phase allocators, reusable input regions, and compile-time capacity declarations. We can use each tool on its own. None of them provides a universal proof of zero process allocation or bounded latency across an entire program.

Within the repository, alloc_phase operates as an internal implementation module. It has no public facade export under tiny.

Runtime phase allocators

To detect allocator calls that arrive after startup, we wrap a caller-supplied backing allocator in a runtime phase guard: SealedPhaseAllocator or ObservingPhaseAllocator. Both wrappers manage state through a separately allocated control block, which can itself fail allocation during initialization. The guard enforces operation permissions at the raw vtable boundary. Initialization permits raw allocation, resizing, remapping, and deallocation. Steady state forbids all four operations. Teardown permits deallocation only. Calling seal advances the guard from initialization to steady state, beginTeardown transitions from steady state to teardown, and abortInitialization transitions directly from a failed initialization to teardown. Callers must free all user allocations before calling deinit, which destroys the control block.

The two runtime wrappers enforce distinct violation policies. SealedPhaseAllocator increments a violation counter and panics before calling the backing allocator, and the call is not forwarded. By contrast, ObservingPhaseAllocator increments the counter, samples up to 16 distinct nonzero return addresses into fixed slots, and forwards the operation to the backing allocator, returning its result or failure. Neither wrapper intercepts operations routed through other allocator handles or standard library calls that return before entering the vtable. While internal atomic scalars protect phase tags and violation counters, this bookkeeping does not drain concurrent in-flight operations or make an arbitrary backing allocator thread-safe. Callers must synchronize phase boundaries and cleanup externally. For implementation details and API signatures, see allocator.zig.

Bounded reusable input storage

For stream and file ingestion, the input.OneRegion container configures a single owned, reusable byte slice. To determine whether an incoming payload fits within a configured limit of n bytes without allocating a secondary buffer, the standard capacity derivation helper deriveCapacity computes n + 1 bytes using checked addition. If a source yields n + 1 bytes, the input exceeds the limit and is rejected. While a custom Capacity.derive function can describe a larger storage size, the standard helper sizes the requirement to n + 1. Calling init allocates this buffer from a caller-supplied allocator, activate enters steady state, and deinit frees the storage using the initialization allocator provided that no borrow remains active. When an input fits within the limit, acquisition grants an exclusive borrow of the slice, which marks the owner busy even when the admitted payload contains zero bytes. Calling release clears the busy state so subsequent operations can reuse the buffer. Lifecycle transitions rely on debug assertions instead of explicit panic enforcement, and this owner exposes neither beginTeardown nor abortInitialization.

An input owner responds to oversized inputs according to its overload policy: a recoverable owner increments a rejection counter and preserves storage for subsequent attempts, while a terminal owner latches a terminal flag and blocks all future reads. Because read operations can consume source bytes or modify buffer contents before reporting an error, recovery indicates permission to reuse the buffer for a future request. Stream framing and transaction management sit with the caller. For files, readFile reads into the bounded buffer for whole-file admission: if an input exceeds the limit, the reader rejects it after reading a bounded prefix rather than consuming the entire file. When inputs exceed buffer capacity, readFileWindow serves bounded portions of larger files. Consumer tools illustrate these boundaries: Glom coordinates windowed reads and parses newline records outside the owner, Issue manages terminal bodies for commands, and Peek decodes image files into external structures using a recoverable buffer. In all cases, the owner manages only its own buffer, leaving decoder, parser, and stream internals to the caller. For the full interface, see input/root.zig.

Capacity declarations and shape verification

The capacity module describes owner shapes and validates declarations at compile time. It classifies owner shapes along two axes: storage source (allocator-backed versus caller-provisioned) and overload interface (exact versus rejecting). An exact classification indicates only that the validator does not require an Exhaustion declaration, which does not guarantee that workloads will always fit or that all methods will succeed. A rejecting classification requires Owner.Exhaustion to be a finite nonempty error set, and at least one non-lifecycle pointer-receiver owner method must return that set directly or return an error union containing it.

A capacity declaration records covered and excluded storage, an expression graph describing sizing formulas, overload policies, risk classifications, obligation keys for external verification, and typed lifecycle bindings. The module also provides checked arithmetic helpers for computing bounds during allocation. Validating a declaration verifies the grammar and type structure of the expression graph: evaluating the formula, proving allocation closure, establishing the truth of bounds, and checking external evidence remain separate verification activities. For the specification grammar and validation rules, see capacity/root.zig.

Definitions

Types and contracts

Public types and contracts.

Namespaces

Public namespaces.

Values and defaults

Public values and defaults.

Code relationships

Direct static dependencies extracted from parsed source by semantic graph analysis.

Uses: tiny.choir, tiny.content, tiny.deadalloc, tiny.glom, tiny.machine, tiny.ui
Used by: tiny.choir, tiny.closure, tiny.sql, tiny.termtex

Verification

No verification records are cataloged for this module in this build.

Audit

EvidenceValue
Sourcelib/alloc/phase/src/root.zig
Definitions147 of 147 documented
Members0 of 317 documented
Public names148 API, 148 indexed
Version26.7.0
Revisiondaab053ee433
Unresolved targets2