2 use crate::sync as public;
10 set_state_to: Cell<State>,
13 #[derive(Clone, Copy, PartialEq, Eq)]
21 struct CompletionGuard<'a> {
22 state: &'a Cell<State>,
23 set_state_on_drop_to: State,
26 impl<'a> Drop for CompletionGuard<'a> {
28 self.state.set(self.set_state_on_drop_to);
32 // Safety: threads are not supported on this platform.
33 unsafe impl Sync for Once {}
37 #[rustc_const_stable(feature = "const_once_new", since = "1.32.0")]
38 pub const fn new() -> Once {
39 Once { state: Cell::new(State::Incomplete) }
43 pub fn is_completed(&self) -> bool {
44 self.state.get() == State::Complete
49 pub fn call(&self, ignore_poisoning: bool, f: &mut impl FnMut(&public::OnceState)) {
50 let state = self.state.get();
52 State::Poisoned if !ignore_poisoning => {
53 // Panic to propagate the poison.
54 panic!("Once instance has previously been poisoned");
56 State::Incomplete | State::Poisoned => {
57 self.state.set(State::Running);
58 // `guard` will set the new state on drop.
60 CompletionGuard { state: &self.state, set_state_on_drop_to: State::Poisoned };
61 // Run the function, letting it know if we're poisoned or not.
62 let f_state = public::OnceState {
64 poisoned: state == State::Poisoned,
65 set_state_to: Cell::new(State::Complete),
69 guard.set_state_on_drop_to = f_state.inner.set_state_to.get();
72 panic!("one-time initialization may not be performed recursively");
81 pub fn is_poisoned(&self) -> bool {
86 pub fn poison(&self) {
87 self.set_state_to.set(State::Poisoned)