use core::{
fmt,
panic::{RefUnwindSafe, UnwindSafe},
};
use crate::{
sync::{ExclusiveState, OnceState},
sys::sync as sys,
};
pub struct Once {
inner: sys::Once,
}
impl UnwindSafe for Once {}
impl RefUnwindSafe for Once {}
impl Once {
#[inline]
#[must_use]
pub const fn new() -> Once {
Once {
inner: sys::Once::new(),
}
}
#[inline]
#[track_caller]
pub fn call_once<F>(&self, f: F)
where
F: FnOnce(),
{
if self.inner.is_completed() {
return;
}
let mut f = Some(f);
self.inner.call(false, &mut |_| f.take().unwrap()());
}
#[inline]
pub fn call_once_force<F>(&self, f: F)
where
F: FnOnce(&OnceState),
{
if self.inner.is_completed() {
return;
}
let mut f = Some(f);
self.inner.call(true, &mut |p| f.take().unwrap()(p));
}
#[inline]
pub fn is_completed(&self) -> bool {
self.inner.is_completed()
}
pub fn wait(&self) {
if !self.inner.is_completed() {
self.inner.wait(false);
}
}
pub fn wait_force(&self) {
if !self.inner.is_completed() {
self.inner.wait(true);
}
}
#[inline]
#[allow(unused)]
pub(crate) fn state(&mut self) -> ExclusiveState {
self.inner.state()
}
#[inline]
#[allow(unused)]
pub(crate) fn set_state(&mut self, new_state: ExclusiveState) {
self.inner.set_state(new_state);
}
}
impl fmt::Debug for Once {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Once").finish_non_exhaustive()
}
}
impl Default for Once {
fn default() -> Self {
Self::new()
}
}