|
tess 1.0.0
Performance-first tile and path simulation substrate
|
#include <tess/experimental/chunk_maintenance.h>
Public Member Functions | |
| ChunkMaintenanceAdapter (World &world, DirtyMask owned_dirty_mask, Rebuild rebuild, std::size_t backend_capacity=0) | |
| ChunkMaintenanceAdapter (const ChunkMaintenanceAdapter &)=delete | |
| auto | operator= (const ChunkMaintenanceAdapter &) -> ChunkMaintenanceAdapter &=delete |
| ChunkMaintenanceAdapter (ChunkMaintenanceAdapter &&)=delete | |
| auto | operator= (ChunkMaintenanceAdapter &&) -> ChunkMaintenanceAdapter &=delete |
| auto | mark_dirty (ChunkKey key, DirtyMask mask, Box3 bounds) -> ChunkMarkResult |
| auto | retry (ChunkKey key) -> std::optional< ScheduleResult > |
| auto | run_some (MaintenanceBudget budget) -> DrainResult |
| auto | flush () -> DrainResult |
| auto | product (ChunkKey key) const -> ChunkProductView< Product > |
| auto | current (ChunkProductToken token) const noexcept -> bool |
| auto | metrics () const noexcept -> MaintenanceMetrics |
| auto | ensure_resident (ChunkKey key) -> ChunkResidencyResult requires(is_sparse) |
| auto | evict (ChunkKey key) -> ChunkEvictionResult requires(is_sparse) |
| auto | reconcile_residency () -> ChunkResidencyStatus requires(is_sparse) |
| auto | try_release () -> ChunkAdapterReleaseResult |
External fixed-slot adapter for one derived product per chunk.
World is borrowed and must outlive this immovable adapter. Product is adapter-owned, while Rebuild is invoked as rebuild(const World&, ChunkKey, DirtyObservation, Product&). A successful callback publishes a content-version/residency token, then clears only the observed bits. The observation may have an empty mask when retry() repairs content-version drift caused by a disjoint owner. If the generation or content version changed, the product remains explicitly stale and the fixed task schedules another pass. Callback exceptions propagate verbatim, leave the owned dirty signal or content-version drift intact, and require the caller to use retry() after inspecting partial product effects.
owned_dirty_mask must be nonzero and disjoint from every other clearing owner for the same world. mark_dirty() rejects zero and foreign bits. It mutates authoritative metadata before offering maintenance, so a capacity failure loses no dirty signal. Scheduling is coalescing; one call does not imply one execution. A disjoint owner may advance the shared content version and stale this product without setting an owned bit; retry() then rebuilds against that content version without clearing the other owner's bits. Failed follow-up admission is retained as adapter-owned retry debt and reoffered by unbounded flush() or explicit retry(), so it cannot produce a false Idle.
Dense slots equal chunk keys. Sparse slots equal the world's fixed resident slots and are rebound only through this adapter at a quiescent boundary. Before ensure_resident(), evict(), or reconcile_residency(), callers close and join every producer, call flush() until it returns a fresh positive Idle, and keep producers closed through the transition. Once a sparse adapter exists, direct world residency mutation is unsupported; reconcile_residency() is the explicit exception for a coordinated archive load or other externally owned transition. A task rechecks resident_ref() before every unchecked sparse access, but that check does not make unsynchronized world mutation safe.
World reads and mutations are not internally synchronized. Concurrent offers are supported by the registered scheduler, but callers must provide the world's documented external synchronization whenever a producer or drain accesses it. Residency and release operations require exclusive adapter access after every producer is closed and joined. Product borrows remain valid until adapter destruction, but sparse slot rebinding may replace their value; copy a needed product before a residency transition.
|
inline |
Allocates fixed task, product, handle, and backend storage, then seals it.
A zero backend_capacity selects the slot count. A smaller capacity is useful only for queue-capacity comparison backends; fixed-registration backends require enough capacity for every adapter slot.
|
inlinenodiscardnoexcept |
Returns whether token still names the current clean slot product.
|
inlinenodiscard |
Makes a sparse key resident at an established quiescent boundary.
The boundary stays open for a batch of adapter-owned residency changes; any later maintenance offer closes it.
|
inlinenodiscard |
Evicts a sparse key at an established quiescent boundary.
|
inlinenodiscard |
Flushes reachable tasks; Idle opens the sparse transition boundary. Adapter retry debt is reoffered around the drain and prevents Idle.
|
inlinenodiscard |
Marks owned dirty bits and offers the corresponding fixed task.
|
inlinenodiscardnoexcept |
Thread-safe monotonic scheduler diagnostics.
|
inlinenodiscard |
Validates and returns one product's content-version/residency token.
|
inlinenodiscard |
Rebinds sparse slots after one coordinated external residency transition.
This is intended for archive load. It is not permission for arbitrary direct world residency mutation while producers or tasks are active. Returns Ready, NotIdle, or Released; reconciliation cannot report Missing because it scans the world's complete resident set.
|
inlinenodiscard |
Reoffers dirty or content-version-stale work without changing world state.
Empty means an out-of-bounds or currently non-resident key, or a released adapter. Capacity and zero-progress outcomes remain explicit.
|
inlinenodiscard |
Runs fixed tasks within budget; world access needs external locking. Adapter retry debt is not reoffered here because a custom backend may execute an accepted offer synchronously outside this budget. Retained debt makes an otherwise completed drain report BudgetExhausted; use retry() or unbounded flush() to reoffer it.
|
inlinenodiscard |
Retires every task after the required fresh positive Idle.
The caller first closes and joins every producer, then keeps exclusive access to this adapter through the Idle observation and release.