std/sys/sync/once/
no_threads.rs1use crate::cell::Cell;
2use crate::sync as public;
3use crate::sync::once::OnceExclusiveState;
4
5pub struct Once {
6 state: Cell<State>,
7}
8
9pub struct OnceState {
10 poisoned: bool,
11 set_state_to: Cell<State>,
12}
13
14#[derive(Clone, Copy, PartialEq, Eq)]
15enum State {
16 Incomplete,
17 Poisoned,
18 Running,
19 Complete,
20}
21
22struct CompletionGuard<'a> {
23 state: &'a Cell<State>,
24 set_state_on_drop_to: State,
25}
26
27impl<'a> Drop for CompletionGuard<'a> {
28 fn drop(&mut self) {
29 self.state.set(self.set_state_on_drop_to);
30 }
31}
32
33unsafe impl Sync for Once {}
35
36impl Once {
37 #[inline]
38 pub const fn new() -> Once {
39 Once { state: Cell::new(State::Incomplete) }
40 }
41
42 #[inline]
43 pub const fn new_complete() -> Once {
44 Once { state: Cell::new(State::Complete) }
45 }
46
47 #[inline]
48 pub fn is_completed(&self) -> bool {
49 self.state.get() == State::Complete
50 }
51
52 #[inline]
53 pub(crate) fn state(&mut self) -> OnceExclusiveState {
54 match self.state.get() {
55 State::Incomplete => OnceExclusiveState::Incomplete,
56 State::Poisoned => OnceExclusiveState::Poisoned,
57 State::Complete => OnceExclusiveState::Complete,
58 _ => unreachable!("invalid Once state"),
59 }
60 }
61
62 #[inline]
63 pub(crate) fn set_state(&mut self, new_state: OnceExclusiveState) {
64 self.state.set(match new_state {
65 OnceExclusiveState::Incomplete => State::Incomplete,
66 OnceExclusiveState::Poisoned => State::Poisoned,
67 OnceExclusiveState::Complete => State::Complete,
68 });
69 }
70
71 #[cold]
72 #[track_caller]
73 pub fn wait(&self, _ignore_poisoning: bool) {
74 panic!("not implementable on this target");
75 }
76
77 #[cold]
78 #[track_caller]
79 pub fn call(&self, ignore_poisoning: bool, f: &mut impl FnMut(&public::OnceState)) {
80 let state = self.state.get();
81 match state {
82 State::Poisoned if !ignore_poisoning => {
83 panic!("Once instance has previously been poisoned");
85 }
86 State::Incomplete | State::Poisoned => {
87 self.state.set(State::Running);
88 let mut guard =
90 CompletionGuard { state: &self.state, set_state_on_drop_to: State::Poisoned };
91 let f_state = public::OnceState {
93 inner: OnceState {
94 poisoned: state == State::Poisoned,
95 set_state_to: Cell::new(State::Complete),
96 },
97 };
98 f(&f_state);
99 guard.set_state_on_drop_to = f_state.inner.set_state_to.get();
100 }
101 State::Running => {
102 panic!("one-time initialization may not be performed recursively");
103 }
104 State::Complete => {}
105 }
106 }
107}
108
109impl OnceState {
110 #[inline]
111 pub fn is_poisoned(&self) -> bool {
112 self.poisoned
113 }
114
115 #[inline]
116 pub fn poison(&self) {
117 self.set_state_to.set(State::Poisoned)
118 }
119}