Clause
← Toda la documentación

Traducido del original en inglés · 1e3a39c8-dirty · 2026-10-26 · Leer en inglés

Runtime

clause_runtime es una biblioteca C++23 sin LLVM. Gestiona los contextos, los heaps de los procesos, los átomos, los módulos cargados y la contabilidad del ciclo de vida, y ejecuta los procesos Erlang en hilos de trabajo del planificador (procesos). Todas las API son internas del proyecto; las llamadas del anfitrión deben serializarse por runtime y no solaparse con una ejecución del programa, cuyos hilos de trabajo se sincronizan entre sí (hilos).

Enlazado

Se enlaza exactamente un runtime compilado para el destino mediante Clause::generated_program:

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

Aporta el archivo, las cabeceras de la ABI y del runtime y C++23, pero no LLVM. link_consumer.cpp muestra un ciclo de vida completo.

Ciclo de vida

runtime.hpp:

Orden de desmontaje: cerrar los registros del planificador → destruir los contextos → liberar los registros de código → destruir el servicio del planificador → la tabla de átomos al final. Los handles de funciones resueltas mantienen vivo el código tras el desmontaje del runtime, pero las palabras de sus ranuras de átomos no fijan ninguna grafía. El almacenamiento de átomos retira sus ranuras globales antes de liberar los registros; acceder a la grafía mediante un Term de átomo no fijo que sobreviva informa de expired_context.

Memoria de los procesos

Cada contexto posee un ProcessHeap (process_heap.hpp); su disposición, áreas, dimensionado, admisión, raíces y recolección se especifican en runtime-heap.md. La API del anfitrión:

Servidor de código y builtins

Cada runtime posee un 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});

Términos persistentes

Una tabla por runtime (memory/persistent_terms), propiedad de Runtime::Impl y accesible mediante ProcessContext::persistent_terms(), guarda los términos de persistent_term (builtins).

Tablas ETS

Un registro por runtime (ets/tables), propiedad de Runtime::Impl y accesible mediante ProcessContext::ets_tables(), guarda las tablas de ets (builtins).

Especificaciones de coincidencia

runtime/src/match_spec/ compila y ejecuta especificaciones de coincidencia como hace erl_db_util.c de OTP, para ets y erlang:match_spec_test/3 (builtins).

Contabilidad del planificador

SchedulerService (scheduler.hpp) es un registro del ciclo de vida de los procesos orientado al anfitrión; no ejecuta código. Los programas se ejecutan en el ejecutor (procesos), que no lo usa.

Hilos

Los hilos de trabajo del planificador (hilos de trabajo) ejecutan procesos en varios hilos de un mismo runtime. Los servicios que comparten están sincronizados; todo lo demás queda confinado al hilo que ejecuta su proceso o protegido por el mutex del ejecutor.

Salida estándar

RuntimeOptions::standard_output (output.hpp) recibe la salida de erlang:display/1 y de io hacia la salida estándar (io). La implementación por defecto escribe en el stdout del proceso mediante stdio de C (con búfer); un receptor del anfitrión devuelve false para informar de una escritura fallida.

erlang:display/1 representa su argumento en estilo display, escribe el texto y un salto de línea en una sola escritura y devuelve true. Los límites de representación y las escrituras rechazadas se convierten en estados de infraestructura (resource_limit, output_failure, ...) en el canal comprobado, nunca en excepciones de Erlang.

Arranque del programa

CLAUSE_main_v1 (startup.hpp, runtime/src/startup/) ejecuta un programa completo para el main generado (ejecutables): comprueba la ABI de cada descriptor, arranca un runtime, registra todos los módulos antes de cualquier código de entrada, construye argv en el contexto de entrada, ejecuta la entrada en el ejecutor y asigna el resultado al estado de salida. Los informes van a stderr después de vaciar stdout; el contexto y el runtime se desmontan en orden en todas las rutas. CLAUSE_halt_v1 implementa erlang:halt/0,1 (abort llama a std::abort).

Servicios diferidos

Estos informan una línea [feature] notimpl (funcionalidades) y no cambian ningún estado:

LímiteError
TermFactory::function(FunctionIdentity)TermError::not_implemented
SchedulerService::run / executeSchedulerError::not_implemented
CodeServer::unloadCodeError::not_implemented
dispatch_builtin en un BIF catalogadoStatus::not_implemented