Expand description
Cycle executor for [RenderPlan] โ Phase 2 of LOCKLESS.md.
The executor replaces the legacy dynamic scheduler (cycle_tasks,
cycle_task_deps, finished-flag sweeps in engine/runtime.rs) with
count-up dependency counters over an immutable, atomically published plan:
deps_completed[i]is a plain (non-atomic)u64โ only the dispatcher thread mutates it. A node is ready when its counter reachescycle * indegree[i]; exactly one completion ever crosses the threshold.- Per cycle:
cycle += 1, dispatch everything inplan.sources. No counter reset, no memcpy, no scan, no allocation. - Per plan swap (rare, user-driven): the dispatcher pulls the published
plan at cycle start (
ArcSwap::load_full), bumpsepoch, and re-baselinesdeps_completed[i] = cycle * indegree[i]. The old plan always executes to completion; the swap takes effect at the next cycle boundary. Stale completions from the previous plan are dropped viaepoch.
Nodes whose dependencies can never be satisfied (plan.forced, feedback
loops) are dispatched once the task timeout has elapsed since cycle start,
mirroring the legacy !progressed fallback: they run with stale input
data, which is the standard feedback-loop behaviour.
Structsยง
- Cycle
Executor - The single-dispatcher cycle executor. Not
Syncby design: all methods run on the engine dispatcher task. - Force
Outcome - Outcome of
CycleExecutor::force_timeoutsandCycleExecutor::abandon_node. - NodeJob
- A unit of work handed to a worker: execute
nodeofplan.