Clause
← Уся документація

Перекладено з англійського оригіналу · 1e3a39c8-dirty · 2026-10-26 · Читати англійською

Runtime

clause_runtime — це бібліотека на C++23 без LLVM. Вона володіє контекстами, купами процесів, атомами, завантаженими модулями й обліком життєвого циклу та виконує процеси Erlang на робочих потоках планувальника (процеси). Усі API внутрішні для проєкту; виклики з боку хоста мають бути серіалізовані для кожного runtime й не перекриватися з виконанням програми, чиї робочі потоки синхронізуються між собою (потоки).

Компонування

Скомпонуйте рівно один runtime, зібраний для цілі, через Clause::generated_program:

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

Він приносить архів, заголовки ABI/runtime і C++23, але не LLVM. link_consumer.cpp показує повний життєвий цикл.

Життєвий цикл

runtime.hpp:

Порядок завершення: закрити записи планувальника → знищити контексти → звільнити реєстрації коду → знищити сервіс планувальника → таблицю атомів останньою. Дескриптори розв’язаних функцій утримують код після завершення runtime, але слова їхніх слотів атомів не утримують написання. Сховище атомів виводить глобальні слоти з ужитку до звільнення записів; доступ до написання через збережений Term нефіксованого атома повертає expired_context.

Пам'ять процесу

Кожен контекст володіє одним ProcessHeap (process_heap.hpp); його розкладку, ділянки, розміри, допуск, корені й збирання описано в runtime-heap.md. API хоста:

Сервер коду й вбудовані функції

Кожен runtime володіє одним 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});

Постійні терми

Одна таблиця на runtime (memory/persistent_terms), яка належить Runtime::Impl і доступна через ProcessContext::persistent_terms(), зберігає терми persistent_term (вбудовані функції).

Таблиці ETS

Один реєстр на runtime (ets/tables), що належить Runtime::Impl і доступний через ProcessContext::ets_tables(), зберігає таблиці ets (вбудовані функції).

Специфікації зіставлення

runtime/src/match_spec/ компілює й виконує специфікації зіставлення так, як erl_db_util.c в OTP, для ets і erlang:match_spec_test/3 (вбудовані функції).

Облік планувальника

SchedulerService (scheduler.hpp) — це запис життєвого циклу процесів для хоста; він не виконує коду. Програми виконуються на виконавці (процеси), який його не використовує.

Потоки

Робочі потоки планувальника (робочі потоки) виконують процеси на кількох потоках одного runtime. Служби, які вони ділять, синхронізовано; усе інше лишається в межах потоку, що виконує свій процес, або захищене м'ютексом виконавця.

Стандартний вивід

RuntimeOptions::standard_output (output.hpp) отримує вивід erlang:display/1 та io у стандартний вивід (io). Типова реалізація пише в stdout процесу через C stdio (буферизовано); приймач хоста повертає false, щоб повідомити про невдалий запис.

erlang:display/1 відображає свій аргумент у стилі display, пише текст і переведення рядка одним записом і повертає true. Обмеження відображення й відхилені записи стають статусами інфраструктури (resource_limit, output_failure, ...) у перевіреному каналі, ніколи не винятками Erlang.

Запуск програми

CLAUSE_main_v1 (startup.hpp, runtime/src/startup/) виконує цілу програму для згенерованого main (виконувані файли): він перевіряє ABI кожного дескриптора, запускає runtime, реєструє всі модулі до будь-якого коду точки входу, будує argv у контексті точки входу, виконує точку входу на виконавці й відображає результат на статус виходу. Звіти йдуть у stderr після скидання stdout; контекст і runtime демонтуються по порядку на кожному шляху. CLAUSE_halt_v1 реалізує erlang:halt/0,1 (abort викликає std::abort).

Відкладені служби

Вони повідомляють один рядок [feature] notimpl (можливості) і не змінюють стану:

МежаПомилка
TermFactory::function(FunctionIdentity)TermError::not_implemented
SchedulerService::run / executeSchedulerError::not_implemented
CodeServer::unloadCodeError::not_implemented
dispatch_builtin для каталогізованої BIFStatus::not_implemented