Experimental Maintenance Scheduling
include/tess/experimental/maintenance.h contains an opt-in experiment for
derived-state maintenance. It does not alter world construction, authoritative
storage, exact event handling, or simulation command execution. The header is
reachable from the compatibility umbrella tess/tess.h so installed consumers
can compile the experiment, but no world or scheduler adopts it implicitly.
Experimental Surface
MaintenanceTaskis a long-lived operation over derived state.MaintenanceBudgetis a shared unit budget for a drain.MaintenanceScheduleris the backend-neutral schedule, run, and explicit flush interface.ImmediateSchedulerexecutes each request synchronously. Self-schedules and A-to-B-to-A requests use an allocation-free iterative trampoline, preserving one execution per request without recursive task entry. A self-schedule that consumes no budget returnsfalseto report that the synchronous backend cannot make progress. A recursive scheduler lock serializes concurrent callers while permitting a running task to schedule itself or another task; each externalschedule()returns only after its own request executes.FifoScheduleris a bounded, non-deduplicating amplification baseline.CoalescingSchedulerretains at most one pending entry per task.MaintenanceMetricsreports schedules, collapsed schedules, executions, and capacity failures.
Queued backends allocate their pointer ring only during construction. A task
must outlive its scheduler or a completed flush(). Destroying a scheduler
with pending tasks drops the non-owning pointers without executing them.
Capacity exhaustion returns false; the authoritative dirty signal must remain
set so the caller can retry. Tasks inspect versions or dirty flags, clear only
the state they actually rebuilt, and may schedule follow-up work when budgeted
work remains. A queued task that successfully schedules any synchronous
follow-up on its executing thread without consuming budget stops that drain
with false instead of allowing direct or cross-task rescheduling to spin
forever. The follow-up remains queued for caller intervention. A schedule call
from another thread is an independent producer and is not attributed to the
running task. Concurrent drain calls and immediate schedule calls are
serialized, so a task never executes against itself. A task may call only
schedule() on a scheduler while it runs; calling run_some() or flush()
reentrantly is outside the contract because queued drains hold their
non-recursive serialization lock.
A queued backend removes an entry before invoking its task. If the task throws, the exception propagates and that queue entry is not restored. The task's authoritative dirty/version state must remain set; after inspecting partial effects, the caller decides whether explicitly scheduling a retry is safe.
Coalescing is not exact-event delivery. Authoritative gameplay events remain on exact queues and simulation phases. Explicit flush points define when a consumer may depend on completed derived state.
Promotion Decision
The prototype remains experimental. It passes correctness, deterministic 1,000-run flush, concurrency, shutdown, and steady-state allocation tests, and it collapses 512 dense schedules to one execution. On the initial local five-repetition run, however, sparse coalescing measured 21,069 ns per 256 distinct tasks versus 517 ns for immediate execution. That fails the required no-more-than-10% sparse overhead gate, so no scheduler hook is integrated into world storage. See the optimization log for retry conditions.