Skip to main content

Store

Struct Store 

Source
pub struct Store<T: 'static> { /* private fields */ }
Expand description

A Copy, process-lifetime handle to one observable value.

Implementations§

Source§

impl<T: 'static> Store<T>

Source

pub fn new(value: T) -> Store<T>

A process-lifetime store, leaked so the handle stays Copy (the property that makes a Signal pleasant to pass). Create once (a thread_local! + accessor fn is the idiom); the scoped owner arrives with the persistence container.

Source

pub fn with_untracked<R>(self, f: impl FnOnce(&T) -> R) -> R

Source

pub fn update(self, label: &'static str, f: impl FnOnce(&mut T))

Mutate the whole value; announces a store-wide change (every reader wakes).

Source

pub fn version(self) -> u64

Bumped on every write; a cheap way for tests to ask “did anything change”.

Source

pub fn store_id(self) -> u64

This store’s root id, the first component of every path under it. A persistence container keys its table map on it.

Source

pub fn pump(self) -> usize

Announce everything background transactions committed, returning how many paths were queued. An app posts this to the main loop after a worker commits; a test calls it directly and asserts what it woke.

Source§

impl<T: Send + Sync + 'static> Store<T>

Source

pub fn transact(self) -> Tx<T>

Open a write transaction: the way a background thread edits. Holding it holds the store’s write lock, so a reader never sees half of one; dropping it commits and queues the announcements for Store::pump.

Source§

impl<T: Identified + 'static> Store<Keyed<T>>

Source

pub fn elem(self, key: impl Into<ModelId<T>>) -> Elem<T>

One element, addressed by its id: a ModelId, a raw handle from Store::keys, an integer key, a Uuid, or a string key all convert. O(1), because the collection keeps a handle→index map.

Source

pub fn keys(self) -> Vec<u64>

Tracked read of the collection’s shape (which keys, in what order): what a list widget wants. A field write does not wake it; an insert, a removal or a reorder does.

Source

pub fn ids(self) -> Vec<ModelId<T>>

Store::keys, typed — the same tracked read, as ModelIds.

Source

pub fn restructure( self, label: &'static str, op: Op, key: impl Into<ModelId<T>>, f: impl FnOnce(&mut Keyed<T>), )
where T: Clone,

Structural change: insert, remove, reorder.

The affected key and the operation are announced alongside the shape path, because a persistence layer has to choose between an INSERT and a DELETE and cannot infer it from “the shape changed”, while the UI, which only re-reads keys(), ignores both.

Source

pub fn push(self, item: T)
where T: Clone,

Append item: the Store::restructure insert, announced under its own key.

Source

pub fn remove(self, key: impl Into<ModelId<T>>) -> bool
where T: Clone,

Remove the row with key: the Store::restructure delete. Returns false, announcing nothing, when no such row exists.

Source

pub fn move_row(self, from: usize, to: usize) -> bool
where T: Clone,

Move the row at index from to index to, the shape a native list’s reorder gesture reports. Returns false, announcing nothing, when the move is out of range or in place.

Source

pub fn next_key(self) -> u64

The next free integer key: one past the largest in use, for a model keyed by a u64 field. Untracked. See Keyed::next_key.

Source

pub fn merge_row( self, key: impl Into<ModelId<T>>, value: T, changed: &[&'static str], ) -> bool
where T: Clone,

Feed one row’s new value from outside the app’s own editing (another connection’s committed write arriving through a persistence container, an import), replacing the stored value and announcing each label in changed as that field’s Set. The announcement is precise: readers of the named fields wake, along with everything coarser, where a wholesale Store::update wakes only readers of the store itself. The announcements carry no values (a background transaction’s shape) and the current author tag; wrap the call in with_author so consumers can tell the merge from the user’s own edits. Returns false, announcing nothing, when the row is absent: an absent row is an insert, which is Store::restructure’s job.

Source

pub fn write_field<V: Clone + 'static>( self, key: impl Into<ModelId<T>>, label: &'static str, value: V, ) -> bool
where T: ApplyField,

Write one field by label: front-door semantics (announced at the field’s own path, prior/new values captured while a consumer wants them, undoable, persisted) without the generated accessor in scope. The relation machinery writes foreign keys and order values through this; it is public because any framework-level maintenance faces the same need. Returns false, announcing nothing, when the row is absent or when label/V name no field of T (the ApplyField downcast refused).

Source

pub fn populate(self, rows: Vec<T>)

Insert-or-replace rows without announcing: the persistence layer faulting stored rows into its cache. No change record is born (sinks, undo and autosave all stay quiet: the rows are the database’s own contents arriving, not edits), and no trigger wakes: a faulting read populates before anything binds, so there is nobody to wake yet. The version still bumps, so version-watching tests see the population.

Source

pub fn depopulate(self, key: impl Into<ModelId<T>>) -> bool

Remove one row without announcing: the persistence layer evicting a clean cached row. The row is not deleted anywhere; it stops being resident, and a later fault brings it back. Callers guard with Store::is_observed: evicting a row something is bound to would flip that binding to its Default with no wakeup to correct it.

Source

pub fn depopulate_many(self, keys: &[u64]) -> usize

Store::depopulate, batched: One retain and one reindex for the whole set, where per-key removal would rebuild the key map per row, the difference between an eviction pass costing O(cache) and O(cache × evicted). Returns how many rows left.

Source

pub fn is_observed(self, key: impl Into<ModelId<T>>) -> bool

Whether anything currently observes this element: a trigger on the element’s own path, or on any path under it (a bound field, a nested struct). The eviction guard: a row nobody observes can leave the cache silently, because the next reader faults it back.

Trait Implementations§

Source§

impl<T> Clone for Store<T>

Source§

fn clone(&self) -> Self

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl<T> Copy for Store<T>

Source§

impl<T: Send + Sync> Send for Store<T>

Source§

impl<T: 'static> Source<T> for Store<T>

Source§

fn path(self) -> Path

The path this source occupies. Implementations revalidate against the interner, so the result is always current.
Source§

fn node(self) -> NodeId

This source’s interned id, so a child can be built with no lookup of its own. Read more
Source§

fn components(self, out: &mut Vec<u64>)

The path as plain components, resolved by walking the handle chain rather than the interner. This is what crosses a thread boundary: a worker names what it changed with components, and the main thread re-establishes them on its own side when it announces.
Source§

fn with_value_untracked<R>(self, f: impl FnOnce(Option<&T>) -> R) -> R

Source§

fn update_value(self, f: impl FnOnce(&mut T)) -> bool

Returns false when the value is gone (a deleted row), in which case nothing is announced either.
Source§

fn bump_version(self)

Source§

const DYNAMIC: bool = false

Whether this source’s location can change over the handle’s lifetime: a recycled list slot whose current row rotates. Fields projected from a dynamic source resolve their path through the source on every operation instead of trusting the one cached at projection time, and their tracked reads also run Source::track_extra.
Source§

fn track_extra(self)

Extra tracking a projected field’s tracked reads perform. A dynamic source tracks its own rebind signal here, so a control bound at build follows the slot to its next row.
Source§

fn with<R>(self, f: impl FnOnce(Option<&T>) -> R) -> R

Tracked read of the whole value: the coarse subscription.
Source§

impl<T: Send + Sync> Sync for Store<T>

Auto Trait Implementations§

§

impl<T> Freeze for Store<T>

§

impl<T> RefUnwindSafe for Store<T>

§

impl<T> Unpin for Store<T>

§

impl<T> UnsafeUnpin for Store<T>

§

impl<T> UnwindSafe for Store<T>

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> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. 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> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

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

Source§

type Error = Infallible

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.