7个不稳定版本 (3个破坏性更新)
0.5.0 | 2023年6月8日 |
---|---|
0.4.1 | 2023年1月12日 |
0.3.2 | 2022年11月23日 |
0.3.1 | 2022年9月16日 |
0.1.3 | 2022年9月8日 |
#2174 in Rust模式
每月754次下载
在2个crate中使用(通过easyfft)
21KB
184 行
generic_singleton
Rust不对其静态泛型项进行单态化。这意味着您不能在泛型函数中使用静态泛型项。您将获得以下错误
error[E0401]: can't use generic parameters from outer function
当您想要编写依赖于泛型参数的单例模式时,这非常令人沮丧。这个crate允许以最小的运行时开销来实现这种模式。
generic_singleton
在幕后使用anymap存储每个泛型类型的映射。第一次调用get_or_init
宏时,我们将初始化单例。随后的get_or_init
调用将从映射中检索单例。
示例
use std::{ops::AddAssign, sync::RwLock};
use num_traits::{One, Zero};
fn generic_call_counter<T: Zero + One + Copy + AddAssign + Send + Sync + 'static>() -> T {
let mut count = generic_singleton::get_or_init!(|| RwLock::new(T::zero())).write().unwrap();
*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);
}
线程局部变体
上述示例的缺点是需要一个RwLock
来确保围绕内部AnyMap的同步。在单线程情况下,我们可以移除此锁,并使用get_or_init_thread_local!
宏直接提供可变引用。这以牺牲易用性为代价,需要您以闭包的形式表达您的逻辑,而不是简单地返回一个引用。
依赖关系
~0.4–6MB
~12K SLoC