pub struct RxDAG<'c>(/* private fields */);
Expand description
The centralized structure which contains all your interconnected reactive values.
This structure is a directed-acyclic-graph (DAG), hence why its called RxDAG. We don’t support computed values recursively depending on each other, which is why it’s acyclic. At the root/top of the DAG are your variables (Var), which you can explicitly set. All other values are CRxs, which are computed. CRx incoming edges are inputs, which are Vars and other CRxs. CRx outgoing edges are outputs, which are more CRxs, but there are also “edges” which just go nowhere, those are side-effects.
§Performance notes
Currently no nodes (Vars or CRxs) are deallocated until the entire DAG is deallocated, so if you keep creating and discarding nodes you will leak memory (TODO fix this?)
§Implementation
Internally this is a vector of interspersed nodes and edges. The edges refer to other nodes relative to their own position. Later Rxs must depend on earlier Rxs. “edges” can have zero outputs, those are side-effects as mentioned above.
When the DAG recomputes, it simply iterates through each node and edge in order and calls [RxDAGElem::recompute]. If the nodes were changed (directly or as edge output), they set their new value, and mark that they got recomputed. The edges will recompute and change their output nodes if any of their inputs got recomputed.
The DAG has interior mutability, in that it can add nodes without a mutable borrow. See elsa crate for why this is sound (though actually the soundness argument is contested). Internally we use a modified version of elsa and stable-deref-trait. which lets us return lifetime-parameterized values instead of references among other things.
Setting Vars is also interior mutability, and OK because we don’t use those values until [RxDAGElem::recompute].
The DAG and refs have an ID so that you can’t use one ref on another DAG, however this is checked at runtime. The lifetimes are checked at compile-time though.
Implementations§
Source§impl<'c> RxDAG<'c>
impl<'c> RxDAG<'c>
Sourcepub fn run_crx<F: FnMut(RxInput<'_, 'c>) + 'c>(&self, compute: F)
pub fn run_crx<F: FnMut(RxInput<'_, 'c>) + 'c>(&self, compute: F)
Run a closure when inputs change, without creating any outputs (for side-effects).
Sourcepub fn new_crx<T: 'c, F: FnMut(RxInput<'_, 'c>) -> T + 'c>(
&self,
compute: F,
) -> CRx<'c, T>
pub fn new_crx<T: 'c, F: FnMut(RxInput<'_, 'c>) -> T + 'c>( &self, compute: F, ) -> CRx<'c, T>
Create a computed value (CRx) in this DAG.
Sourcepub fn new_crx2<T1: 'c, T2: 'c, F: FnMut(RxInput<'_, 'c>) -> (T1, T2) + 'c>(
&self,
compute: F,
) -> (CRx<'c, T1>, CRx<'c, T2>)
pub fn new_crx2<T1: 'c, T2: 'c, F: FnMut(RxInput<'_, 'c>) -> (T1, T2) + 'c>( &self, compute: F, ) -> (CRx<'c, T1>, CRx<'c, T2>)
Create 2 computed values (CRxs) in this DAG which are created from the same function.
Sourcepub fn new_crx3<T1: 'c, T2: 'c, T3: 'c, F: FnMut(RxInput<'_, 'c>) -> (T1, T2, T3) + 'c>(
&self,
compute: F,
) -> (CRx<'c, T1>, CRx<'c, T2>, CRx<'c, T3>)
pub fn new_crx3<T1: 'c, T2: 'c, T3: 'c, F: FnMut(RxInput<'_, 'c>) -> (T1, T2, T3) + 'c>( &self, compute: F, ) -> (CRx<'c, T1>, CRx<'c, T2>, CRx<'c, T3>)
Create 3 computed values (CRxs) in this DAG which are created from the same function.
Sourcepub fn new_crx4<T1: 'c, T2: 'c, T3: 'c, T4: 'c, F: FnMut(RxInput<'_, 'c>) -> (T1, T2, T3, T4) + 'c>(
&self,
compute: F,
) -> (CRx<'c, T1>, CRx<'c, T2>, CRx<'c, T3>, CRx<'c, T4>)
pub fn new_crx4<T1: 'c, T2: 'c, T3: 'c, T4: 'c, F: FnMut(RxInput<'_, 'c>) -> (T1, T2, T3, T4) + 'c>( &self, compute: F, ) -> (CRx<'c, T1>, CRx<'c, T2>, CRx<'c, T3>, CRx<'c, T4>)
Create 4 computed values (CRxs) in this DAG which are created from the same function.
Sourcepub fn new_crx5<T1: 'c, T2: 'c, T3: 'c, T4: 'c, T5: 'c, F: FnMut(RxInput<'_, 'c>) -> (T1, T2, T3, T4, T5) + 'c>(
&self,
compute: F,
) -> (CRx<'c, T1>, CRx<'c, T2>, CRx<'c, T3>, CRx<'c, T4>, CRx<'c, T5>)
pub fn new_crx5<T1: 'c, T2: 'c, T3: 'c, T4: 'c, T5: 'c, F: FnMut(RxInput<'_, 'c>) -> (T1, T2, T3, T4, T5) + 'c>( &self, compute: F, ) -> (CRx<'c, T1>, CRx<'c, T2>, CRx<'c, T3>, CRx<'c, T4>, CRx<'c, T5>)
Create 5 computed values (CRxs) in this DAG which are created from the same function.
Sourcepub fn now(&mut self) -> RxDAGSnapshot<'_, 'c>
pub fn now(&mut self) -> RxDAGSnapshot<'_, 'c>
Recomputes if necessary and then returns an RxContext you can use to get the current value.
Sourcepub fn stale(&self) -> RxDAGSnapshot<'_, 'c>
pub fn stale(&self) -> RxDAGSnapshot<'_, 'c>
Returns an RxContext you can use to get the current value. However any newly-set values or computations will not be returned until RxDAG::recompute is called.