中文 | English
coact (Cooperative Active-object framework) is a header-first C++17
event framework whose active-object and hierarchical state machine model follows
QP/C++ by Quantum Leaps. It targets
single-core MCUs running RT-Thread or FreeRTOS, and the same headers
build and run on Linux and Windows hosts through the Posix and Windows
PALs (host is a test reference, not a product target). Producers submit events
from task or ISR context; one dispatcher thread delivers them to active
objects whose behaviour is a hierarchical state machine. Events replace
threads, transition tables are constexpr, and nothing allocates at run time.
The submission, staging, admission, breaker and PAL layers are coact's own.
Three properties are structural here, not aspirations:
| Property | Where it lives in the tree | How it is checked |
|---|---|---|
| Bounded | every queue, pool and batch size is a compile-time constant; no heap, no new/delete, no dynamic registration |
worst-case flash/RAM and the longest dispatch batch are fixed at link time (test/renode/footprint.sh) |
| Detectable | SubmitResult codes, Monitor counters, Breaker::level(), the fatal_assert handler |
a failure is visible where it happens, with the AO and partition it belongs to |
| Recoverable | one breaker state machine per AO (Normal, BrokenL1, BrokenL2, Safe, Recovering) over static HSMs | recovery has explicit conditions: cooldown, sustained low watermark, successful probe, consecutive healthy windows (examples/safety_supervisor_demo.cpp) |
coact supplies the mechanisms; the board supplies the evidence. Partition
watermarks, watchdog progress and reserve exhaustion are sampled by BSP code
that calls the BreakerBank inputs, as the supervisor example shows.
- C++17 only, no code generator. Transitions are ordinary
constexprtables in your translation unit; no modelling tool sits in the build. - Single core is the design point.
SingleCoreCriticalRingplus an injectedCriticalSection(irq mask on RT-Thread, task critical section / ISR mask on FreeRTOS) keeps the ISR path lock-free and libatomic-free; host SMP is a test reference, not the product target. - Fixed capacity, zero hot-path allocation. A fixed-size
EventPoolrecycled by ref-count lets one event fan out safely (-fno-exceptions -fno-rtti). - RT-Thread and FreeRTOS are first-class targets, not ports. Both PALs use caller-provided static resources and never allocate; Linux and Windows hosts build from the same headers through the same PAL boundary.
- Critical-High staging reservation (this branch):
kHighCriticalReservekeeps High-partition cells free for critical events, plus aReservedNormallane. - Deterministic wakeups. The dispatcher wakes only when idle and a drain-check
closes the missed-wakeup window;
try_submit_from_isrnever blocks. - Back-pressure, not silent drops. A breaker degrades under overload; the low-priority partition ages out instead of starving.
- Coroutines included (
coact/coro/): stackful coroutines,CoroSem, and stack guard/watermark diagnostics.
C can implement everything coact does. The difference is who enforces the constraints: in C, capacity relationships, resource ownership, handle types and cleanup pairing live in comments, naming prefixes and review checklists; in C++17, part of them lives in the type system and in compile-time assertions. coact uses only that subset: no exceptions, no RTTI, no heap, no code generator. Against an equivalent C implementation the cost is about 1 to 2 KiB more flash and roughly the same RAM. The measurements, the cases where C wins and the limits of the approach are in C++17 与 C 的能力差异、成本与使用边界 (Chinese).
flowchart LR
classDef prod fill:#FFE0B2,stroke:#E65100,color:#000
classDef core fill:#BBDEFB,stroke:#0D47A1,color:#000
classDef app fill:#E1BEE7,stroke:#4A148C,color:#000
PR["producer<br/>task / ISR submit"]:::prod
C["Coordinator<br/>submit pipeline"]:::core
S["Staging<br/>High · Normal · Low"]:::core
D["Dispatcher<br/>single thread"]:::core
A["Active Object<br/>+ HSM"]:::app
P[("EventPool<br/>fixed · ref-counted")]:::prod
PR --> C --> S --> D --> A --> P
P -.->|recycle / alloc| PR
flowchart TB
classDef app fill:#E1BEE7,stroke:#4A148C,color:#000
classDef core fill:#BBDEFB,stroke:#0D47A1,color:#000
classDef pal fill:#FFE0B2,stroke:#E65100,color:#000
L4["application<br/>Active Object · HSM · Context"]:::app
L3["core/<br/>Coordinator · Dispatcher · Runtime"]:::core
L2["blocks<br/>staging · event/pool · queue · monitor · policy · coro"]:::core
L1["pal/<br/>RtThread · Posix · Windows"]:::pal
L4 --> L3 --> L2 --> L1
cmake -B build -S . -DCMAKE_BUILD_TYPE=RelWithDebInfo && cmake --build build -j && ctest --test-dir build#include "coact/runtime.hpp"
#include "coact/pal_posix.hpp"
coact::pal::Posix pal;
coact::Runtime<coact::DefaultConfig, coact::pal::Posix> rt(pal);
rt.bind(&my_ao); // my_ao : coact::Ao<Ctx, Hsm, Traits>
rt.initialize();
rt.start();On RT-Thread include the same headers, select coact/pal_rtthread.hpp and compile
src/core/pal_rtthread.cpp into the BSP — the PAL uses caller-provided static
resources and never allocates.
On FreeRTOS select coact/pal_freertos.hpp and compile
src/core/pal_freertos.cpp; FreeRtosResources owns the dispatcher/worker
stacks and every kernel object. The port requires a single-core build with
static allocation enabled; Cortex-M0/M0+ is not supported.
event pool queue hsm ao staging monitor policy coro pal
span, with
coordinator / dispatcher / runtime as the assembly
(docs/interface_contract.md).
Host targets pass under ctest and are TSan-clean on the pool/dispatcher paths;
CI adds ASan/UBSan and a Windows MSVC job, and a weekly or on-demand renode job runs the Cortex-M4 fixtures below. Brought up on RT-Thread under
qemu-vexpress-a9 (single core) and on FreeRTOS under Renode (Cortex-M4 running
the CM3 port), including a fault-injection fixture where IWDG resets a task that
masks interrupts and spins.
The active-object execution model, the pooled-event and reference-count semantics, and the dispatcher loop follow QP/C++ by Quantum Leaps. Quantum Leaps ships SafeQP/C++ (commercial) with certification kits for IEC 61508 and ISO 26262; coact is not a certified product and carries no certification artifacts. coact's own work is the submission pipeline, three-partition staging, admission and breaker policies, the PAL abstraction and the single-core lock-free queues.
MIT — see LICENSE.