Macro get_or_init

Source
macro_rules! get_or_init {
    ($init:expr) => { ... };
}
Expand description

Get a static reference to a generic singleton or initialize it if it doesn’t exist.

§Example

use std::collections::HashMap;
use std::ops::{Deref, DerefMut, Mul};
use std::sync::RwLock;

// The expensive function we're trying to cache using a singleton map, however,
// we want the user of the function to determine the type of the elements being
// multiplied.
fn multiply<T: Mul<Output = T>>(a: T, b: T) -> T {
    a * b
}

fn multiply_with_cache<T: Mul<Output = T> + Send>(a: T, b: T) -> T
where
    T: std::cmp::Eq,
    T: Copy,
    T: Sync + 'static,
    (T, T): std::hash::Hash,
{
    // This is a generic singleton map!!!
    let map = generic_singleton::get_or_init!(|| RwLock::new(HashMap::new()));
    let key = (a, b);
    if map.read().unwrap().contains_key(&key) {
        *map.read().unwrap().get(&key).unwrap()
    } else {
        let result = multiply(a, b);
        map.write().unwrap().insert(key, result);
        result
    }
}

fn main() {
    // This call will create the AnyMap and the HashMap<i32> and do the multiplication
    multiply_with_cache::<u32>(10, 10);
    // This call will only retrieve the value of the multiplication from HashMap<i32>
    multiply_with_cache::<u32>(10, 10);

    // This call will create a second HashMap< and do the multiplication
    multiply_with_cache::<i32>(-1, -10);
    // This call will only retrieve the value of the multiplication from HashMap
    multiply_with_cache::<i32>(-1, -10);
}