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

Перекладено з англійського оригіналу · 06042fa · 2026-10-09 · Читати англійською

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, але ніколи не процес.

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

Кожен контекст володіє одним ProcessHeap: єдиним блоком купи, створеним його першим виділенням і розміром max(min_heap_words, request), плюс ланцюгом фрагментів купи, що належать тому самому процесу. Слова переміщуються лише тоді, коли хост викликає collect() у безпечній точці.

Купа відповідає класичному дизайну ERTS; runtime-heap.md — це її контракт (розкладка, ділянки, розміри, допуск, корені, збирання).

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

Кожен 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});

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

SchedulerService (scheduler.hpp) лише записує життєвий цикл процесів; він не виконує коду.

Ескізи дизайну робочих потоків і процесів містяться в runtime/design/ і runtime/include/{scheduler,process}.hpp. Повідомлення реалізовано (процеси): надсилання копіює повідомлення в купу отримувача й додає його до його вхідної черги сигналів (runtime/include/mailbox.hpp).

Потоки

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

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

RuntimeOptions::standard_output (output.hpp) отримує байти erlang:display/1, а пізніше standard_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::port (портів ще немає, крок плану 53), reference(ReferenceIdentity) і function(FunctionIdentity)TermError::not_implemented
SchedulerService::run / executeSchedulerError::not_implemented
CodeServer::unloadCodeError::not_implemented
dispatch_builtin для каталогізованої BIFStatus::not_implemented