#![no_std]
#![doc = include_str!("../README.md")]
use core::cell::UnsafeCell;
use core::mem::MaybeUninit;
use atomic_polyfill::{AtomicBool, Ordering};
pub struct StaticCell<T> {
used: AtomicBool,
val: UnsafeCell<MaybeUninit<T>>,
}
unsafe impl<T> Send for StaticCell<T> {}
unsafe impl<T> Sync for StaticCell<T> {}
impl<T> StaticCell<T> {
#[inline]
pub const fn new() -> Self {
Self {
used: AtomicBool::new(false),
val: UnsafeCell::new(MaybeUninit::uninit()),
}
}
#[inline]
#[allow(clippy::mut_from_ref)]
pub fn init(&'static self, val: T) -> &'static mut T {
self.init_with(|| val)
}
#[inline]
#[allow(clippy::mut_from_ref)]
pub fn init_with(&'static self, val: impl FnOnce() -> T) -> &'static mut T {
if self
.used
.compare_exchange(false, true, Ordering::Acquire, Ordering::Relaxed)
.is_err()
{
panic!("StaticCell::init() called multiple times");
}
let p: &mut MaybeUninit<T> = unsafe { &mut *self.val.get() };
p.write(val())
}
}