1//! A "once initialization" primitive
2//!
3//! This primitive is meant to be used to run one-time initialization. An
4//! example use case would be for initializing an FFI library.
5
6#[cfg(all(test, not(target_os = "emscripten")))]
7mod tests;
8
9use crate::fmt;
10use crate::panic::{RefUnwindSafe, UnwindSafe};
11use crate::sys_common::once as sys;
12
13/// A synchronization primitive which can be used to run a one-time global
14/// initialization. Useful for one-time initialization for FFI or related
15/// functionality. This type can only be constructed with [`Once::new()`].
16///
17/// # Examples
18///
19/// ```
20/// use std::sync::Once;
21///
22/// static START: Once = Once::new();
23///
24/// START.call_once(|| {
25/// // run initialization here
26/// });
27/// ```
28#[stable(feature = "rust1", since = "1.0.0")]
29pub struct Once {
30 inner: sys::Once,
31}
32
33#[stable(feature = "sync_once_unwind_safe", since = "1.59.0")]
34impl UnwindSafe for Once {}
35
36#[stable(feature = "sync_once_unwind_safe", since = "1.59.0")]
37impl RefUnwindSafe for Once {}
38
39/// State yielded to [`Once::call_once_force()`]’s closure parameter. The state
40/// can be used to query the poison status of the [`Once`].
41#[stable(feature = "once_poison", since = "1.51.0")]
42pub struct OnceState {
43 pub(crate) inner: sys::OnceState,
44}
45
46pub(crate) enum ExclusiveState {
47 Incomplete,
48 Poisoned,
49 Complete,
50}
51
52/// Initialization value for static [`Once`] values.
53///
54/// # Examples
55///
56/// ```
57/// use std::sync::{Once, ONCE_INIT};
58///
59/// static START: Once = ONCE_INIT;
60/// ```
61#[stable(feature = "rust1", since = "1.0.0")]
62#[deprecated(
63 since = "1.38.0",
64 note = "the `new` function is now preferred",
65 suggestion = "Once::new()"
66)]
67pub const ONCE_INIT: Once = Once::new();
68
69impl Once {
70 /// Creates a new `Once` value.
71 #[inline]
72 #[stable(feature = "once_new", since = "1.2.0")]
73 #[rustc_const_stable(feature = "const_once_new", since = "1.32.0")]
74 #[must_use]
75 pub const fn new() -> Once {
76 Once { inner: sys::Once::new() }
77 }
78
79 /// Performs an initialization routine once and only once. The given closure
80 /// will be executed if this is the first time `call_once` has been called,
81 /// and otherwise the routine will *not* be invoked.
82 ///
83 /// This method will block the calling thread if another initialization
84 /// routine is currently running.
85 ///
86 /// When this function returns, it is guaranteed that some initialization
87 /// has run and completed (it might not be the closure specified). It is also
88 /// guaranteed that any memory writes performed by the executed closure can
89 /// be reliably observed by other threads at this point (there is a
90 /// happens-before relation between the closure and code executing after the
91 /// return).
92 ///
93 /// If the given closure recursively invokes `call_once` on the same [`Once`]
94 /// instance, the exact behavior is not specified: allowed outcomes are
95 /// a panic or a deadlock.
96 ///
97 /// # Examples
98 ///
99 /// ```
100 /// use std::sync::Once;
101 ///
102 /// static mut VAL: usize = 0;
103 /// static INIT: Once = Once::new();
104 ///
105 /// // Accessing a `static mut` is unsafe much of the time, but if we do so
106 /// // in a synchronized fashion (e.g., write once or read all) then we're
107 /// // good to go!
108 /// //
109 /// // This function will only call `expensive_computation` once, and will
110 /// // otherwise always return the value returned from the first invocation.
111 /// fn get_cached_val() -> usize {
112 /// unsafe {
113 /// INIT.call_once(|| {
114 /// VAL = expensive_computation();
115 /// });
116 /// VAL
117 /// }
118 /// }
119 ///
120 /// fn expensive_computation() -> usize {
121 /// // ...
122 /// # 2
123 /// }
124 /// ```
125 ///
126 /// # Panics
127 ///
128 /// The closure `f` will only be executed once even if this is called
129 /// concurrently amongst many threads. If that closure panics, however, then
130 /// it will *poison* this [`Once`] instance, causing all future invocations of
131 /// `call_once` to also panic.
132 ///
133 /// This is similar to [poisoning with mutexes][poison].
134 ///
135 /// [poison]: struct.Mutex.html#poisoning
136 #[inline]
137 #[stable(feature = "rust1", since = "1.0.0")]
138 #[track_caller]
139 pub fn call_once<F>(&self, f: F)
140 where
141 F: FnOnce(),
142 {
143 // Fast path check
144 if self.inner.is_completed() {
145 return;
146 }
147
148 let mut f = Some(f);
149 self.inner.call(false, &mut |_| f.take().unwrap()());
150 }
151
152 /// Performs the same function as [`call_once()`] except ignores poisoning.
153 ///
154 /// Unlike [`call_once()`], if this [`Once`] has been poisoned (i.e., a previous
155 /// call to [`call_once()`] or [`call_once_force()`] caused a panic), calling
156 /// [`call_once_force()`] will still invoke the closure `f` and will _not_
157 /// result in an immediate panic. If `f` panics, the [`Once`] will remain
158 /// in a poison state. If `f` does _not_ panic, the [`Once`] will no
159 /// longer be in a poison state and all future calls to [`call_once()`] or
160 /// [`call_once_force()`] will be no-ops.
161 ///
162 /// The closure `f` is yielded a [`OnceState`] structure which can be used
163 /// to query the poison status of the [`Once`].
164 ///
165 /// [`call_once()`]: Once::call_once
166 /// [`call_once_force()`]: Once::call_once_force
167 ///
168 /// # Examples
169 ///
170 /// ```
171 /// use std::sync::Once;
172 /// use std::thread;
173 ///
174 /// static INIT: Once = Once::new();
175 ///
176 /// // poison the once
177 /// let handle = thread::spawn(|| {
178 /// INIT.call_once(|| panic!());
179 /// });
180 /// assert!(handle.join().is_err());
181 ///
182 /// // poisoning propagates
183 /// let handle = thread::spawn(|| {
184 /// INIT.call_once(|| {});
185 /// });
186 /// assert!(handle.join().is_err());
187 ///
188 /// // call_once_force will still run and reset the poisoned state
189 /// INIT.call_once_force(|state| {
190 /// assert!(state.is_poisoned());
191 /// });
192 ///
193 /// // once any success happens, we stop propagating the poison
194 /// INIT.call_once(|| {});
195 /// ```
196 #[inline]
197 #[stable(feature = "once_poison", since = "1.51.0")]
198 pub fn call_once_force<F>(&self, f: F)
199 where
200 F: FnOnce(&OnceState),
201 {
202 // Fast path check
203 if self.inner.is_completed() {
204 return;
205 }
206
207 let mut f = Some(f);
208 self.inner.call(true, &mut |p| f.take().unwrap()(p));
209 }
210
211 /// Returns `true` if some [`call_once()`] call has completed
212 /// successfully. Specifically, `is_completed` will return false in
213 /// the following situations:
214 /// * [`call_once()`] was not called at all,
215 /// * [`call_once()`] was called, but has not yet completed,
216 /// * the [`Once`] instance is poisoned
217 ///
218 /// This function returning `false` does not mean that [`Once`] has not been
219 /// executed. For example, it may have been executed in the time between
220 /// when `is_completed` starts executing and when it returns, in which case
221 /// the `false` return value would be stale (but still permissible).
222 ///
223 /// [`call_once()`]: Once::call_once
224 ///
225 /// # Examples
226 ///
227 /// ```
228 /// use std::sync::Once;
229 ///
230 /// static INIT: Once = Once::new();
231 ///
232 /// assert_eq!(INIT.is_completed(), false);
233 /// INIT.call_once(|| {
234 /// assert_eq!(INIT.is_completed(), false);
235 /// });
236 /// assert_eq!(INIT.is_completed(), true);
237 /// ```
238 ///
239 /// ```
240 /// use std::sync::Once;
241 /// use std::thread;
242 ///
243 /// static INIT: Once = Once::new();
244 ///
245 /// assert_eq!(INIT.is_completed(), false);
246 /// let handle = thread::spawn(|| {
247 /// INIT.call_once(|| panic!());
248 /// });
249 /// assert!(handle.join().is_err());
250 /// assert_eq!(INIT.is_completed(), false);
251 /// ```
252 #[stable(feature = "once_is_completed", since = "1.43.0")]
253 #[inline]
254 pub fn is_completed(&self) -> bool {
255 self.inner.is_completed()
256 }
257
258 /// Returns the current state of the `Once` instance.
259 ///
260 /// Since this takes a mutable reference, no initialization can currently
261 /// be running, so the state must be either "incomplete", "poisoned" or
262 /// "complete".
263 #[inline]
264 pub(crate) fn state(&mut self) -> ExclusiveState {
265 self.inner.state()
266 }
267}
268
269#[stable(feature = "std_debug", since = "1.16.0")]
270impl fmt::Debug for Once {
271 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
272 f.debug_struct(name:"Once").finish_non_exhaustive()
273 }
274}
275
276impl OnceState {
277 /// Returns `true` if the associated [`Once`] was poisoned prior to the
278 /// invocation of the closure passed to [`Once::call_once_force()`].
279 ///
280 /// # Examples
281 ///
282 /// A poisoned [`Once`]:
283 ///
284 /// ```
285 /// use std::sync::Once;
286 /// use std::thread;
287 ///
288 /// static INIT: Once = Once::new();
289 ///
290 /// // poison the once
291 /// let handle = thread::spawn(|| {
292 /// INIT.call_once(|| panic!());
293 /// });
294 /// assert!(handle.join().is_err());
295 ///
296 /// INIT.call_once_force(|state| {
297 /// assert!(state.is_poisoned());
298 /// });
299 /// ```
300 ///
301 /// An unpoisoned [`Once`]:
302 ///
303 /// ```
304 /// use std::sync::Once;
305 ///
306 /// static INIT: Once = Once::new();
307 ///
308 /// INIT.call_once_force(|state| {
309 /// assert!(!state.is_poisoned());
310 /// });
311 #[stable(feature = "once_poison", since = "1.51.0")]
312 #[inline]
313 pub fn is_poisoned(&self) -> bool {
314 self.inner.is_poisoned()
315 }
316
317 /// Poison the associated [`Once`] without explicitly panicking.
318 // NOTE: This is currently only exposed for `OnceLock`.
319 #[inline]
320 pub(crate) fn poison(&self) {
321 self.inner.poison();
322 }
323}
324
325#[stable(feature = "std_debug", since = "1.16.0")]
326impl fmt::Debug for OnceState {
327 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
328 f.debug_struct("OnceState").field(name:"poisoned", &self.is_poisoned()).finish()
329 }
330}
331