use std::marker::PhantomData;
use std::mem::MaybeUninit;
use std::sync::Once;
use crate::sync_unsafe_cell::SyncUnsafeCell;
use crate::token::TokenWrapper;
pub struct Static<T, Token> {
value: SyncUnsafeCell<MaybeUninit<T>>,
init_once: Once,
initializer: fn() -> T,
_token: PhantomData<fn(Token) -> Token>,
}
impl<T, Token: TokenWrapper> Static<T, Token> {
#[doc(hidden)]
pub const fn new(initializer: fn() -> T) -> Self {
Self {
value: SyncUnsafeCell::new(MaybeUninit::uninit()),
init_once: Once::new(),
initializer,
_token: PhantomData,
}
}
#[inline]
pub fn init(&self) -> Token {
self.init_once.call_once(|| {
let value = unsafe { self.value.get_mut() };
value.write((self.initializer)());
});
unsafe { Token::new() }
}
#[doc(hidden)]
#[inline]
pub unsafe fn get_value(&self) -> &T {
let value = unsafe { self.value.get() };
unsafe { value.assume_init_ref() }
}
}