Scheduler & phases
In one line: from each system's declared reads/writes, the engine derives the execution graph once and rejects unsafe schedules at build time.
The runtime walks a fixed structure you declare at startup: Track → DAG → Phase → System. Phases (Input / Simulation / Output / Cleanup, or your own) are a DAG-local total order — everything in Input finishes before Simulation starts. Within and across phases, two systems run concurrently unless their access declarations conflict: phases are a contract, not a barrier wall.
Access declarations are the heart of it. Reads<T> / Writes<T> state what a system touches; ReadsFresh<T> wants this tick's value (ordered after the writer), ReadsSnapshot<T> accepts last tick's (runs concurrently with the writer — Versioned-only). Two unordered writers of the same component in the same phase is a build-time error, not a production race. After/Before add explicit edges when you need them.
How it relates
- System — supplies the access declarations the scheduler consumes.
- Runtime — executes the derived graph every tick.
- Storage mode —
ReadsSnapshot<T>requires aVersionedT(history to hand out). - Snapshot isolation — what a snapshot read returns.
In the API
Phase— the built-in phases (Input/Simulation/Output/Cleanup).SystemBuilder— where access and ordering are declared (Reads/Writes/ReadsSnapshot/After/…).
Learn & use
- Narrative: Guide ch.5 §3–4 — declaring access, ordering
- Feature detail: declarative scheduling · track/DAG/phase partitioning · access conflict detection