pub struct SubcomposeState { /* private fields */ }Expand description
Tracks the state of nodes produced by subcomposition, enabling reuse between measurement passes.
Implementations§
Source§impl SubcomposeState
impl SubcomposeState
Sourcepub fn new(policy: Box<dyn SlotReusePolicy>) -> Self
pub fn new(policy: Box<dyn SlotReusePolicy>) -> Self
Creates a new SubcomposeState using the supplied reuse policy.
Sourcepub fn set_policy(&mut self, policy: Box<dyn SlotReusePolicy>)
pub fn set_policy(&mut self, policy: Box<dyn SlotReusePolicy>)
Sets the policy used for future reuse decisions.
pub fn set_reusable_pool_limits(&mut self, per_type: usize, untyped: usize)
Sourcepub fn register_content_type(&mut self, slot_id: SlotId, content_type: u64)
pub fn register_content_type(&mut self, slot_id: SlotId, content_type: u64)
Registers a content type for a slot.
Stores the content type locally for efficient pool-based reuse lookup, and also delegates to the policy for compatibility checking.
Call this before subcomposing an item to enable content-type-aware slot reuse.
Sourcepub fn update_content_type(
&mut self,
slot_id: SlotId,
content_type: Option<u64>,
)
pub fn update_content_type( &mut self, slot_id: SlotId, content_type: Option<u64>, )
Updates the content type for a slot, handling optional content types.
If content_type is Some(type), registers the type for the slot.
If content_type is None, removes any previously registered type.
This ensures stale types don’t drive incorrect reuse.
Sourcepub fn get_content_type(&self, slot_id: SlotId) -> Option<u64>
pub fn get_content_type(&self, slot_id: SlotId) -> Option<u64>
Returns the content type for a slot, if registered.
Sourcepub fn begin_pass(&mut self)
pub fn begin_pass(&mut self)
Starts a new subcompose pass.
Call this before subcomposing the current frame so the state can track which slots are active and dispose the inactive ones later.
Sourcepub fn active_slot_cursor(&self) -> usize
pub fn active_slot_cursor(&self) -> usize
Returns the current active slot cursor for the in-progress pass.
Sourcepub fn restore_active_slot_cursor(&mut self, cursor: usize)
pub fn restore_active_slot_cursor(&mut self, cursor: usize)
Restores the active slot cursor for work that should not become part of the rendered active set, such as lazy-list prefetch measurement.
Sourcepub fn recycle_active_slot(&mut self, slot_id: SlotId) -> Vec<NodeId> ⓘ
pub fn recycle_active_slot(&mut self, slot_id: SlotId) -> Vec<NodeId> ⓘ
Moves an active slot out of the rendered set and into the reusable pool.
pub fn recycle_prefetched_active_slot(&mut self, slot_id: SlotId) -> Vec<NodeId> ⓘ
pub fn recycle_active_slots_where( &mut self, predicate: impl FnMut(SlotId) -> bool, ) -> Vec<NodeId> ⓘ
Sourcepub fn finish_pass(&mut self) -> Vec<NodeId> ⓘ
pub fn finish_pass(&mut self) -> Vec<NodeId> ⓘ
Finishes a subcompose pass, disposing slots that were not used.
Sourcepub fn get_or_create_slots(&mut self, slot_id: SlotId) -> Rc<SlotsHost>
pub fn get_or_create_slots(&mut self, slot_id: SlotId) -> Rc<SlotsHost>
Returns the SlotsHost for the given slot ID, creating a new one if it doesn’t exist. Each slot gets its own isolated slot table, avoiding cursor-based conflicts when items are subcomposed in different orders.
Sourcepub fn callback_holder(&mut self, slot_id: SlotId) -> CallbackHolder
pub fn callback_holder(&mut self, slot_id: SlotId) -> CallbackHolder
Returns the latest callback holder for the given slot, creating one if needed.
Sourcepub fn has_pending_precompositions(&self, slot_id: SlotId) -> bool
pub fn has_pending_precompositions(&self, slot_id: SlotId) -> bool
Whether precomposed nodes are waiting to be consumed for this slot. A pending precomposition means the retained mapping is about to be superseded, so clean-slot reuse must reject and compose.
Sourcepub fn retained_capture_key_matches<K: PartialEq + 'static>(
&self,
slot_id: SlotId,
key: &K,
) -> bool
pub fn retained_capture_key_matches<K: PartialEq + 'static>( &self, slot_id: SlotId, key: &K, ) -> bool
Whether the slot’s stored capture key equals key. A missing key never
matches: a slot must compose at least once under the key discipline
before it may skip.
Sourcepub fn store_retained_capture_key<K: PartialEq + 'static>(
&mut self,
slot_id: SlotId,
key: K,
)
pub fn store_retained_capture_key<K: PartialEq + 'static>( &mut self, slot_id: SlotId, key: K, )
Records the capture key the slot is being composed under.
Sourcepub fn register_active(
&mut self,
slot_id: SlotId,
node_ids: &[NodeId],
scopes: &[RecomposeScope],
)
pub fn register_active( &mut self, slot_id: SlotId, node_ids: &[NodeId], scopes: &[RecomposeScope], )
Records that the nodes in node_ids are currently rendering the provided
slot_id.
Sourcepub fn register_precomposed(&mut self, slot_id: SlotId, node_id: NodeId)
pub fn register_precomposed(&mut self, slot_id: SlotId, node_id: NodeId)
Stores a precomposed node for the provided slot. Precomposed nodes stay
detached from the tree until they are activated by register_active.
Sourcepub fn take_node_from_reusables(
&mut self,
slot_id: SlotId,
) -> Option<(NodeId, bool)>
pub fn take_node_from_reusables( &mut self, slot_id: SlotId, ) -> Option<(NodeId, bool)>
Returns the node that previously rendered this slot, if it is still considered reusable, and whether it was REBOUND — taken from another slot, so its retained subtree is about to show different content. An exact-slot reactivation hands the same item its own subtree back and is not a rebinding.
Lookup order:
- Exact slot match in the appropriate pool (not a rebinding)
- Any policy-compatible node from the same content-type pool
- Fallback to untyped pool with policy compatibility check
Sourcepub fn dispose_or_reuse_starting_from_index(
&mut self,
start_index: usize,
) -> Vec<NodeId> ⓘ
pub fn dispose_or_reuse_starting_from_index( &mut self, start_index: usize, ) -> Vec<NodeId> ⓘ
Moves active slots starting from start_index to the reusable bucket.
Returns the list of node ids that were DISPOSED (not just moved to reusable).
Nodes that exceed max_reusable_per_type are disposed instead of cached.
Sourcepub fn active_slots_count(&self) -> usize
pub fn active_slots_count(&self) -> usize
Returns the number of slots currently active (in use during this pass).
This reflects the slots that were activated via register_active() during
the current measurement pass.
Sourcepub fn reusable_slots_count(&self) -> usize
pub fn reusable_slots_count(&self) -> usize
Returns the number of reusable slots in the pool.
These are slots that were previously active but are now available for reuse by compatible content types.
Sourcepub fn invalidate_scopes(&self)
pub fn invalidate_scopes(&self)
Invalidates all tracked subcomposition scopes.
Hosts should call this when parent-captured inputs change without directly invalidating the child scopes themselves. The next subcompose pass will then re-run active slot content instead of skipping with stale captures. Invalidating scopes alone is not a reliable “recompose on next measure” signal: the recomposer drains invalid scopes before measure runs, re-executing the RETAINED slot callbacks — parent-captured values baked into a replaced closure never flow in, yet the scopes come back valid. The generation bump is the unlaunderable half: only a measure-time compose of the slot brings it current, so clean-slot reuse stays blocked until the new content actually landed.
Sourcepub fn bump_content_generation(&self)
pub fn bump_content_generation(&self)
Advances the content generation without invalidating scopes: every slot must re-compose once before clean-slot reuse may skip it again. Called when the owning node leaves its parent — a retained subtree that comes back from the reuse pool restarts its effects only if its slots actually recompose, and scope flags carry no durable trace of the detach (deactivation walks stop at nested slot-host boundaries).
Sourcepub fn slot_content_generation_current(
&self,
slot_id: SlotId,
owner_epoch: u64,
) -> bool
pub fn slot_content_generation_current( &self, slot_id: SlotId, owner_epoch: u64, ) -> bool
Whether the slot last composed under the current content generation
and owner-chain deactivation epoch. False after any
Self::invalidate_scopes, and false after any composition up the
owner chain was deactivated, until a measure-time compose of this
slot runs.
Sourcepub fn mark_slot_composed_current(&mut self, slot_id: SlotId, owner_epoch: u64)
pub fn mark_slot_composed_current(&mut self, slot_id: SlotId, owner_epoch: u64)
Records that the slot just composed under the current generation and the given owner-chain deactivation epoch.
Sourcepub fn was_last_slot_reused(&self) -> Option<bool>
pub fn was_last_slot_reused(&self) -> Option<bool>
Returns whether the last slot registered via Self::register_active was reused.
Returns Some(true) if the slot already existed (was reused from pool or
was recomposed), Some(false) if it was newly created, or None if no
slot has been registered yet this pass.
This is useful for tracking composition statistics in lazy layouts.
Sourcepub fn precomposed(&self) -> &HashMap<SlotId, Vec<NodeId>>
pub fn precomposed(&self) -> &HashMap<SlotId, Vec<NodeId>>
Returns a snapshot of precomposed nodes.
Sourcepub fn drain_inactive_precomposed(&mut self) -> Vec<NodeId> ⓘ
pub fn drain_inactive_precomposed(&mut self) -> Vec<NodeId> ⓘ
Removes any precomposed nodes whose slots were not activated during the current pass and returns their identifiers for disposal.