use std::sync::{Mutex, OnceLock};
pub struct Single<T> {
instance: OnceLock<Mutex<T>>,
}
impl<T> Single<T> {
pub const fn new() -> Self {
Self {
instance: OnceLock::new(),
}
}
pub fn get_or_init<F>(&'static self, init: F) -> &'static Mutex<T>
where
F: FnOnce() -> T,
{
self.instance.get_or_init(|| Mutex::new(init()))
}
pub fn get(&'static self) -> Option<&'static Mutex<T>> {
self.instance.get()
}
}
impl<T> Default for Single<T> {
fn default() -> Self {
Self::new()
}
}
unsafe impl<T> Sync for Single<T> where T: Sync {}
#[macro_export]
macro_rules! singleton {
($vis:vis $name:ident: $ty:ty = $expr:expr) => {
use once_cell::sync::Lazy;
use std::sync::Mutex;
$vis static $name: Lazy<Mutex<$ty>> = Lazy::new(|| {
Mutex::new($expr)
});
impl $ty {
$vis fn single() -> &'static Mutex<Self> {
&$name
}
}
};
}