Clause
← Gesamte Dokumentation

Übersetzt aus dem englischen Original · 06042fa · 2026-10-09 · Auf Englisch lesen

Runtime

clause_runtime ist eine LLVM-freie C++23-Bibliothek. Sie besitzt Kontexte, Prozess-Heaps, Atome, geladene Module und die Verwaltung des Lebenszyklus und führt Erlang-Prozesse auf Scheduler-Workern aus (Prozesse). Alle APIs sind projektintern; Host-Aufrufe müssen pro Runtime serialisiert werden und dürfen sich nicht mit einem Programmlauf überschneiden, dessen Worker sich untereinander synchronisieren (Threads).

Linken

Genau eine für das Ziel gebaute Runtime über Clause::generated_program linken:

add_executable(harness harness.cpp)
target_link_libraries(harness PRIVATE Clause::generated_program)

Das bringt das Archiv, die ABI-/Runtime-Header und C++23 mit, aber nicht LLVM. link_consumer.cpp zeigt einen vollständigen Lebenszyklus.

Lebenszyklus

runtime.hpp:

Abbaureihenfolge: Scheduler-Einträge schließen → Kontexte zerstören → Code-Registrierungen freigeben → Scheduler-Dienst zerstören → Atomtabelle zuletzt. Aufgelöste Funktions-Handles halten Code und Atom-Schreibweisen über den Abbau der Runtime hinaus am Leben, aber nie einen Prozess.

Prozessspeicher

Jeder Kontext besitzt einen ProcessHeap: einen einzigen Heap-Block, der durch seine erste Allokation erzeugt wird und die Größe max(min_heap_words, request) hat, plus eine Kette von Heap-Fragmenten im Besitz desselben Prozesses. Wörter bewegen sich nur, wenn der Host an einem sicheren Punkt collect() aufruft.

Der Heap folgt dem klassischen ERTS-Design; runtime-heap.md ist sein Vertrag (Layout, Bereiche, Größenbemessung, Zulassung, Wurzeln, Speicherbereinigung).

Code-Server und Builtins

Jede Runtime besitzt einen CodeServer (code_server.hpp, callable.hpp):

auto functions = std::make_unique<ModuleRegistry>();
auto added = functions->add("identity", 1,
    [](ProcessContext &, std::span<const Term> args) -> CallResult<Term> { return args.front(); });
auto loaded = context.code_server().load({"native_demo", CodeImage::linked(), std::move(functions)});
auto fn = context.code_server().resolve({.module = "native_demo", .function = "identity", .arity = 1});

Scheduler-Buchführung

SchedulerService (scheduler.hpp) verzeichnet nur den Lebenszyklus von Prozessen; er führt keinen Code aus.

Entwurfsskizzen für Worker und Prozesse liegen in runtime/design/ und runtime/include/{scheduler,process}.hpp. Nachrichten sind umgesetzt (Prozesse): Eine Sendung kopiert die Nachricht in den Heap des Empfängers und hängt sie an seinen Signal-Eingang an (runtime/include/mailbox.hpp).

Threads

Scheduler-Worker (Plan-Step 56, Worker) führen Prozesse auf mehreren Threads einer Runtime aus. Dienste, die sie gemeinsam nutzen, sind synchronisiert; alles andere bleibt auf den Thread beschränkt, der seinen Prozess ausführt, oder wird durch den Mutex des Executors geschützt.

Standardausgabe

RuntimeOptions::standard_output (output.hpp) empfängt erlang:display/1 und später Bytes von standard_io. Der Standard schreibt über C-stdio (gepuffert) auf stdout des Prozesses; eine Host-Senke gibt false zurück, um einen gescheiterten Schreibvorgang zu melden.

erlang:display/1 stellt sein Argument im Anzeigestil dar, schreibt den Text und einen Zeilenumbruch in einem Schreibvorgang und gibt true zurück. Darstellungsgrenzen und abgewiesene Schreibvorgänge werden zu Infrastruktur-Status (resource_limit, output_failure, ...) im geprüften Kanal, nie zu Erlang-Ausnahmen.

Programmstart

CLAUSE_main_v1 (startup.hpp, runtime/src/startup/) führt ein ganzes Programm für das erzeugte main aus: Es prüft die ABI jedes Deskriptors, startet eine Standard-Runtime, registriert alle Module vor jeglichem Einstiegscode, baut argv im Einstiegskontext auf, ruft den Einstiegspunkt auf und bildet das Ergebnis auf den Exit-Status aus ausführbare Dateien ab. Berichte gehen nach dem Leeren von stdout an stderr; Kontext und Runtime werden auf jedem Pfad in Reihenfolge abgebaut. CLAUSE_halt_v1 implementiert erlang:halt/0,1 (abort ruft std::abort auf).

Zurückgestellte Dienste

Diese melden eine Zeile [feature] notimpl (Features) und ändern keinen Zustand:

GrenzeFehler
TermFactory::port (noch keine Ports, Plan-Step 53), reference(ReferenceIdentity) und function(FunctionIdentity)TermError::not_implemented
SchedulerService::run / executeSchedulerError::not_implemented
CodeServer::unloadCodeError::not_implemented
dispatch_builtin auf einem katalogisierten BIFStatus::not_implemented