std/sync/
lazy_lock.rs

1use super::poison::once::ExclusiveState;
2use crate::cell::UnsafeCell;
3use crate::mem::ManuallyDrop;
4use crate::ops::Deref;
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/// # Examples
29///
30/// Initialize static variables with `LazyLock`.
31/// ```
32/// use std::sync::LazyLock;
33///
34/// // Note: static items do not call [`Drop`] on program termination, so this won't be deallocated.
35/// // this is fine, as the OS can deallocate the terminated program faster than we can free memory
36/// // but tools like valgrind might report "memory leaks" as it isn't obvious this is intentional.
37/// static DEEP_THOUGHT: LazyLock<String> = LazyLock::new(|| {
38/// # mod another_crate {
39/// #     pub fn great_question() -> String { "42".to_string() }
40/// # }
41///     // M3 Ultra takes about 16 million years in --release config
42///     another_crate::great_question()
43/// });
44///
45/// // The `String` is built, stored in the `LazyLock`, and returned as `&String`.
46/// let _ = &*DEEP_THOUGHT;
47/// ```
48///
49/// Initialize fields with `LazyLock`.
50/// ```
51/// use std::sync::LazyLock;
52///
53/// #[derive(Debug)]
54/// struct UseCellLock {
55///     number: LazyLock<u32>,
56/// }
57/// fn main() {
58///     let lock: LazyLock<u32> = LazyLock::new(|| 0u32);
59///
60///     let data = UseCellLock { number: lock };
61///     println!("{}", *data.number);
62/// }
63/// ```
64#[stable(feature = "lazy_cell", since = "1.80.0")]
65pub struct LazyLock<T, F = fn() -> T> {
66    // FIXME(nonpoison_once): if possible, switch to nonpoison version once it is available
67    once: Once,
68    data: UnsafeCell<Data<T, F>>,
69}
70
71impl<T, F: FnOnce() -> T> LazyLock<T, F> {
72    /// Creates a new lazy value with the given initializing function.
73    ///
74    /// # Examples
75    ///
76    /// ```
77    /// use std::sync::LazyLock;
78    ///
79    /// let hello = "Hello, World!".to_string();
80    ///
81    /// let lazy = LazyLock::new(|| hello.to_uppercase());
82    ///
83    /// assert_eq!(&*lazy, "HELLO, WORLD!");
84    /// ```
85    #[inline]
86    #[stable(feature = "lazy_cell", since = "1.80.0")]
87    #[rustc_const_stable(feature = "lazy_cell", since = "1.80.0")]
88    pub const fn new(f: F) -> LazyLock<T, F> {
89        LazyLock { once: Once::new(), data: UnsafeCell::new(Data { f: ManuallyDrop::new(f) }) }
90    }
91
92    /// Creates a new lazy value that is already initialized.
93    #[inline]
94    #[cfg(test)]
95    pub(crate) fn preinit(value: T) -> LazyLock<T, F> {
96        let once = Once::new();
97        once.call_once(|| {});
98        LazyLock { once, data: UnsafeCell::new(Data { value: ManuallyDrop::new(value) }) }
99    }
100
101    /// Consumes this `LazyLock` returning the stored value.
102    ///
103    /// Returns `Ok(value)` if `Lazy` is initialized and `Err(f)` otherwise.
104    ///
105    /// # Examples
106    ///
107    /// ```
108    /// #![feature(lazy_cell_into_inner)]
109    ///
110    /// use std::sync::LazyLock;
111    ///
112    /// let hello = "Hello, World!".to_string();
113    ///
114    /// let lazy = LazyLock::new(|| hello.to_uppercase());
115    ///
116    /// assert_eq!(&*lazy, "HELLO, WORLD!");
117    /// assert_eq!(LazyLock::into_inner(lazy).ok(), Some("HELLO, WORLD!".to_string()));
118    /// ```
119    #[unstable(feature = "lazy_cell_into_inner", issue = "125623")]
120    pub fn into_inner(mut this: Self) -> Result<T, F> {
121        let state = this.once.state();
122        match state {
123            ExclusiveState::Poisoned => panic_poisoned(),
124            state => {
125                let this = ManuallyDrop::new(this);
126                let data = unsafe { ptr::read(&this.data) }.into_inner();
127                match state {
128                    ExclusiveState::Incomplete => Err(ManuallyDrop::into_inner(unsafe { data.f })),
129                    ExclusiveState::Complete => Ok(ManuallyDrop::into_inner(unsafe { data.value })),
130                    ExclusiveState::Poisoned => unreachable!(),
131                }
132            }
133        }
134    }
135
136    /// Forces the evaluation of this lazy value and returns a mutable reference to
137    /// the result.
138    ///
139    /// # Examples
140    ///
141    /// ```
142    /// #![feature(lazy_get)]
143    /// use std::sync::LazyLock;
144    ///
145    /// let mut lazy = LazyLock::new(|| 92);
146    ///
147    /// let p = LazyLock::force_mut(&mut lazy);
148    /// assert_eq!(*p, 92);
149    /// *p = 44;
150    /// assert_eq!(*lazy, 44);
151    /// ```
152    #[inline]
153    #[unstable(feature = "lazy_get", issue = "129333")]
154    pub fn force_mut(this: &mut LazyLock<T, F>) -> &mut T {
155        #[cold]
156        /// # Safety
157        /// May only be called when the state is `Incomplete`.
158        unsafe fn really_init_mut<T, F: FnOnce() -> T>(this: &mut LazyLock<T, F>) -> &mut T {
159            struct PoisonOnPanic<'a, T, F>(&'a mut LazyLock<T, F>);
160            impl<T, F> Drop for PoisonOnPanic<'_, T, F> {
161                #[inline]
162                fn drop(&mut self) {
163                    self.0.once.set_state(ExclusiveState::Poisoned);
164                }
165            }
166
167            // SAFETY: We always poison if the initializer panics (then we never check the data),
168            // or set the data on success.
169            let f = unsafe { ManuallyDrop::take(&mut this.data.get_mut().f) };
170            // INVARIANT: Initiated from mutable reference, don't drop because we read it.
171            let guard = PoisonOnPanic(this);
172            let data = f();
173            guard.0.data.get_mut().value = ManuallyDrop::new(data);
174            guard.0.once.set_state(ExclusiveState::Complete);
175            core::mem::forget(guard);
176            // SAFETY: We put the value there above.
177            unsafe { &mut this.data.get_mut().value }
178        }
179
180        let state = this.once.state();
181        match state {
182            ExclusiveState::Poisoned => panic_poisoned(),
183            // SAFETY: The `Once` states we completed the initialization.
184            ExclusiveState::Complete => unsafe { &mut this.data.get_mut().value },
185            // SAFETY: The state is `Incomplete`.
186            ExclusiveState::Incomplete => unsafe { really_init_mut(this) },
187        }
188    }
189
190    /// Forces the evaluation of this lazy value and returns a reference to
191    /// result. This is equivalent to the `Deref` impl, but is explicit.
192    ///
193    /// This method will block the calling thread if another initialization
194    /// routine is currently running.
195    ///
196    /// # Examples
197    ///
198    /// ```
199    /// use std::sync::LazyLock;
200    ///
201    /// let lazy = LazyLock::new(|| 92);
202    ///
203    /// assert_eq!(LazyLock::force(&lazy), &92);
204    /// assert_eq!(&*lazy, &92);
205    /// ```
206    #[inline]
207    #[stable(feature = "lazy_cell", since = "1.80.0")]
208    pub fn force(this: &LazyLock<T, F>) -> &T {
209        this.once.call_once(|| {
210            // SAFETY: `call_once` only runs this closure once, ever.
211            let data = unsafe { &mut *this.data.get() };
212            let f = unsafe { ManuallyDrop::take(&mut data.f) };
213            let value = f();
214            data.value = ManuallyDrop::new(value);
215        });
216
217        // SAFETY:
218        // There are four possible scenarios:
219        // * the closure was called and initialized `value`.
220        // * the closure was called and panicked, so this point is never reached.
221        // * the closure was not called, but a previous call initialized `value`.
222        // * the closure was not called because the Once is poisoned, so this point
223        //   is never reached.
224        // So `value` has definitely been initialized and will not be modified again.
225        unsafe { &*(*this.data.get()).value }
226    }
227}
228
229impl<T, F> LazyLock<T, F> {
230    /// Returns a mutable reference to the value if initialized, or `None` if not.
231    ///
232    /// # Examples
233    ///
234    /// ```
235    /// #![feature(lazy_get)]
236    ///
237    /// use std::sync::LazyLock;
238    ///
239    /// let mut lazy = LazyLock::new(|| 92);
240    ///
241    /// assert_eq!(LazyLock::get_mut(&mut lazy), None);
242    /// let _ = LazyLock::force(&lazy);
243    /// *LazyLock::get_mut(&mut lazy).unwrap() = 44;
244    /// assert_eq!(*lazy, 44);
245    /// ```
246    #[inline]
247    #[unstable(feature = "lazy_get", issue = "129333")]
248    pub fn get_mut(this: &mut LazyLock<T, F>) -> Option<&mut T> {
249        // `state()` does not perform an atomic load, so prefer it over `is_complete()`.
250        let state = this.once.state();
251        match state {
252            // SAFETY:
253            // The closure has been run successfully, so `value` has been initialized.
254            ExclusiveState::Complete => Some(unsafe { &mut this.data.get_mut().value }),
255            _ => None,
256        }
257    }
258
259    /// Returns a reference to the value if initialized, or `None` if not.
260    ///
261    /// # Examples
262    ///
263    /// ```
264    /// #![feature(lazy_get)]
265    ///
266    /// use std::sync::LazyLock;
267    ///
268    /// let lazy = LazyLock::new(|| 92);
269    ///
270    /// assert_eq!(LazyLock::get(&lazy), None);
271    /// let _ = LazyLock::force(&lazy);
272    /// assert_eq!(LazyLock::get(&lazy), Some(&92));
273    /// ```
274    #[inline]
275    #[unstable(feature = "lazy_get", issue = "129333")]
276    pub fn get(this: &LazyLock<T, F>) -> Option<&T> {
277        if this.once.is_completed() {
278            // SAFETY:
279            // The closure has been run successfully, so `value` has been initialized
280            // and will not be modified again.
281            Some(unsafe { &(*this.data.get()).value })
282        } else {
283            None
284        }
285    }
286}
287
288#[stable(feature = "lazy_cell", since = "1.80.0")]
289impl<T, F> Drop for LazyLock<T, F> {
290    fn drop(&mut self) {
291        match self.once.state() {
292            ExclusiveState::Incomplete => unsafe { ManuallyDrop::drop(&mut self.data.get_mut().f) },
293            ExclusiveState::Complete => unsafe {
294                ManuallyDrop::drop(&mut self.data.get_mut().value)
295            },
296            ExclusiveState::Poisoned => {}
297        }
298    }
299}
300
301#[stable(feature = "lazy_cell", since = "1.80.0")]
302impl<T, F: FnOnce() -> T> Deref for LazyLock<T, F> {
303    type Target = T;
304
305    /// Dereferences the value.
306    ///
307    /// This method will block the calling thread if another initialization
308    /// routine is currently running.
309    ///
310    #[inline]
311    fn deref(&self) -> &T {
312        LazyLock::force(self)
313    }
314}
315
316#[stable(feature = "lazy_cell", since = "1.80.0")]
317impl<T: Default> Default for LazyLock<T> {
318    /// Creates a new lazy value using `Default` as the initializing function.
319    #[inline]
320    fn default() -> LazyLock<T> {
321        LazyLock::new(T::default)
322    }
323}
324
325#[stable(feature = "lazy_cell", since = "1.80.0")]
326impl<T: fmt::Debug, F> fmt::Debug for LazyLock<T, F> {
327    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
328        let mut d = f.debug_tuple("LazyLock");
329        match LazyLock::get(self) {
330            Some(v) => d.field(v),
331            None => d.field(&format_args!("<uninit>")),
332        };
333        d.finish()
334    }
335}
336
337#[cold]
338#[inline(never)]
339fn panic_poisoned() -> ! {
340    panic!("LazyLock instance has previously been poisoned")
341}
342
343// We never create a `&F` from a `&LazyLock<T, F>` so it is fine
344// to not impl `Sync` for `F`.
345#[stable(feature = "lazy_cell", since = "1.80.0")]
346unsafe impl<T: Sync + Send, F: Send> Sync for LazyLock<T, F> {}
347// auto-derived `Send` impl is OK.
348
349#[stable(feature = "lazy_cell", since = "1.80.0")]
350impl<T: RefUnwindSafe + UnwindSafe, F: UnwindSafe> RefUnwindSafe for LazyLock<T, F> {}
351#[stable(feature = "lazy_cell", since = "1.80.0")]
352impl<T: UnwindSafe, F: UnwindSafe> UnwindSafe for LazyLock<T, F> {}