std/sync/
once_lock.rs

1use crate::cell::UnsafeCell;
2use crate::fmt;
3use crate::marker::PhantomData;
4use crate::mem::MaybeUninit;
5use crate::panic::{RefUnwindSafe, UnwindSafe};
6use crate::sync::Once;
7
8/// A synchronization primitive which can nominally be written to only once.
9///
10/// This type is a thread-safe [`OnceCell`], and can be used in statics.
11/// In many simple cases, you can use [`LazyLock<T, F>`] instead to get the benefits of this type
12/// with less effort: `LazyLock<T, F>` "looks like" `&T` because it initializes with `F` on deref!
13/// Where OnceLock shines is when LazyLock is too simple to support a given case, as LazyLock
14/// doesn't allow additional inputs to its function after you call [`LazyLock::new(|| ...)`].
15///
16/// A `OnceLock` can be thought of as a safe abstraction over uninitialized data that becomes
17/// initialized once written.
18///
19/// Unlike [`Mutex`](crate::sync::Mutex), `OnceLock` is never poisoned on panic.
20///
21/// [`OnceCell`]: crate::cell::OnceCell
22/// [`LazyLock<T, F>`]: crate::sync::LazyLock
23/// [`LazyLock::new(|| ...)`]: crate::sync::LazyLock::new
24///
25/// # Examples
26///
27/// Writing to a `OnceLock` from a separate thread:
28///
29/// ```
30/// use std::sync::OnceLock;
31///
32/// static CELL: OnceLock<usize> = OnceLock::new();
33///
34/// // `OnceLock` has not been written to yet.
35/// assert!(CELL.get().is_none());
36///
37/// // Spawn a thread and write to `OnceLock`.
38/// std::thread::spawn(|| {
39///     let value = CELL.get_or_init(|| 12345);
40///     assert_eq!(value, &12345);
41/// })
42/// .join()
43/// .unwrap();
44///
45/// // `OnceLock` now contains the value.
46/// assert_eq!(
47///     CELL.get(),
48///     Some(&12345),
49/// );
50/// ```
51///
52/// You can use `OnceLock` to implement a type that requires "append-only" logic:
53///
54/// ```
55/// use std::sync::{OnceLock, atomic::{AtomicU32, Ordering}};
56/// use std::thread;
57///
58/// struct OnceList<T> {
59///     data: OnceLock<T>,
60///     next: OnceLock<Box<OnceList<T>>>,
61/// }
62/// impl<T> OnceList<T> {
63///     const fn new() -> OnceList<T> {
64///         OnceList { data: OnceLock::new(), next: OnceLock::new() }
65///     }
66///     fn push(&self, value: T) {
67///         // FIXME: this impl is concise, but is also slow for long lists or many threads.
68///         // as an exercise, consider how you might improve on it while preserving the behavior
69///         if let Err(value) = self.data.set(value) {
70///             let next = self.next.get_or_init(|| Box::new(OnceList::new()));
71///             next.push(value)
72///         };
73///     }
74///     fn contains(&self, example: &T) -> bool
75///     where
76///         T: PartialEq,
77///     {
78///         self.data.get().map(|item| item == example).filter(|v| *v).unwrap_or_else(|| {
79///             self.next.get().map(|next| next.contains(example)).unwrap_or(false)
80///         })
81///     }
82/// }
83///
84/// // Let's exercise this new Sync append-only list by doing a little counting
85/// static LIST: OnceList<u32> = OnceList::new();
86/// static COUNTER: AtomicU32 = AtomicU32::new(0);
87///
88/// # const LEN: u32 = if cfg!(miri) { 50 } else { 1000 };
89/// # /*
90/// const LEN: u32 = 1000;
91/// # */
92/// thread::scope(|s| {
93///     for _ in 0..thread::available_parallelism().unwrap().get() {
94///         s.spawn(|| {
95///             while let i @ 0..LEN = COUNTER.fetch_add(1, Ordering::Relaxed) {
96///                 LIST.push(i);
97///             }
98///         });
99///     }
100/// });
101///
102/// for i in 0..LEN {
103///     assert!(LIST.contains(&i));
104/// }
105///
106/// ```
107#[stable(feature = "once_cell", since = "1.70.0")]
108pub struct OnceLock<T> {
109    // FIXME(nonpoison_once): switch to nonpoison version once it is available
110    once: Once,
111    // Whether or not the value is initialized is tracked by `once.is_completed()`.
112    value: UnsafeCell<MaybeUninit<T>>,
113    /// `PhantomData` to make sure dropck understands we're dropping T in our Drop impl.
114    ///
115    /// ```compile_fail,E0597
116    /// use std::sync::OnceLock;
117    ///
118    /// struct A<'a>(&'a str);
119    ///
120    /// impl<'a> Drop for A<'a> {
121    ///     fn drop(&mut self) {}
122    /// }
123    ///
124    /// let cell = OnceLock::new();
125    /// {
126    ///     let s = String::new();
127    ///     let _ = cell.set(A(&s));
128    /// }
129    /// ```
130    _marker: PhantomData<T>,
131}
132
133impl<T> OnceLock<T> {
134    /// Creates a new uninitialized cell.
135    #[inline]
136    #[must_use]
137    #[stable(feature = "once_cell", since = "1.70.0")]
138    #[rustc_const_stable(feature = "once_cell", since = "1.70.0")]
139    pub const fn new() -> OnceLock<T> {
140        OnceLock {
141            once: Once::new(),
142            value: UnsafeCell::new(MaybeUninit::uninit()),
143            _marker: PhantomData,
144        }
145    }
146
147    /// Gets the reference to the underlying value.
148    ///
149    /// Returns `None` if the cell is uninitialized, or being initialized.
150    /// This method never blocks.
151    #[inline]
152    #[stable(feature = "once_cell", since = "1.70.0")]
153    pub fn get(&self) -> Option<&T> {
154        if self.is_initialized() {
155            // Safe b/c checked is_initialized
156            Some(unsafe { self.get_unchecked() })
157        } else {
158            None
159        }
160    }
161
162    /// Gets the mutable reference to the underlying value.
163    ///
164    /// Returns `None` if the cell is uninitialized.
165    ///
166    /// This method never blocks. Since it borrows the `OnceLock` mutably,
167    /// it is statically guaranteed that no active borrows to the `OnceLock`
168    /// exist, including from other threads.
169    #[inline]
170    #[stable(feature = "once_cell", since = "1.70.0")]
171    pub fn get_mut(&mut self) -> Option<&mut T> {
172        if self.is_initialized() {
173            // Safe b/c checked is_initialized and we have a unique access
174            Some(unsafe { self.get_unchecked_mut() })
175        } else {
176            None
177        }
178    }
179
180    /// Blocks the current thread until the cell is initialized.
181    ///
182    /// # Example
183    ///
184    /// Waiting for a computation on another thread to finish:
185    /// ```rust
186    /// use std::thread;
187    /// use std::sync::OnceLock;
188    ///
189    /// let value = OnceLock::new();
190    ///
191    /// thread::scope(|s| {
192    ///     s.spawn(|| value.set(1 + 1));
193    ///
194    ///     let result = value.wait();
195    ///     assert_eq!(result, &2);
196    /// })
197    /// ```
198    #[inline]
199    #[stable(feature = "once_wait", since = "1.86.0")]
200    pub fn wait(&self) -> &T {
201        self.once.wait_force();
202
203        unsafe { self.get_unchecked() }
204    }
205
206    /// Initializes the contents of the cell to `value`.
207    ///
208    /// May block if another thread is currently attempting to initialize the cell. The cell is
209    /// guaranteed to contain a value when `set` returns, though not necessarily the one provided.
210    ///
211    /// Returns `Ok(())` if the cell was uninitialized and
212    /// `Err(value)` if the cell was already initialized.
213    ///
214    /// # Examples
215    ///
216    /// ```
217    /// use std::sync::OnceLock;
218    ///
219    /// static CELL: OnceLock<i32> = OnceLock::new();
220    ///
221    /// fn main() {
222    ///     assert!(CELL.get().is_none());
223    ///
224    ///     std::thread::spawn(|| {
225    ///         assert_eq!(CELL.set(92), Ok(()));
226    ///     }).join().unwrap();
227    ///
228    ///     assert_eq!(CELL.set(62), Err(62));
229    ///     assert_eq!(CELL.get(), Some(&92));
230    /// }
231    /// ```
232    #[inline]
233    #[stable(feature = "once_cell", since = "1.70.0")]
234    pub fn set(&self, value: T) -> Result<(), T> {
235        match self.try_insert(value) {
236            Ok(_) => Ok(()),
237            Err((_, value)) => Err(value),
238        }
239    }
240
241    /// Initializes the contents of the cell to `value` if the cell was uninitialized,
242    /// then returns a reference to it.
243    ///
244    /// May block if another thread is currently attempting to initialize the cell. The cell is
245    /// guaranteed to contain a value when `try_insert` returns, though not necessarily the
246    /// one provided.
247    ///
248    /// Returns `Ok(&value)` if the cell was uninitialized and
249    /// `Err((&current_value, value))` if it was already initialized.
250    ///
251    /// # Examples
252    ///
253    /// ```
254    /// #![feature(once_cell_try_insert)]
255    ///
256    /// use std::sync::OnceLock;
257    ///
258    /// static CELL: OnceLock<i32> = OnceLock::new();
259    ///
260    /// fn main() {
261    ///     assert!(CELL.get().is_none());
262    ///
263    ///     std::thread::spawn(|| {
264    ///         assert_eq!(CELL.try_insert(92), Ok(&92));
265    ///     }).join().unwrap();
266    ///
267    ///     assert_eq!(CELL.try_insert(62), Err((&92, 62)));
268    ///     assert_eq!(CELL.get(), Some(&92));
269    /// }
270    /// ```
271    #[inline]
272    #[unstable(feature = "once_cell_try_insert", issue = "116693")]
273    pub fn try_insert(&self, value: T) -> Result<&T, (&T, T)> {
274        let mut value = Some(value);
275        let res = self.get_or_init(|| value.take().unwrap());
276        match value {
277            None => Ok(res),
278            Some(value) => Err((res, value)),
279        }
280    }
281
282    /// Gets the contents of the cell, initializing it to `f()` if the cell
283    /// was uninitialized.
284    ///
285    /// Many threads may call `get_or_init` concurrently with different
286    /// initializing functions, but it is guaranteed that only one function
287    /// will be executed if the function doesn't panic.
288    ///
289    /// # Panics
290    ///
291    /// If `f()` panics, the panic is propagated to the caller, and the cell
292    /// remains uninitialized.
293    ///
294    /// It is an error to reentrantly initialize the cell from `f`. The
295    /// exact outcome is unspecified. Current implementation deadlocks, but
296    /// this may be changed to a panic in the future.
297    ///
298    /// # Examples
299    ///
300    /// ```
301    /// use std::sync::OnceLock;
302    ///
303    /// let cell = OnceLock::new();
304    /// let value = cell.get_or_init(|| 92);
305    /// assert_eq!(value, &92);
306    /// let value = cell.get_or_init(|| unreachable!());
307    /// assert_eq!(value, &92);
308    /// ```
309    #[inline]
310    #[stable(feature = "once_cell", since = "1.70.0")]
311    pub fn get_or_init<F>(&self, f: F) -> &T
312    where
313        F: FnOnce() -> T,
314    {
315        match self.get_or_try_init(|| Ok::<T, !>(f())) {
316            Ok(val) => val,
317        }
318    }
319
320    /// Gets the mutable reference of the contents of the cell, initializing
321    /// it to `f()` if the cell was uninitialized.
322    ///
323    /// This method never blocks. Since it borrows the `OnceLock` mutably,
324    /// it is statically guaranteed that no active borrows to the `OnceLock`
325    /// exist, including from other threads.
326    ///
327    /// # Panics
328    ///
329    /// If `f()` panics, the panic is propagated to the caller, and the cell
330    /// remains uninitialized.
331    ///
332    /// # Examples
333    ///
334    /// ```
335    /// #![feature(once_cell_get_mut)]
336    ///
337    /// use std::sync::OnceLock;
338    ///
339    /// let mut cell = OnceLock::new();
340    /// let value = cell.get_mut_or_init(|| 92);
341    /// assert_eq!(*value, 92);
342    ///
343    /// *value += 2;
344    /// assert_eq!(*value, 94);
345    ///
346    /// let value = cell.get_mut_or_init(|| unreachable!());
347    /// assert_eq!(*value, 94);
348    /// ```
349    #[inline]
350    #[unstable(feature = "once_cell_get_mut", issue = "121641")]
351    pub fn get_mut_or_init<F>(&mut self, f: F) -> &mut T
352    where
353        F: FnOnce() -> T,
354    {
355        match self.get_mut_or_try_init(|| Ok::<T, !>(f())) {
356            Ok(val) => val,
357        }
358    }
359
360    /// Gets the contents of the cell, initializing it to `f()` if
361    /// the cell was uninitialized. If the cell was uninitialized
362    /// and `f()` failed, an error is returned.
363    ///
364    /// # Panics
365    ///
366    /// If `f()` panics, the panic is propagated to the caller, and
367    /// the cell remains uninitialized.
368    ///
369    /// It is an error to reentrantly initialize the cell from `f`.
370    /// The exact outcome is unspecified. Current implementation
371    /// deadlocks, but this may be changed to a panic in the future.
372    ///
373    /// # Examples
374    ///
375    /// ```
376    /// #![feature(once_cell_try)]
377    ///
378    /// use std::sync::OnceLock;
379    ///
380    /// let cell = OnceLock::new();
381    /// assert_eq!(cell.get_or_try_init(|| Err(())), Err(()));
382    /// assert!(cell.get().is_none());
383    /// let value = cell.get_or_try_init(|| -> Result<i32, ()> {
384    ///     Ok(92)
385    /// });
386    /// assert_eq!(value, Ok(&92));
387    /// assert_eq!(cell.get(), Some(&92))
388    /// ```
389    #[inline]
390    #[unstable(feature = "once_cell_try", issue = "109737")]
391    pub fn get_or_try_init<F, E>(&self, f: F) -> Result<&T, E>
392    where
393        F: FnOnce() -> Result<T, E>,
394    {
395        // Fast path check
396        // NOTE: We need to perform an acquire on the state in this method
397        // in order to correctly synchronize `LazyLock::force`. This is
398        // currently done by calling `self.get()`, which in turn calls
399        // `self.is_initialized()`, which in turn performs the acquire.
400        if let Some(value) = self.get() {
401            return Ok(value);
402        }
403        self.initialize(f)?;
404
405        debug_assert!(self.is_initialized());
406
407        // SAFETY: The inner value has been initialized
408        Ok(unsafe { self.get_unchecked() })
409    }
410
411    /// Gets the mutable reference of the contents of the cell, initializing
412    /// it to `f()` if the cell was uninitialized. If the cell was uninitialized
413    /// and `f()` failed, an error is returned.
414    ///
415    /// This method never blocks. Since it borrows the `OnceLock` mutably,
416    /// it is statically guaranteed that no active borrows to the `OnceLock`
417    /// exist, including from other threads.
418    ///
419    /// # Panics
420    ///
421    /// If `f()` panics, the panic is propagated to the caller, and
422    /// the cell remains uninitialized.
423    ///
424    /// # Examples
425    ///
426    /// ```
427    /// #![feature(once_cell_get_mut)]
428    ///
429    /// use std::sync::OnceLock;
430    ///
431    /// let mut cell: OnceLock<u32> = OnceLock::new();
432    ///
433    /// // Failed attempts to initialize the cell do not change its contents
434    /// assert!(cell.get_mut_or_try_init(|| "not a number!".parse()).is_err());
435    /// assert!(cell.get().is_none());
436    ///
437    /// let value = cell.get_mut_or_try_init(|| "1234".parse());
438    /// assert_eq!(value, Ok(&mut 1234));
439    /// *value.unwrap() += 2;
440    /// assert_eq!(cell.get(), Some(&1236))
441    /// ```
442    #[inline]
443    #[unstable(feature = "once_cell_get_mut", issue = "121641")]
444    pub fn get_mut_or_try_init<F, E>(&mut self, f: F) -> Result<&mut T, E>
445    where
446        F: FnOnce() -> Result<T, E>,
447    {
448        if self.get().is_none() {
449            self.initialize(f)?;
450        }
451        debug_assert!(self.is_initialized());
452        // SAFETY: The inner value has been initialized
453        Ok(unsafe { self.get_unchecked_mut() })
454    }
455
456    /// Consumes the `OnceLock`, returning the wrapped value. Returns
457    /// `None` if the cell was uninitialized.
458    ///
459    /// # Examples
460    ///
461    /// ```
462    /// use std::sync::OnceLock;
463    ///
464    /// let cell: OnceLock<String> = OnceLock::new();
465    /// assert_eq!(cell.into_inner(), None);
466    ///
467    /// let cell = OnceLock::new();
468    /// cell.set("hello".to_string()).unwrap();
469    /// assert_eq!(cell.into_inner(), Some("hello".to_string()));
470    /// ```
471    #[inline]
472    #[stable(feature = "once_cell", since = "1.70.0")]
473    pub fn into_inner(mut self) -> Option<T> {
474        self.take()
475    }
476
477    /// Takes the value out of this `OnceLock`, moving it back to an uninitialized state.
478    ///
479    /// Has no effect and returns `None` if the `OnceLock` was uninitialized.
480    ///
481    /// Since this method borrows the `OnceLock` mutably, it is statically guaranteed that
482    /// no active borrows to the `OnceLock` exist, including from other threads.
483    ///
484    /// # Examples
485    ///
486    /// ```
487    /// use std::sync::OnceLock;
488    ///
489    /// let mut cell: OnceLock<String> = OnceLock::new();
490    /// assert_eq!(cell.take(), None);
491    ///
492    /// let mut cell = OnceLock::new();
493    /// cell.set("hello".to_string()).unwrap();
494    /// assert_eq!(cell.take(), Some("hello".to_string()));
495    /// assert_eq!(cell.get(), None);
496    /// ```
497    #[inline]
498    #[stable(feature = "once_cell", since = "1.70.0")]
499    pub fn take(&mut self) -> Option<T> {
500        if self.is_initialized() {
501            self.once = Once::new();
502            // SAFETY: `self.value` is initialized and contains a valid `T`.
503            // `self.once` is reset, so `is_initialized()` will be false again
504            // which prevents the value from being read twice.
505            unsafe { Some((&mut *self.value.get()).assume_init_read()) }
506        } else {
507            None
508        }
509    }
510
511    #[inline]
512    fn is_initialized(&self) -> bool {
513        self.once.is_completed()
514    }
515
516    #[cold]
517    #[optimize(size)]
518    fn initialize<F, E>(&self, f: F) -> Result<(), E>
519    where
520        F: FnOnce() -> Result<T, E>,
521    {
522        let mut res: Result<(), E> = Ok(());
523        let slot = &self.value;
524
525        // Ignore poisoning from other threads
526        // If another thread panics, then we'll be able to run our closure
527        self.once.call_once_force(|p| {
528            match f() {
529                Ok(value) => {
530                    unsafe { (&mut *slot.get()).write(value) };
531                }
532                Err(e) => {
533                    res = Err(e);
534
535                    // Treat the underlying `Once` as poisoned since we
536                    // failed to initialize our value.
537                    p.poison();
538                }
539            }
540        });
541        res
542    }
543
544    /// # Safety
545    ///
546    /// The cell must be initialized
547    #[inline]
548    unsafe fn get_unchecked(&self) -> &T {
549        debug_assert!(self.is_initialized());
550        unsafe { (&*self.value.get()).assume_init_ref() }
551    }
552
553    /// # Safety
554    ///
555    /// The cell must be initialized
556    #[inline]
557    unsafe fn get_unchecked_mut(&mut self) -> &mut T {
558        debug_assert!(self.is_initialized());
559        unsafe { (&mut *self.value.get()).assume_init_mut() }
560    }
561}
562
563// Why do we need `T: Send`?
564// Thread A creates a `OnceLock` and shares it with
565// scoped thread B, which fills the cell, which is
566// then destroyed by A. That is, destructor observes
567// a sent value.
568#[stable(feature = "once_cell", since = "1.70.0")]
569unsafe impl<T: Sync + Send> Sync for OnceLock<T> {}
570#[stable(feature = "once_cell", since = "1.70.0")]
571unsafe impl<T: Send> Send for OnceLock<T> {}
572
573#[stable(feature = "once_cell", since = "1.70.0")]
574impl<T: RefUnwindSafe + UnwindSafe> RefUnwindSafe for OnceLock<T> {}
575#[stable(feature = "once_cell", since = "1.70.0")]
576impl<T: UnwindSafe> UnwindSafe for OnceLock<T> {}
577
578#[stable(feature = "once_cell", since = "1.70.0")]
579impl<T> Default for OnceLock<T> {
580    /// Creates a new uninitialized cell.
581    ///
582    /// # Example
583    ///
584    /// ```
585    /// use std::sync::OnceLock;
586    ///
587    /// fn main() {
588    ///     assert_eq!(OnceLock::<()>::new(), OnceLock::default());
589    /// }
590    /// ```
591    #[inline]
592    fn default() -> OnceLock<T> {
593        OnceLock::new()
594    }
595}
596
597#[stable(feature = "once_cell", since = "1.70.0")]
598impl<T: fmt::Debug> fmt::Debug for OnceLock<T> {
599    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
600        let mut d = f.debug_tuple("OnceLock");
601        match self.get() {
602            Some(v) => d.field(v),
603            None => d.field(&format_args!("<uninit>")),
604        };
605        d.finish()
606    }
607}
608
609#[stable(feature = "once_cell", since = "1.70.0")]
610impl<T: Clone> Clone for OnceLock<T> {
611    #[inline]
612    fn clone(&self) -> OnceLock<T> {
613        let cell = Self::new();
614        if let Some(value) = self.get() {
615            match cell.set(value.clone()) {
616                Ok(()) => (),
617                Err(_) => unreachable!(),
618            }
619        }
620        cell
621    }
622}
623
624#[stable(feature = "once_cell", since = "1.70.0")]
625impl<T> From<T> for OnceLock<T> {
626    /// Creates a new cell with its contents set to `value`.
627    ///
628    /// # Example
629    ///
630    /// ```
631    /// use std::sync::OnceLock;
632    ///
633    /// # fn main() -> Result<(), i32> {
634    /// let a = OnceLock::from(3);
635    /// let b = OnceLock::new();
636    /// b.set(3)?;
637    /// assert_eq!(a, b);
638    /// Ok(())
639    /// # }
640    /// ```
641    #[inline]
642    fn from(value: T) -> Self {
643        let cell = Self::new();
644        match cell.set(value) {
645            Ok(()) => cell,
646            Err(_) => unreachable!(),
647        }
648    }
649}
650
651#[stable(feature = "once_cell", since = "1.70.0")]
652impl<T: PartialEq> PartialEq for OnceLock<T> {
653    /// Equality for two `OnceLock`s.
654    ///
655    /// Two `OnceLock`s are equal if they either both contain values and their
656    /// values are equal, or if neither contains a value.
657    ///
658    /// # Examples
659    ///
660    /// ```
661    /// use std::sync::OnceLock;
662    ///
663    /// let five = OnceLock::new();
664    /// five.set(5).unwrap();
665    ///
666    /// let also_five = OnceLock::new();
667    /// also_five.set(5).unwrap();
668    ///
669    /// assert!(five == also_five);
670    ///
671    /// assert!(OnceLock::<u32>::new() == OnceLock::<u32>::new());
672    /// ```
673    #[inline]
674    fn eq(&self, other: &OnceLock<T>) -> bool {
675        self.get() == other.get()
676    }
677}
678
679#[stable(feature = "once_cell", since = "1.70.0")]
680impl<T: Eq> Eq for OnceLock<T> {}
681
682#[stable(feature = "once_cell", since = "1.70.0")]
683unsafe impl<#[may_dangle] T> Drop for OnceLock<T> {
684    #[inline]
685    fn drop(&mut self) {
686        if self.is_initialized() {
687            // SAFETY: The cell is initialized and being dropped, so it can't
688            // be accessed again. We also don't touch the `T` other than
689            // dropping it, which validates our usage of #[may_dangle].
690            unsafe { (&mut *self.value.get()).assume_init_drop() };
691        }
692    }
693}