once.rs - source
Description: Source of the Rust file `library/std/src/sync/once.rs`.

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