Watch a logic library on disk and hot-reload it when it changes (the standalone dev loop). More...
#include <pulp/format/reload/reload_transaction.hpp>#include <pulp/format/reload/reload_trust_policy.hpp>#include <pulp/runtime/crypto.hpp>#include <array>#include <atomic>#include <cstddef>#include <cstdint>#include <filesystem>#include <fstream>#include <optional>#include <string>#include <system_error>#include <utility>#include <cerrno>#include <csignal>#include <unistd.h>Go to the source code of this file.
Classes | |
| class | pulp::format::reload::ReloadController |
| struct | pulp::format::reload::ReloadController::Baseline |
| The version the controller compares against: the watched file's mtime and content hash it last acted on (or was seeded with). More... | |
Namespaces | |
| namespace | pulp |
| namespace | pulp::format |
| What the product grants a device: the quota table indexed by capability tier and live thermal state. | |
| namespace | pulp::format::reload |
Functions | |
| bool | pulp::format::reload::staged_pid_is_alive (long pid) |
| void | pulp::format::reload::reap_stale_staged (const std::filesystem::path &dir, const std::string &stem) |
Watch a logic library on disk and hot-reload it when it changes (the standalone dev loop).
The shell drives poll() on a control-thread timer (the standalone app ticks it from its UI/event loop). When the watched logic library's modification time changes — i.e. the developer recompiled it — the controller runs a ReloadSession reload, which gates and (on success) swaps the new DSP into the live slot. Polling mtime is portable and dependency-free; a half-written file is harmless because the transaction's load/fingerprint/contract gates reject it (no swap), and the next completed write (new mtime) is retried.
Each distinct file version is attempted exactly once: the controller records the mtime it acted on whether the reload succeeded or failed, so a candidate that fails its gates is not retried on every tick — only the next edit (a new mtime) triggers another attempt. The first poll() establishes the baseline without reloading (the shell already loaded the initial logic).
CRITICAL — load each version from a UNIQUE path, for TWO independent reasons (do not "simplify" the staging away on the strength of only one):