Function moxie_dom::prelude::cache_state [−][src]
pub fn cache_state<Arg, Input, Output>(
arg: &Arg,
init: impl FnOnce(&Input) -> Output
) -> (Commit<Output>, Key<Output>) where
Arg: PartialEq<Input> + ToOwned<Owned = Input> + ?Sized,
Input: 'static + Borrow<Arg>,
Output: 'static,
Expand description
Root a state variable at this callsite, returning a Key
to the state
variable. Re-initializes the state variable if the capture arg
changes.
Example
use moxie::{cache_state, runtime::RunLoop, testing::BoolWaker};
use std::sync::atomic::{AtomicU64, Ordering};
let epoch = AtomicU64::new(0);
// this runtime holds a single state variable
// which is reinitialized whenever we change `epoch` above
let mut rt = RunLoop::new(|| cache_state(&epoch.load(Ordering::Relaxed), |e| *e));
let track_wakes = BoolWaker::new();
rt.set_state_change_waker(futures::task::waker(track_wakes.clone()));
let (first_commit, first_key) = rt.run_once();
assert_eq!(*first_commit, 0, "no updates yet");
assert!(!track_wakes.is_woken(), "no updates yet");
first_key.set(0); // this is a no-op
assert_eq!(*first_key, 0, "no updates yet");
assert!(!track_wakes.is_woken(), "no updates yet");
first_key.set(1);
assert_eq!(*first_key, 0, "update only enqueued, not yet committed");
assert!(track_wakes.is_woken());
let (second_commit, second_key) = rt.run_once(); // this commits the pending update
assert_eq!(*second_key, 1);
assert_eq!(*second_commit, 1);
assert_eq!(*first_commit, 0, "previous value still held by previous pointer");
assert!(!track_wakes.is_woken(), "wakes only come from updating state vars");
assert_eq!(first_key, second_key, "same state variable");
// start the whole thing over again
epoch.store(2, Ordering::Relaxed);
let (third_commit, third_key) = rt.run_once();
assert_ne!(third_key, second_key, "different state variable");
// the rest is repeated from above with slight modifications
assert_eq!(*third_commit, 2);
assert!(!track_wakes.is_woken());
third_key.set(2);
assert_eq!(*third_key, 2);
assert!(!track_wakes.is_woken());
third_key.set(3);
assert_eq!(*third_key, 2);
assert!(track_wakes.is_woken());
let (fourth_commit, fourth_key) = rt.run_once();
assert_eq!(*fourth_key, 3);
assert_eq!(*fourth_commit, 3);
assert_eq!(*third_commit, 2);
assert!(!track_wakes.is_woken());
assert_eq!(third_key, fourth_key);
Environment Expectations
This function requires the following types to be visible to illicit::get
and will
panic otherwise:
Context