Skip to main content

FrameStartView

Struct FrameStartView 

Source
pub struct FrameStartView<'a> { /* private fields */ }
Expand description

A borrowing view over a pinned frame-start World: reads are served by reference from the shared &World, writes land in a private per-view overlay that the shared world never sees.

This is docs/effects-spec.md §12.2’s “borrow, don’t copy” primitive (issue #937). It exists for batch-mode stepping, where N flows must each advance against the same frame-start state while their writes stay private until a later, ordered Apply pass. The obvious way to get that is to hand every flow its own frame_start.clone(); the cost of that clone is O(world size) per flow, per turn — every global Value, every visit/turn-count entry — which is nearly free for a scalar toy world and emphatically not free for a real game’s.

FrameStartView pays O(1) to construct and O(cells this flow actually wrote) thereafter. It is observationally identical to stepping against a private clone:

  • a read returns the overlay’s value if this view has written that cell, else the frame-start value — i.e. frame_start ⊕ own writes, exactly what a clone would hold;
  • a write only ever mutates the overlay, so the borrowed &World (and therefore every peer view over it) is untouched;
  • an increment (increment_visit, increment_turn_index) is copy-on-write from that same read-through value, so a flow’s first increment starts from the frame-start count rather than 0.

Because it borrows shared-immutably, many FrameStartViews over one &World can run concurrently — the property bevy-brink’s parallel batch driver needs, and the reason this type takes &World rather than the &mut World ContextView requires. The semantics are those of Mode::Sandbox (every unit treated as flow-private, the shared world read-only), reachable here without a &mut borrow and without a FlowLocal chain — this view has no frozen base and consults no ResolvedPolicy, because every cell is unconditionally overlaid.

The overlay is intentionally not readable back out: the authoritative record of what a flow wrote is the WriteObserver callback stream, which a caller gets by wrapping this view in an ObservedContext. Keeping one changeset record instead of two is what makes the buffered-write Apply pass trivially consistent with what the flow actually observed.

Implementations§

Source§

impl<'a> FrameStartView<'a>

Source

pub fn new(frame_start: &'a World) -> Self

Open a fresh view over frame_start. The overlay starts empty, so every read passes straight through to the borrowed world until this view writes the cell in question.

Trait Implementations§

Source§

impl ContextAccess for FrameStartView<'_>

Source§

fn take_global(&mut self, idx: u32) -> Value

A real core::mem::replace move once the slot is in the overlay — which is what keeps docs/value-model-spec.md §5’s take → make_mut → write-back discipline O(1)-amortized here, exactly as it is against a private clone. The first take of a given slot must still clone out of the borrowed frame-start world (it is shared; this view may not move out of it), but that is one Arc bump for one cell — the same bump a whole-world clone would have paid for that cell up front, and every subsequent take of the slot is a move.

Source§

fn global(&self, idx: u32) -> &Value

Source§

fn set_global(&mut self, idx: u32, value: Value)

Source§

fn visit_count(&self, id: DefinitionId) -> u32

Source§

fn increment_visit(&mut self, id: DefinitionId)

Source§

fn set_visit_count(&mut self, id: DefinitionId, count: u32)

Set a visit count directly, rather than incrementing it. Used by crate::load_state to reconcile a durable save, whose entries carry absolute counts rather than deltas.
Source§

fn turn_count(&self, id: DefinitionId) -> Option<u32>

Source§

fn set_turn_count(&mut self, id: DefinitionId, turn: u32)

Source§

fn turn_index(&self) -> u32

Source§

fn increment_turn_index(&mut self)

Source§

fn set_turn_index(&mut self, index: u32)

Set the turn index directly, rather than incrementing it. Used by crate::load_state to restore a saved turn index.
Source§

fn rng_seed(&self) -> i32

Source§

fn set_rng_seed(&mut self, seed: i32)

Source§

fn previous_random(&self) -> i32

Source§

fn set_previous_random(&mut self, val: i32)

Source§

fn next_random<R: StoryRng>(&self, seed: i32) -> i32

Source§

fn random_sequence<R: StoryRng>(&self, seed: i32, count: usize) -> Vec<i32>

Auto Trait Implementations§

§

impl<'a> Freeze for FrameStartView<'a>

§

impl<'a> RefUnwindSafe for FrameStartView<'a>

§

impl<'a> Send for FrameStartView<'a>

§

impl<'a> Sync for FrameStartView<'a>

§

impl<'a> Unpin for FrameStartView<'a>

§

impl<'a> UnsafeUnpin for FrameStartView<'a>

§

impl<'a> UnwindSafe for FrameStartView<'a>

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.