pub struct Signal<T: Send + Sync + 'static> { /* private fields */ }Expand description
Latest-value state cell with a lock-free synchronous snapshot and a coalesced change feed.
Signal has a two-plane implementation. The data plane (set, set_eventually, update,
and update_eventually) runs on the caller thread: it publishes the ArcSwap mirror, stores
the published sequence, wakes currently parked subscribers, and then returns. The Ractor actor
owns only the control plane: subscribe, unsubscribe, close, and terminal delivery.
changes() is coalesced. Each materialized subscriber keeps only a consumed sequence cursor and
reads the latest global snapshot when pulled; slow subscribers skip intermediate values and
writers are never backpressured. Subscribe has no get-then-subscribe gap: the actor publishes
the new slot-table snapshot before the materialized stream can pull, and the first pull reads
the latest global mirror + published_sequence snapshot.
update uses ArcSwap::compare_and_swap under the write publication turn. The update function
may be re-invoked if a concurrent writer wins the CAS race, matching the usual Ref/atomic
update contract.
Values are stored as immutable Arc<T> snapshots. Datum cannot prevent user-chosen interior
mutability inside T; callers should treat values placed in a Signal as logically immutable.
Implementations§
Source§impl<T: Send + Sync + 'static> Signal<T>
impl<T: Send + Sync + 'static> Signal<T>
Sourcepub fn new(initial: T) -> StreamResult<Self>
pub fn new(initial: T) -> StreamResult<Self>
Create a new signal initialized to initial.
Sourcepub fn get(&self) -> Arc<T> ⓘ
pub fn get(&self) -> Arc<T> ⓘ
Return the current immutable snapshot without sending an actor message.
Sourcepub fn get_cloned(&self) -> Twhere
T: Clone,
pub fn get_cloned(&self) -> Twhere
T: Clone,
Return a cloned value using ArcSwap::load()’s guarded read path.
This avoids cloning the Arc itself on the hot read path. For scalar Copy/cheap-Clone
values, this is the fair equivalent of JVM refs returning the value directly; use
Signal::get when the caller wants an owned snapshot shared by Arc.
Sourcepub fn set(&self, value: T) -> StreamResult<()>
pub fn set(&self, value: T) -> StreamResult<()>
Set the state and return after the value is published to current subscribers.
Sourcepub fn set_eventually(&self, value: T) -> StreamResult<()>
pub fn set_eventually(&self, value: T) -> StreamResult<()>
Set the state on the caller thread.
In the two-plane implementation this publishes before returning; it remains named
set_eventually for API compatibility with the actor-backed first implementation.
Sourcepub fn update<F>(&self, update: F) -> StreamResult<()>
pub fn update<F>(&self, update: F) -> StreamResult<()>
Update the state atomically and return after publication.
The update function may be called more than once if a concurrent writer wins the CAS race.
Sourcepub fn update_eventually<F>(&self, update: F) -> StreamResult<()>
pub fn update_eventually<F>(&self, update: F) -> StreamResult<()>
Update the state atomically on the caller thread.
The update function may be called more than once if a concurrent writer wins the CAS race.
Sourcepub fn close(&self) -> StreamResult<()>
pub fn close(&self) -> StreamResult<()>
Close the signal, re-emitting the current final snapshot to current subscribers before completing them. Post-close subscribers receive the final snapshot and then completion.
Sourcepub fn close_with(&self, final_value: T) -> StreamResult<()>
pub fn close_with(&self, final_value: T) -> StreamResult<()>
Set a final value, then close the signal in one control-plane turn.
Source§impl<T: Clone + Send + Sync + 'static> Signal<T>
impl<T: Clone + Send + Sync + 'static> Signal<T>
Sourcepub fn changes(&self) -> Source<T>
pub fn changes(&self) -> Source<T>
A coalesced source of the current value followed by later snapshots.
Each materialization registers a fresh slot with the control actor. Slow subscribers may skip intermediate values, but always observe the newest pending snapshot and the final snapshot before completion.