Function moxie::cache_state [−][src]
pub fn cache_state<Arg: ?Sized, Input, Output>(
arg: &Arg,
init: impl FnOnce(&Input) -> Output
) -> (Commit<Output>, Key<Output>) where
Arg: PartialEq<Input> + ToOwned<Owned = Input>,
Input: Borrow<Arg> + 'static,
Output: 'static,
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