#static #singleton #generic #global #initialize

generic_singleton

A library crate allowing for generic singleton patterns

4 releases

Uses new Rust 2021

0.3.2 Nov 23, 2022
0.3.1 Sep 16, 2022
0.2.0 Sep 13, 2022
0.1.3 Sep 8, 2022

#935 in Rust patterns

Download history 45/week @ 2022-08-31 61/week @ 2022-09-07 83/week @ 2022-09-14 10/week @ 2022-09-21 15/week @ 2022-09-28 30/week @ 2022-10-05 12/week @ 2022-10-12 16/week @ 2022-10-19 12/week @ 2022-10-26 11/week @ 2022-11-02 17/week @ 2022-11-09 20/week @ 2022-11-16 42/week @ 2022-11-23 15/week @ 2022-11-30

95 downloads per month
Used in 2 crates (via easyfft)

MIT/Apache

12KB
83 lines

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 function

That'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. 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:

  • The map is guarded by an RwLock for thread-safety. This is unnecessary in single-threaded situations.

Dependencies

~0.5–5MB
~78K SLoC