Crate generic_singleton
source · [−]Expand description
generic_singleton
Rust does NOT monomorphize it’s static generic items. This means you cannot use a generic static item in a generic function. You’ll get the following error:
error[E0401]: can't use generic parameters from outer functionThat’s pretty frustrating when you want to write a singleton pattern that rely’s on a generic parameter. This crate allows for this pattern with minimal runtime overhead.
generic_singleton uses anymap behind the scenes to store a map of each
generic type. The first time you hit the get_or_init macro we initialize the
singleton in thread local storage. Subsequent calls to get_or_init will
retrieve the singleton from the map.
Example
use std::{cell::RefCell, ops::AddAssign};
use num_traits::{One, Zero};
fn generic_call_counter<T: Zero + One + Copy + AddAssign + 'static>() -> T {
let mut count = generic_singleton::get_or_init!(|| RefCell::new(T::zero())).borrow_mut();
*count += T::one();
*count
}
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);
}Current limitations:
- Each thread has a different map. I may add
get_or_init_localandget_or_init_globalif I can figure out how to implement concurrent access and the required trait bound to make it safe.
Re-exports
pub extern crate anymap;Macros
Get a static reference to a generic singleton or initialize it if it doesn’t exist.
Functions
Used by the get_or_init macro to access the generic item from the map. Do not use
directly. Use the get_or_init macro instead.