generic_singleton

Macro get_or_init_thread_local

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

Same as the get_or_init! macro but using thread local storage. Similar to the thread_local! macro API, we use a closure that yields a mutable reference to your struct. The closure ensures the reference cannot escape to a different thread.

ยงExample

use num_traits::{One, Zero};
use std::cell::Cell;
use std::ops::AddAssign;

fn generic_call_counter<T: Zero + One + Copy + AddAssign + Send + 'static>() -> T {
    let mut output = T::zero();
    generic_singleton::get_or_init_thread_local!(|| Cell::new(T::zero()), |count_cell| {
        let mut count = count_cell.get();
        count += T::one();
        count_cell.set(count);
        output = count;
    });
    output
}

fn main() {
    // Works with usize
    assert_eq!(generic_call_counter::<usize>(), 1);
    assert_eq!(generic_call_counter::<usize>(), 2);
    assert_eq!(generic_call_counter::<usize>(), 3);

    // Works with i32
    assert_eq!(generic_call_counter::<i32>(), 1);
    assert_eq!(generic_call_counter::<i32>(), 2);
    assert_eq!(generic_call_counter::<i32>(), 3);

    // Works with f32
    assert_eq!(generic_call_counter::<f32>(), 1.0);
    assert_eq!(generic_call_counter::<f32>(), 2.0);
    assert_eq!(generic_call_counter::<f32>(), 3.0);
}