[][src]Function moxie::cache

pub fn cache<Arg: ?Sized, Input, Output>(
    arg: &Arg,
    init: impl FnOnce(&Input) -> Output
) -> Output where
    Arg: PartialEq<Input> + ToOwned<Owned = Input>,
    Input: Borrow<Arg> + 'static,
    Output: Clone + 'static, 

Memoizes init at this callsite, cloning a cached Output if it exists and Input is the same as when the stored value was created.

init takes a reference to Input so that the cache can compare future calls' arguments against the one used to produce the stored value.

Example

use moxie::{cache, 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(&epoch.load(Ordering::Relaxed), |_| {
        num_created.fetch_add(1, Ordering::Relaxed);
        CountsClones::default()
    });

    (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);

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: