Function moxie::cache_with [−][src]
pub fn cache_with<Arg, Input, Output, Ret>(
arg: &Arg,
init: impl FnOnce(&Input) -> Output,
with: impl FnOnce(&Output) -> Ret
) -> Ret where
Arg: PartialEq<Input> + ToOwned<Owned = Input> + ?Sized,
Input: Borrow<Arg> + 'static,
Output: 'static,
Ret: 'static, Expand description
Cache the return of the init function.
If the cache has a stored (Input, Output) for the current topo::CallId
and if arg is equal to the stored Input, marks the value as alive in the
cache and returns the result of calling with on the stored Output.
Otherwise, calls arg.to_owned() to get an Input and calls init to get
an Output. It calls with on the Output to get a Ret value, stores
the (Input, Output) in the cache, and returns Ret.
Example
use moxie::{cache_with, runtime::RunLoop, testing::CountsClones};
use std::sync::atomic::{AtomicU64, Ordering};
let epoch = AtomicU64::new(0);
let num_created = AtomicU64::new(0);
// this runtime holds a single state variable
// which is reinitialized whenever we change `epoch` above
let mut rt = RunLoop::new(|| {
let cached = cache_with(
&epoch.load(Ordering::Relaxed),
|_| {
num_created.fetch_add(1, Ordering::Relaxed);
CountsClones::default()
},
// this makes it equivalent to calling moxie::once(...)
CountsClones::clone,
);
(num_created.load(Ordering::Relaxed), cached.clone_count())
});
for i in 1..1_000 {
let (num_created, num_clones) = rt.run_once();
assert_eq!(num_created, 1, "the first value is always cached");
assert_eq!(num_clones, i, "cloned once per revision");
}
epoch.store(1, Ordering::Relaxed); // invalidates the cache
for i in 1..1_000 {
let (num_created, num_clones) = rt.run_once();
assert_eq!(num_created, 2, "reinitialized once after epoch changed");
assert_eq!(num_clones, i, "cloned once per revision");
}Environment Expectations
This function requires the following types to be visible to illicit::get and will
panic otherwise:
Context