Class CellRegistry¶
Defined in File cell_registry.hpp
Nested Relationships¶
Nested Types¶
Class Documentation¶
-
class CellRegistry¶
Runtime side of the cell table: the current result of each cell. This is the owner of those results: it tracks the live byte total across held slots, enforces fill-once (a non-persistent cell produced twice without an intervening clear is a duplicate producer – a bug, not a legitimate replay), and seeds/publishes persistent cells through a
PersistentValueStoreso they survive across top-level evaluation calls without depending on the scope caches’ own persistence. Bound cells are cleared at the start of every batch of a loop instance they are bound to (the per-batch scratch reset, expressed on cells).Orientation convention, shared with the
CacheManagerscope caches: a cell holds the value in its node’s canonical orientation, and every reader applies that node’s owncanon_phaseonce. A producer therefore storesapply_phase(node, result)–evaluate_implhands back the oriented result, and the phase is an involution – matchingCacheManager::store_and_access(, readerscache.store_and_access(node,
apply_phase(node, rb))
apply_phaseagain, rootsmult_by_phase). Storing the oriented value here instead would double-apply the phase at every read and flip the sign of every value whose canonicalization needed an odd permutation.Public Functions
-
inline explicit CellRegistry(CellTable const &table, CellRegistryHooks hooks = {})¶
-
inline void seed_persistent()¶
Seeds every persistent cell whose canonical hash is currently held by
hooks_.persistentwith the store’s value. A no-op for a cell the store does not (yet) hold, and entirely a no-op whenhooks_.persistentorhooks_.hash_ofis unset. Intended to run once, right after construction, before the first read of this evaluation call (seerun_ordered_schedule_pre_results).
-
inline void set(CellId c, ResultPtr v)¶
Production: overwrites the cell’s current result. Fill-once: a non-persistent cell already holding a value that was neither taken, released nor cleared since (
filled_since_clear) is a duplicate producer – seeCellRegistryHooks::strict_fill_once(throws a namedException, defaulting to theSEQUANT_UT_STRICT_FILL_ONCEenv gate; a plainSEQUANT_ASSERTotherwise). Persistent cells are excluded from this check, exactly asCacheManager::entry::storeexcludes its own persistent entries: they legitimately re-store across batch replays and repeated top-level evaluation calls (e.g. successive CC iterations), often with no table-declared clear between productions. A persistent cell is published tohooks_.persistent(when set) on every production, mirroring what it now holds.
-
inline ResultPtr read(CellId c)¶
A read: the cell’s current result, which stays in the cell for its later readers. Throws if the cell has none.
-
inline ResultPtr take(CellId c)¶
The last read of the cell in its epoch (
ReleasePlan::last_read,ReleasePlan::last_assemble): the reader takes the value over and the registry drops its own reference. Holding on would both pin the memory and make the buffer look shared to the reader that just took it – the same thingCacheManager::entry::access()does at the same point for the scope cache. A later production of the cell is a fresh one. A persistent cell is never given away: for it this isread. Throws if the cell has no result.
-
inline void release(CellId c) noexcept¶
Lets the cell’s result go: the schedule has no reader of it left in this epoch (
ReleasePlan::after). A no-op for a persistent cell and for a cell holding nothing (its last reader took it, or it was not produced this epoch).
-
inline void clear_bound_to(LoopKey const &k)¶
Batch start: drops every cell bound to loop instance
k– the per-batch scratch reset, expressed on cells instead of on a whole scope’s storage. A cell is bound tokeither explicitly (detail::bound_instances:a carriedslicedposition or apartial_overreduction onk) or implicitly, for a non-persistent cell whose own declared home scope’s deepest loop instance isk:the executor re-runs whatever this cell’s tree position computes fresh every batch of that position’s innermost enclosing loop (a step’s own block for a Build; a block-close aggregation for an Assemble), independent of whether the value it holds happens to carrykas a mode or a reduced axis – a “whole” cell unsliced and unsummed on its own home loop is still re-run every batch of it; how long the result is then read for is the release plan’s business. A persistent cell is never cleared here (by definition it is bound to no loop instance – seeTableCell::persistent– so neither check ever matches it; the explicitcontinueis a defensive redundant guard). Aproduce_if_absentcell is the one exception to the implicit rule: it is precisely a cell whose home scope sits inside a loop it is not bound to, and the table says it is produced on first visit and reused on every later batch of that loop (the executor’s Build step skips its production while it is resident), so the implicit “its scope’s innermost
loop is \p k” clear would defeat the flag by dropping it at every batch boundary. Such a cell is cleared only on an instance it is genuinely bound to. Also resets the fill-once mark of every cell it clears: the boundary this crosses is exactly the one
set'sfill-once check must not treat as a duplicate producer across.
-
inline std::size_t live_bytes() const¶
- Returns:
the sum, over every slot currently holding a value (persistent and non-persistent alike), of the
Result::size_in_bytes()it measured when stored. A value that grows while held (a pending view that materializes) is counted at its stored size.
-
template<typename F>
inline void for_each_live(F &&f) const¶ Invokes
f(CellId, ResultPtr const&)for every slot currently holding a value – the registry-side sourceon_peak_livesetwalks once storage moves fully onto the table.
-
inline bool holds(ResultPtr const &value) const¶
- Returns:
whether some slot currently holds
value(pointer identity). Read-only: spends no life.
-
inline bool drained(CellId c) const¶
- Returns:
whether cell
cis a non-persistent cell holding no value: taken by its last reader, released, cleared, or not produced yet. A persistent cell is never given away, so it is never reported as drained even when it happens to hold no value yet (e.g. before its first production this evaluation).
-
inline std::optional<CellId> cell_of(std::size_t vid, CellScope const &scope) const¶
The value’s form visible at
scope, by residency (not exact scope equality) – the table’s own visibility contract, decided by the one shared ruledetail::deepest_visible_formstates (deepest resident form wins; at equal depth the earlier candidate does), which the table builder’s read-source selection uses too. Build cells are offered first, which is how a tie prefers a Build. Leaf cells are not candidates here (seeleaf_cell): a leaf has no scope in this sense.
-
inline explicit CellRegistry(CellTable const &table, CellRegistryHooks hooks = {})¶