Skip to main content

std/sync/
lazy_lock.rs

1use super::once::OnceExclusiveState;
2use crate::cell::UnsafeCell;
3use crate::mem::ManuallyDrop;
4use crate::ops::{Deref, DerefMut};
5use crate::panic::{RefUnwindSafe, UnwindSafe};
6use crate::sync::Once;
7use crate::{fmt, ptr};
8
9// We use the state of a Once as discriminant value. Upon creation, the state is
10// "incomplete" and `f` contains the initialization closure. In the first call to
11// `call_once`, `f` is taken and run. If it succeeds, `value` is set and the state
12// is changed to "complete". If it panics, the Once is poisoned, so none of the
13// two fields is initialized.
14union Data<T, F> {
15    value: ManuallyDrop<T>,
16    f: ManuallyDrop<F>,
17}
18
19/// A value which is initialized on the first access.
20///
21/// This type is a thread-safe [`LazyCell`], and can be used in statics.
22/// Since initialization may be called from multiple threads, any
23/// dereferencing call will block the calling thread if another
24/// initialization routine is currently running.
25///
26/// [`LazyCell`]: crate::cell::LazyCell
27///
28/// # Poisoning
29///
30/// If the initialization closure passed to [`LazyLock::new`] panics, the lock will be poisoned.
31/// Once the lock is poisoned, any threads that attempt to access this lock (via a dereference
32/// or via an explicit call to [`force()`]) will panic.
33///
34/// This concept is similar to that of poisoning in the [`std::sync::poison`] module. A key
35/// difference, however, is that poisoning in `LazyLock` is _unrecoverable_. All future accesses of
36/// the lock from other threads will panic, whereas a type in [`std::sync::poison`] like
37/// [`std::sync::poison::Mutex`] allows recovery via [`PoisonError::into_inner()`].
38///
39/// [`force()`]: LazyLock::force
40/// [`std::sync::poison`]: crate::sync::poison
41/// [`std::sync::poison::Mutex`]: crate::sync::poison::Mutex
42/// [`PoisonError::into_inner()`]: crate::sync::poison::PoisonError::into_inner
43///
44/// # Examples
45///
46/// Initialize static variables with `LazyLock`.
47/// ```
48/// use std::sync::LazyLock;
49///
50/// // Note: static items do not call [`Drop`] on program termination, so this won't be deallocated.
51/// // this is fine, as the OS can deallocate the terminated program faster than we can free memory
52/// // but tools like valgrind might report "memory leaks" as it isn't obvious this is intentional.
53/// static DEEP_THOUGHT: LazyLock<String> = LazyLock::new(|| {
54/// # mod another_crate {
55/// #     pub fn great_question() -> String { "42".to_string() }
56/// # }
57///     // M3 Ultra takes about 16 million years in --release config
58///     another_crate::great_question()
59/// });
60///
61/// // The `String` is built, stored in the `LazyLock`, and returned as `&String`.
62/// let _ = &*DEEP_THOUGHT;
63/// ```
64///
65/// Initialize fields with `LazyLock`.
66/// ```
67/// use std::sync::LazyLock;
68///
69/// #[derive(Debug)]
70/// struct UseCellLock {
71///     number: LazyLock<u32>,
72/// }
73/// fn main() {
74///     let lock: LazyLock<u32> = LazyLock::new(|| 0u32);
75///
76///     let data = UseCellLock { number: lock };
77///     println!("{}", *data.number);
78/// }
79/// ```
80#[stable(feature = "lazy_cell", since = "1.80.0")]
81pub struct LazyLock<T, F = fn() -> T> {
82    // FIXME(nonpoison_once): if possible, switch to nonpoison version once it is available
83    once: Once,
84    data: UnsafeCell<Data<T, F>>,
85}
86
87impl<T, F: FnOnce() -> T> LazyLock<T, F> {
88    /// Creates a new lazy value with the given initializing function.
89    ///
90    /// # Examples
91    ///
92    /// ```
93    /// use std::sync::LazyLock;
94    ///
95    /// let hello = "Hello, World!".to_string();
96    ///
97    /// let lazy = LazyLock::new(|| hello.to_uppercase());
98    ///
99    /// assert_eq!(&*lazy, "HELLO, WORLD!");
100    /// ```
101    #[inline]
102    #[stable(feature = "lazy_cell", since = "1.80.0")]
103    #[rustc_const_stable(feature = "lazy_cell", since = "1.80.0")]
104    pub const fn new(f: F) -> LazyLock<T, F> {
105        LazyLock { once: Once::new(), data: UnsafeCell::new(Data { f: ManuallyDrop::new(f) }) }
106    }
107
108    /// Consumes this `LazyLock` returning the stored value.
109    ///
110    /// Returns `Ok(value)` if `Lazy` is initialized and `Err(f)` otherwise.
111    ///
112    /// # Panics
113    ///
114    /// Panics if the lock is poisoned.
115    ///
116    /// # Examples
117    ///
118    /// ```
119    /// #![feature(lazy_cell_into_inner)]
120    ///
121    /// use std::sync::LazyLock;
122    ///
123    /// let hello = "Hello, World!".to_string();
124    ///
125    /// let lazy = LazyLock::new(|| hello.to_uppercase());
126    ///
127    /// assert_eq!(&*lazy, "HELLO, WORLD!");
128    /// assert_eq!(LazyLock::into_inner(lazy).ok(), Some("HELLO, WORLD!".to_string()));
129    /// ```
130    #[unstable(feature = "lazy_cell_into_inner", issue = "125623")]
131    pub fn into_inner(mut this: Self) -> Result<T, F> {
132        let state = this.once.state();
133        match state {
134            OnceExclusiveState::Poisoned => panic_poisoned(),
135            state => {
136                let this = ManuallyDrop::new(this);
137                let data = unsafe { ptr::read(&this.data) }.into_inner();
138                match state {
139                    OnceExclusiveState::Incomplete => {
140                        Err(ManuallyDrop::into_inner(unsafe { data.f }))
141                    }
142                    OnceExclusiveState::Complete => {
143                        Ok(ManuallyDrop::into_inner(unsafe { data.value }))
144                    }
145                    OnceExclusiveState::Poisoned => unreachable!(),
146                }
147            }
148        }
149    }
150
151    /// Forces the evaluation of this lazy value and returns a mutable reference to
152    /// the result.
153    ///
154    /// # Panics
155    ///
156    /// If the initialization closure panics (the one that is passed to the [`new()`] method), the
157    /// panic is propagated to the caller, and the lock becomes poisoned. This will cause all future
158    /// accesses of the lock (via [`force()`] or a dereference) to panic.
159    ///
160    /// [`new()`]: LazyLock::new
161    /// [`force()`]: LazyLock::force
162    ///
163    /// # Examples
164    ///
165    /// ```
166    /// use std::sync::LazyLock;
167    ///
168    /// let mut lazy = LazyLock::new(|| 92);
169    ///
170    /// let p = LazyLock::force_mut(&mut lazy);
171    /// assert_eq!(*p, 92);
172    /// *p = 44;
173    /// assert_eq!(*lazy, 44);
174    /// ```
175    #[inline]
176    #[stable(feature = "lazy_get", since = "1.94.0")]
177    pub fn force_mut(this: &mut LazyLock<T, F>) -> &mut T {
178        #[cold]
179        /// # Safety
180        /// May only be called when the state is `Incomplete`.
181        unsafe fn really_init_mut<T, F: FnOnce() -> T>(this: &mut LazyLock<T, F>) -> &mut T {
182            struct PoisonOnPanic<'a, T, F>(&'a mut LazyLock<T, F>);
183            impl<T, F> Drop for PoisonOnPanic<'_, T, F> {
184                #[inline]
185                fn drop(&mut self) {
186                    self.0.once.set_state(OnceExclusiveState::Poisoned);
187                }
188            }
189
190            // SAFETY: We always poison if the initializer panics (then we never check the data),
191            // or set the data on success.
192            let f = unsafe { ManuallyDrop::take(&mut this.data.get_mut().f) };
193            // INVARIANT: Initiated from mutable reference, don't drop because we read it.
194            let guard = PoisonOnPanic(this);
195            let data = f();
196            guard.0.data.get_mut().value = ManuallyDrop::new(data);
197            guard.0.once.set_state(OnceExclusiveState::Complete);
198            core::mem::forget(guard);
199            // SAFETY: We put the value there above.
200            unsafe { LazyLock::get_unchecked_mut(this) }
201        }
202
203        let state = this.once.state();
204        match state {
205            OnceExclusiveState::Poisoned => panic_poisoned(),
206            // SAFETY: The `Once` states we completed the initialization.
207            OnceExclusiveState::Complete => unsafe { LazyLock::get_unchecked_mut(this) },
208            // SAFETY: The state is `Incomplete`.
209            OnceExclusiveState::Incomplete => unsafe { really_init_mut(this) },
210        }
211    }
212
213    /// Forces the evaluation of this lazy value and returns a reference to
214    /// result. This is equivalent to the `Deref` impl, but is explicit.
215    ///
216    /// This method will block the calling thread if another initialization
217    /// routine is currently running.
218    ///
219    /// # Panics
220    ///
221    /// If the initialization closure panics (the one that is passed to the [`new()`] method), the
222    /// panic is propagated to the caller, and the lock becomes poisoned. This will cause all future
223    /// accesses of the lock (via [`force()`] or a dereference) to panic.
224    ///
225    /// [`new()`]: LazyLock::new
226    /// [`force()`]: LazyLock::force
227    ///
228    /// # Examples
229    ///
230    /// ```
231    /// use std::sync::LazyLock;
232    ///
233    /// let lazy = LazyLock::new(|| 92);
234    ///
235    /// assert_eq!(LazyLock::force(&lazy), &92);
236    /// assert_eq!(&*lazy, &92);
237    /// ```
238    #[inline]
239    #[stable(feature = "lazy_cell", since = "1.80.0")]
240    #[rustc_should_not_be_called_on_const_items]
241    pub fn force(this: &LazyLock<T, F>) -> &T {
242        this.once.call_once_force(|state| {
243            if state.is_poisoned() {
244                panic_poisoned();
245            }
246
247            // SAFETY: `call_once` only runs this closure once, ever.
248            let data = unsafe { &mut *this.data.get() };
249            let f = unsafe { ManuallyDrop::take(&mut data.f) };
250            let value = f();
251            data.value = ManuallyDrop::new(value);
252        });
253
254        // SAFETY:
255        // There are four possible scenarios:
256        // * the closure was called and initialized `value`.
257        // * the closure was called and panicked, so this point is never reached.
258        // * the closure was not called, but a previous call initialized `value`.
259        // * the closure was not called because the Once is poisoned, which we handled above.
260        // So `value` has definitely been initialized and will not be modified again.
261        unsafe { LazyLock::get_unchecked(this) }
262    }
263}
264
265impl<T, F> LazyLock<T, F> {
266    /// Returns a mutable reference to the value if initialized. Otherwise (if uninitialized or
267    /// poisoned), returns `None`.
268    ///
269    /// # Examples
270    ///
271    /// ```
272    /// use std::sync::LazyLock;
273    ///
274    /// let mut lazy = LazyLock::new(|| 92);
275    ///
276    /// assert_eq!(LazyLock::get_mut(&mut lazy), None);
277    /// let _ = LazyLock::force(&lazy);
278    /// *LazyLock::get_mut(&mut lazy).unwrap() = 44;
279    /// assert_eq!(*lazy, 44);
280    /// ```
281    #[inline]
282    #[stable(feature = "lazy_get", since = "1.94.0")]
283    pub fn get_mut(this: &mut LazyLock<T, F>) -> Option<&mut T> {
284        // `state()` does not perform an atomic load, so prefer it over `is_complete()`.
285        let state = this.once.state();
286        match state {
287            // SAFETY:
288            // The closure has been run successfully, so `value` has been initialized.
289            OnceExclusiveState::Complete => Some(unsafe { LazyLock::get_unchecked_mut(this) }),
290            _ => None,
291        }
292    }
293
294    /// Returns a reference to the value if initialized. Otherwise (if uninitialized or poisoned),
295    /// returns `None`.
296    ///
297    /// # Examples
298    ///
299    /// ```
300    /// use std::sync::LazyLock;
301    ///
302    /// let lazy = LazyLock::new(|| 92);
303    ///
304    /// assert_eq!(LazyLock::get(&lazy), None);
305    /// let _ = LazyLock::force(&lazy);
306    /// assert_eq!(LazyLock::get(&lazy), Some(&92));
307    /// ```
308    #[inline]
309    #[stable(feature = "lazy_get", since = "1.94.0")]
310    #[rustc_should_not_be_called_on_const_items]
311    pub fn get(this: &LazyLock<T, F>) -> Option<&T> {
312        if this.once.is_completed() {
313            // SAFETY:
314            // The closure has been run successfully, so `value` has been initialized
315            // and will not be modified again.
316            Some(unsafe { LazyLock::get_unchecked(this) })
317        } else {
318            None
319        }
320    }
321
322    /// Returns a shared reference to the value stored in the `LazyLock` without
323    /// checking whether it has been initialized.
324    ///
325    /// # Safety
326    ///
327    /// The lazy value must be initialized before calling this function.
328    ///
329    /// # Examples
330    ///
331    /// ```
332    /// #![feature(once_lazy_lock_get_unchecked)]
333    ///
334    /// use std::sync::LazyLock;
335    ///
336    /// let lazy = LazyLock::new(|| 42);
337    ///
338    /// // Initialize the lazy.
339    /// let _ = &*lazy;
340    ///
341    /// let value = unsafe { LazyLock::get_unchecked(&lazy) };
342    /// assert_eq!(*value, 42);
343    /// ```
344    #[inline]
345    #[unstable(feature = "once_lazy_lock_get_unchecked", issue = "162716")]
346    pub unsafe fn get_unchecked(this: &LazyLock<T, F>) -> &T {
347        debug_assert!(this.once.is_completed());
348        unsafe { &(*this.data.get()).value }
349    }
350
351    /// Returns a mutable reference to the value stored in the `LazyLock` without
352    /// checking whether it has been initialized.
353    ///
354    /// # Safety
355    ///
356    /// The lazy value must be initialized before calling this function.
357    ///
358    /// # Examples
359    ///
360    /// ```
361    /// #![feature(once_lazy_lock_get_unchecked)]
362    ///
363    /// use std::sync::LazyLock;
364    ///
365    /// let mut lazy = LazyLock::new(|| 42);
366    ///
367    /// // Initialize the lazy.
368    /// let _ = &*lazy;
369    ///
370    /// let value = unsafe { LazyLock::get_unchecked_mut(&mut lazy) };
371    /// *value = 100;
372    ///
373    /// assert_eq!(*lazy, 100);
374    /// ```
375    #[inline]
376    #[unstable(feature = "once_lazy_lock_get_unchecked", issue = "162716")]
377    pub unsafe fn get_unchecked_mut(this: &mut LazyLock<T, F>) -> &mut T {
378        debug_assert!(this.once.is_completed());
379        unsafe { &mut this.data.get_mut().value }
380    }
381}
382
383#[stable(feature = "lazy_cell", since = "1.80.0")]
384impl<T, F> Drop for LazyLock<T, F> {
385    fn drop(&mut self) {
386        match self.once.state() {
387            OnceExclusiveState::Incomplete => unsafe {
388                ManuallyDrop::drop(&mut self.data.get_mut().f)
389            },
390            OnceExclusiveState::Complete => unsafe {
391                ManuallyDrop::drop(&mut self.data.get_mut().value)
392            },
393            OnceExclusiveState::Poisoned => {}
394        }
395    }
396}
397
398#[stable(feature = "lazy_cell", since = "1.80.0")]
399impl<T, F: FnOnce() -> T> Deref for LazyLock<T, F> {
400    type Target = T;
401
402    /// Dereferences the value.
403    ///
404    /// This method will block the calling thread if another initialization
405    /// routine is currently running.
406    ///
407    /// # Panics
408    ///
409    /// If the initialization closure panics (the one that is passed to the [`new()`] method), the
410    /// panic is propagated to the caller, and the lock becomes poisoned. This will cause all future
411    /// accesses of the lock (via [`force()`] or a dereference) to panic.
412    ///
413    /// [`new()`]: LazyLock::new
414    /// [`force()`]: LazyLock::force
415    #[inline]
416    fn deref(&self) -> &T {
417        LazyLock::force(self)
418    }
419}
420
421#[stable(feature = "lazy_deref_mut", since = "1.89.0")]
422impl<T, F: FnOnce() -> T> DerefMut for LazyLock<T, F> {
423    /// # Panics
424    ///
425    /// If the initialization closure panics (the one that is passed to the [`new()`] method), the
426    /// panic is propagated to the caller, and the lock becomes poisoned. This will cause all future
427    /// accesses of the lock (via [`force()`] or a dereference) to panic.
428    ///
429    /// [`new()`]: LazyLock::new
430    /// [`force()`]: LazyLock::force
431    #[inline]
432    fn deref_mut(&mut self) -> &mut T {
433        LazyLock::force_mut(self)
434    }
435}
436
437#[stable(feature = "lazy_cell", since = "1.80.0")]
438#[rustc_const_unstable(feature = "const_default", issue = "143894")]
439const impl<T: Default> Default for LazyLock<T> {
440    /// Creates a new lazy value using `Default` as the initializing function.
441    #[inline]
442    fn default() -> LazyLock<T> {
443        LazyLock::new(T::default)
444    }
445}
446
447#[stable(feature = "lazy_cell", since = "1.80.0")]
448impl<T: fmt::Debug, F> fmt::Debug for LazyLock<T, F> {
449    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
450        let mut d = f.debug_tuple("LazyLock");
451        match LazyLock::get(self) {
452            Some(v) => d.field(v),
453            None => d.field(&format_args!("<uninit>")),
454        };
455        d.finish()
456    }
457}
458
459#[stable(feature = "from_wrapper_impls", since = "1.96.0")]
460impl<T, F> From<T> for LazyLock<T, F> {
461    /// Constructs a `LazyLock` that starts already initialized
462    /// with the provided value.
463    #[inline]
464    fn from(value: T) -> Self {
465        LazyLock {
466            once: Once::new_complete(),
467            data: UnsafeCell::new(Data { value: ManuallyDrop::new(value) }),
468        }
469    }
470}
471
472#[cold]
473#[inline(never)]
474fn panic_poisoned() -> ! {
475    panic!("LazyLock instance has previously been poisoned")
476}
477
478// We never create a `&F` from a `&LazyLock<T, F>` so it is fine
479// to not impl `Sync` for `F`.
480#[stable(feature = "lazy_cell", since = "1.80.0")]
481unsafe impl<T: Sync + Send, F: Send> Sync for LazyLock<T, F> {}
482// auto-derived `Send` impl is OK.
483
484#[stable(feature = "lazy_cell", since = "1.80.0")]
485impl<T: RefUnwindSafe + UnwindSafe, F: UnwindSafe> RefUnwindSafe for LazyLock<T, F> {}
486#[stable(feature = "lazy_cell", since = "1.80.0")]
487impl<T: UnwindSafe, F: UnwindSafe> UnwindSafe for LazyLock<T, F> {}