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

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy