Skip to content

Versions and Migration

Current scope

The latest release record is v0.5.0. This site uses that stable version as its baseline while following later master development; capabilities without a stable tag are not version promises. This first English edition does not maintain historical versioned sites.

What to checkSource of truth
Released versions and breaking changesCHANGELOG.md
Recommended migrations from older APIsMIGRATION.md
Build options, compilers, and backendsBUILD.md
Complete current signaturesAPI.md

Moving from bool to _ex

The legacy entry points remain compatible when a caller only needs success or failure. New code that must log, alert, or fall back safely should prefer the diagnostic _ex variants and inspect ExecutorResult::error_code and message.

MigrationUse it when
initialize(config)initialize_ex(config)Configuration, repeated initialization, or post-shutdown failures need distinct causes.
register_realtime_task(...)register_realtime_task_ex(...)You need to distinguish invalid configuration, duplicate names, or platform startup failures.
register_gpu_executor(...)register_gpu_executor_ex(...)You need to distinguish invalid configuration from BackendUnavailable.
wait_for_completion()wait_for_completion_for() / _ex()Waiting must be bounded or timeout status must be recorded.
IRealtimeExecutor::push_task()Executor::try_push_realtime_task()Rejection, backpressure, and failure events must be observable.

_ex is not a second business API that is always superior. Its value is connecting a failure reason to logs, alerts, or a fallback path.

0.3.1: from backend-first to intent-first

New code begins with submit_auto(lambda), then enters a specialist path only when the business explicitly requires independent CPU/GPU implementations, bounded admission, or a long-lived worker lifecycle:

Existing style or requirement0.3.1 recommended entryBoundary that remains unchanged
Ordinary submit(lambda)Gradually adopt submit_auto(lambda)Both return futures; submit() remains the explicit default-pool entry.
One callable branches on a null CPU/GPU streamcpu_gpu_task(cpu, gpu) plus submit_auto()The legacy four-argument overload remains available in 0.3.x without implicit fallback.
Direct lock-free push_task()Register, start, then use dispatch_auto(LowLatency)accepted means admission only; single-consumer and backpressure semantics remain.
Direct real-time push_task()Use dispatch_auto(RealtimeQueue) after startaccepted does not mean a later cycle completed and never falls back to the pool.
Register and start an I/O worker separatelystart_worker(BlockingWorkerSpec)WorkerHandle retains wakeup, stop token, startup timeout, and exit reason.

Automatic routing does not infer callable real-time safety, thread safety, GPU-memory ownership, or I/O interruptibility. get_executor_capabilities() is only an advisory snapshot; each actual submission must still handle stop races and backpressure.

0.5.0: task lifecycle semantics, Android phase one, and hot-path performance

0.5.0 keeps the existing public submission API compatible while promoting task-level cooperative cancellation, cancellable and reschedulable timer handles, the serial execution context, and total bounded admission; Android CPU-only cross-compilation lands in phase one; the P1/P2 stages of the 2026-09 performance audit significantly improve submission throughput and realtime jitter. Release artifacts now include CI-built Linux amd64 debs (full build inside a CUDA devel container) and a Windows x64 static library.

Need0.5.0 entryBoundary you still own
Cancel a queued or running tasksubmit_cancellable* + request_task_cancel()Cancellation is a cooperative request, not preemption; running tasks must check the injected StopToken and return promptly.
Cancellable, reschedulable timerssubmit_delayed/periodic_*_with_handle + TimerHandleExpiry work dispatches to the ordinary pool and does not bind to external event loops (see the interop guide for asio strands).
Strict submit-order settlement on one contextsubmit_on / submit_on_with_handleOrder only; one long task on a context still delays later tasks.
Structured overload rejectionExecutorConfig::max_in_flight_tasksDefaults to 0 (disabled); at the bound the future completes with CapacityExhaustedException and must be handled.
Parse status snapshot textExecutorSnapshot schema 3cancellation/timers fields are additive; parsers asserting column counts must relax.
Android CPU-only cross-compilationNDK r26c/r28b scripts and CIThread priority, affinity, mlockall, and timer slack stay best-effort; no hard realtime promise.

Migration notes for ExecutorSnapshot schema 2 → 3, the process memory-lock lease, and the shutdown cleanup of pending delayed tasks are in the "0.4.0 → 0.5.0" section of MIGRATION.md.

0.4.0: fixed synchronization boundaries and communication observability

0.4.0 moves communication synchronization to construction-time fixed storage and atomic state while retaining the main existing call patterns. New code can choose Topic<T>, phase-bound LET communication, latency percentiles, and real-time allocation diagnostics by data semantics; none of them proves that an application's whole path is real-time safe.

Need0.4.0 entryBoundary you still own
Fan out events independently to ordinary consumerscomm::Topic<T> and TopicSubscription<T>Topic uses a mutex and dynamic allocation; it is not a real-time or lock-free data plane.
Exchange consistent data only at phase boundariesBind PhaseGate, DoubleBuffer, and LatestMailbox to LET phasesOne publish is allowed per phase; reads and writes during a transition, or without prior-phase data, are rejected.
Assess communication latency trendsApproximate p50_latency and p99_latency in CommStatsPercentiles use a fixed histogram and do not replace end-to-end latency measurement.
Detect allocations on a guarded real-time pathRealtimeAllocationGuard and RealtimeThreadConfig::enable_allocation_guardRecording requires an enabled Linux build and guarded path; payload work, clocks, page faults, and scheduling still need whole-path measurement.
Bound completed task-graph handle retentiontask_graph_retention_capacityActive dependencies are not evicted early; an evicted handle explicitly rejects as expired.
Adjust thread-pool worker count onlineThreadPool::resize() / ThreadPoolResizerResizing stays inside the initialized range; validate throughput and convergence latency under target load.

The synchronization core of MpscChannel, RealtimeChannel, unbound DoubleBuffer, PhaseGate, and Sequencer can be checked with is_synchronization_lock_free(). That result covers only component synchronization atomics and fixed storage, not operations on T, callbacks, clocks, page faults, caller allocation, or OS scheduling. Prefer non-waiting APIs, disable high-frequency callbacks, and validate the complete path on target hardware when migrating a real-time path.

Upgrade checklist

  1. Read the target version's CHANGELOG and verify that each used capability exists in that tag.
  2. Reconfigure and build with the target compiler, operating system, and any GPU or real-time permissions.
  3. Keep observation paths for futures, return values, and status counters; use _ex at setup boundaries that need diagnosis.
  4. Recheck real-time affinity, memory locking, timer slack, GPU backend, driver, and device status.
  5. Run tests and tutorial smoke tests, then retest timeout, backpressure, and performance behavior under target load.

Chinese and English guides share the published information architecture. Check translation status whenever a new public page or language counterpart is added.