Skip to documentation
SLOP

tiny.mprompt

Reference tiny.mprompt

Overview · API · Code relationships · Verification · Audit

Overview

The package lets a Zig function stop partway through, hand control back to an earlier point on the call stack, and later continue from where it stopped, with a value passed in. Capturing a running computation's stack segment and resuming it later gives the package delimited continuations, and on top of them typed algebraic effect handlers. It has two layers: functions with the C calling convention that pass raw pointers, and a typed Zig API whose value types the compiler checks. The runtime keeps each thread's running computations, cached stacks and handlers in per-thread state.

Generators, workers that wait for their next request, backtracking searches, and interpreters that pause to ask their host for a value all need a computation that stops in the middle and continues later. The code that started such a computation needs to learn whether it finished or paused, and then continue it once, continue it more than once, or abandon it.

A paused computation needs every frame between the pause and its starting point kept alive, with its locals and return addresses, and an ordinary call stack discards those frames when the function returns. Continuing twice from one pause needs the frames as they were at the pause, and running the rest of the computation the first time overwrites them. Each paused computation needs a stack of its own, and programs hold many at once: a test keeps 16 workers paused, and the profiling workload runs 10,000. So an idle stack has to cost little memory, and a busy one has to stay within a bound. Moving from one stack to another means saving and restoring the processor's registers, which takes code written for each processor.

Daan Leijen's paper Implementing Algebraic Effects in C and his libmprompt library, from the Koka project, implement multi-prompt delimited continuations and algebraic effect handlers. The package keeps libmprompt's execution model: code runs on stacks of its own, suspends to a marked point, and resumes through a handle, and handlers move control the same way. The package's reference benchmark reruns libmprompt's reference workloads at release sizes, and a test runs the effect counter at the upstream debug workload size.

Each resumable computation runs on a stack of its own, a stacklet, reserved at a fixed size (8 MiB by default) with an unmapped gap at each end, and its pages become usable only as the stack grows into them. The runtime marks the point where a computation enters its stacklet as the computation's prompt, the computation suspends back to that point, and the stacklet keeps the suspended frames as they were. Suspending hands back a handle to the suspended computation, a resumption. Resuming the resumption makes the suspending call return the value passed in. One form is a resumption that runs once (one-shot): it returns control to the point where the computation suspended, and the computation continues on the same stacklet with no copy. The other form is a resumption that may run more than once (multi-shot): it keeps a reference count, and the runtime saves the stacklet's segments to the heap and restores them when it needs to, so the handle can resume again and again. Duplicating such a handle adds one reference and copies no stack memory at that moment. The Zig API keeps ownership explicit: run and SuspendedRun keep the body's result where the caller reads it, and a caller that abandons a paused run drops its handle. The Zig API has the compiler check the type of every value that crosses between stacks, and error unions pass through unchanged. Stacklet memory is bounded: the process takes stacklets from shared pool regions of at most 32,000 blocks each, 256 GiB of address space by default, and each thread keeps at most four freed stacklets for reuse by default. The stack switch exists for x86_64 and aarch64 targets other than Windows, and the package compiles only for 64-bit targets, because every stacklet reserves address space of its own.

Definitions

Actions

Public operations.

Types and contracts

Public types and contracts.

Namespaces

Public namespaces.

Code relationships

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

Uses: tiny.bench, tiny.hypothesis, tiny.sys
Used by: None

Verification

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

Audit

EvidenceValue
Sourcelib/mprompt/src/root.zig
Definitions37 of 37 documented
Members0 of 0 documented
Public names37 API, 78 indexed
Version26.7.0
Revisiondaab053ee433