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