use crate::rt;
pub use crate::rt::thread::AccessError;
pub use crate::rt::yield_now;
use crate::sync::atomic::Ordering;
pub use std::thread::panicking;
use std::fmt;
use std::marker::PhantomData;
pub struct Lazy<T> {
#[doc(hidden)]
pub init: fn() -> T,
#[doc(hidden)]
pub _p: PhantomData<fn(T)>,
}
impl<T: 'static> Lazy<T> {
pub fn get(&'static self) -> &'static T {
match unsafe { self.try_get() } {
Some(v) => v,
None => {
let sv = crate::rt::lazy_static::StaticValue::new((self.init)());
if let Some(v) = unsafe { self.try_get() } {
return v;
}
rt::execution(|execution| {
let sv = execution.lazy_statics.init_static(self, sv);
sv.sync.sync_store(&mut execution.threads, Ordering::AcqRel);
});
unsafe { self.try_get() }.expect("bug")
}
}
}
unsafe fn try_get(&'static self) -> Option<&'static T> {
unsafe fn transmute_lt<'a, 'b, T>(t: &'a T) -> &'b T {
std::mem::transmute::<&'a T, &'b T>(t)
}
let sv = rt::execution(|execution| {
let sv = execution.lazy_statics.get_static(self)?;
sv.sync.sync_load(&mut execution.threads, Ordering::Acquire);
Some(transmute_lt(sv))
})?;
Some(sv.get::<T>())
}
}
impl<T: 'static> fmt::Debug for Lazy<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.pad("Lazy { .. }")
}
}