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 /// Creates a new lazy value that is already initialized.
109 #[inline]
110 #[cfg(test)]
111 pub(crate) fn preinit(value: T) -> LazyLock<T, F> {
112 let once = Once::new();
113 once.call_once(|| {});
114 LazyLock { once, data: UnsafeCell::new(Data { value: ManuallyDrop::new(value) }) }
115 }
116
117 /// Consumes this `LazyLock` returning the stored value.
118 ///
119 /// Returns `Ok(value)` if `Lazy` is initialized and `Err(f)` otherwise.
120 ///
121 /// # Panics
122 ///
123 /// Panics if the lock is poisoned.
124 ///
125 /// # Examples
126 ///
127 /// ```
128 /// #![feature(lazy_cell_into_inner)]
129 ///
130 /// use std::sync::LazyLock;
131 ///
132 /// let hello = "Hello, World!".to_string();
133 ///
134 /// let lazy = LazyLock::new(|| hello.to_uppercase());
135 ///
136 /// assert_eq!(&*lazy, "HELLO, WORLD!");
137 /// assert_eq!(LazyLock::into_inner(lazy).ok(), Some("HELLO, WORLD!".to_string()));
138 /// ```
139 #[unstable(feature = "lazy_cell_into_inner", issue = "125623")]
140 pub fn into_inner(mut this: Self) -> Result<T, F> {
141 let state = this.once.state();
142 match state {
143 OnceExclusiveState::Poisoned => panic_poisoned(),
144 state => {
145 let this = ManuallyDrop::new(this);
146 let data = unsafe { ptr::read(&this.data) }.into_inner();
147 match state {
148 OnceExclusiveState::Incomplete => {
149 Err(ManuallyDrop::into_inner(unsafe { data.f }))
150 }
151 OnceExclusiveState::Complete => {
152 Ok(ManuallyDrop::into_inner(unsafe { data.value }))
153 }
154 OnceExclusiveState::Poisoned => unreachable!(),
155 }
156 }
157 }
158 }
159
160 /// Forces the evaluation of this lazy value and returns a mutable reference to
161 /// the result.
162 ///
163 /// # Panics
164 ///
165 /// If the initialization closure panics (the one that is passed to the [`new()`] method), the
166 /// panic is propagated to the caller, and the lock becomes poisoned. This will cause all future
167 /// accesses of the lock (via [`force()`] or a dereference) to panic.
168 ///
169 /// [`new()`]: LazyLock::new
170 /// [`force()`]: LazyLock::force
171 ///
172 /// # Examples
173 ///
174 /// ```
175 /// #![feature(lazy_get)]
176 /// use std::sync::LazyLock;
177 ///
178 /// let mut lazy = LazyLock::new(|| 92);
179 ///
180 /// let p = LazyLock::force_mut(&mut lazy);
181 /// assert_eq!(*p, 92);
182 /// *p = 44;
183 /// assert_eq!(*lazy, 44);
184 /// ```
185 #[inline]
186 #[unstable(feature = "lazy_get", issue = "129333")]
187 pub fn force_mut(this: &mut LazyLock<T, F>) -> &mut T {
188 #[cold]
189 /// # Safety
190 /// May only be called when the state is `Incomplete`.
191 unsafe fn really_init_mut<T, F: FnOnce() -> T>(this: &mut LazyLock<T, F>) -> &mut T {
192 struct PoisonOnPanic<'a, T, F>(&'a mut LazyLock<T, F>);
193 impl<T, F> Drop for PoisonOnPanic<'_, T, F> {
194 #[inline]
195 fn drop(&mut self) {
196 self.0.once.set_state(OnceExclusiveState::Poisoned);
197 }
198 }
199
200 // SAFETY: We always poison if the initializer panics (then we never check the data),
201 // or set the data on success.
202 let f = unsafe { ManuallyDrop::take(&mut this.data.get_mut().f) };
203 // INVARIANT: Initiated from mutable reference, don't drop because we read it.
204 let guard = PoisonOnPanic(this);
205 let data = f();
206 guard.0.data.get_mut().value = ManuallyDrop::new(data);
207 guard.0.once.set_state(OnceExclusiveState::Complete);
208 core::mem::forget(guard);
209 // SAFETY: We put the value there above.
210 unsafe { &mut this.data.get_mut().value }
211 }
212
213 let state = this.once.state();
214 match state {
215 OnceExclusiveState::Poisoned => panic_poisoned(),
216 // SAFETY: The `Once` states we completed the initialization.
217 OnceExclusiveState::Complete => unsafe { &mut this.data.get_mut().value },
218 // SAFETY: The state is `Incomplete`.
219 OnceExclusiveState::Incomplete => unsafe { really_init_mut(this) },
220 }
221 }
222
223 /// Forces the evaluation of this lazy value and returns a reference to
224 /// result. This is equivalent to the `Deref` impl, but is explicit.
225 ///
226 /// This method will block the calling thread if another initialization
227 /// routine is currently running.
228 ///
229 /// # Panics
230 ///
231 /// If the initialization closure panics (the one that is passed to the [`new()`] method), the
232 /// panic is propagated to the caller, and the lock becomes poisoned. This will cause all future
233 /// accesses of the lock (via [`force()`] or a dereference) to panic.
234 ///
235 /// [`new()`]: LazyLock::new
236 /// [`force()`]: LazyLock::force
237 ///
238 /// # Examples
239 ///
240 /// ```
241 /// use std::sync::LazyLock;
242 ///
243 /// let lazy = LazyLock::new(|| 92);
244 ///
245 /// assert_eq!(LazyLock::force(&lazy), &92);
246 /// assert_eq!(&*lazy, &92);
247 /// ```
248 #[inline]
249 #[stable(feature = "lazy_cell", since = "1.80.0")]
250 #[rustc_should_not_be_called_on_const_items]
251 pub fn force(this: &LazyLock<T, F>) -> &T {
252 this.once.call_once_force(|state| {
253 if state.is_poisoned() {
254 panic_poisoned();
255 }
256
257 // SAFETY: `call_once` only runs this closure once, ever.
258 let data = unsafe { &mut *this.data.get() };
259 let f = unsafe { ManuallyDrop::take(&mut data.f) };
260 let value = f();
261 data.value = ManuallyDrop::new(value);
262 });
263
264 // SAFETY:
265 // There are four possible scenarios:
266 // * the closure was called and initialized `value`.
267 // * the closure was called and panicked, so this point is never reached.
268 // * the closure was not called, but a previous call initialized `value`.
269 // * the closure was not called because the Once is poisoned, which we handled above.
270 // So `value` has definitely been initialized and will not be modified again.
271 unsafe { &*(*this.data.get()).value }
272 }
273}
274
275impl<T, F> LazyLock<T, F> {
276 /// Returns a mutable reference to the value if initialized. Otherwise (if uninitialized or
277 /// poisoned), returns `None`.
278 ///
279 /// # Examples
280 ///
281 /// ```
282 /// #![feature(lazy_get)]
283 ///
284 /// use std::sync::LazyLock;
285 ///
286 /// let mut lazy = LazyLock::new(|| 92);
287 ///
288 /// assert_eq!(LazyLock::get_mut(&mut lazy), None);
289 /// let _ = LazyLock::force(&lazy);
290 /// *LazyLock::get_mut(&mut lazy).unwrap() = 44;
291 /// assert_eq!(*lazy, 44);
292 /// ```
293 #[inline]
294 #[unstable(feature = "lazy_get", issue = "129333")]
295 pub fn get_mut(this: &mut LazyLock<T, F>) -> Option<&mut T> {
296 // `state()` does not perform an atomic load, so prefer it over `is_complete()`.
297 let state = this.once.state();
298 match state {
299 // SAFETY:
300 // The closure has been run successfully, so `value` has been initialized.
301 OnceExclusiveState::Complete => Some(unsafe { &mut this.data.get_mut().value }),
302 _ => None,
303 }
304 }
305
306 /// Returns a reference to the value if initialized. Otherwise (if uninitialized or poisoned),
307 /// returns `None`.
308 ///
309 /// # Examples
310 ///
311 /// ```
312 /// #![feature(lazy_get)]
313 ///
314 /// use std::sync::LazyLock;
315 ///
316 /// let lazy = LazyLock::new(|| 92);
317 ///
318 /// assert_eq!(LazyLock::get(&lazy), None);
319 /// let _ = LazyLock::force(&lazy);
320 /// assert_eq!(LazyLock::get(&lazy), Some(&92));
321 /// ```
322 #[inline]
323 #[unstable(feature = "lazy_get", issue = "129333")]
324 #[rustc_should_not_be_called_on_const_items]
325 pub fn get(this: &LazyLock<T, F>) -> Option<&T> {
326 if this.once.is_completed() {
327 // SAFETY:
328 // The closure has been run successfully, so `value` has been initialized
329 // and will not be modified again.
330 Some(unsafe { &(*this.data.get()).value })
331 } else {
332 None
333 }
334 }
335}
336
337#[stable(feature = "lazy_cell", since = "1.80.0")]
338impl<T, F> Drop for LazyLock<T, F> {
339 fn drop(&mut self) {
340 match self.once.state() {
341 OnceExclusiveState::Incomplete => unsafe {
342 ManuallyDrop::drop(&mut self.data.get_mut().f)
343 },
344 OnceExclusiveState::Complete => unsafe {
345 ManuallyDrop::drop(&mut self.data.get_mut().value)
346 },
347 OnceExclusiveState::Poisoned => {}
348 }
349 }
350}
351
352#[stable(feature = "lazy_cell", since = "1.80.0")]
353impl<T, F: FnOnce() -> T> Deref for LazyLock<T, F> {
354 type Target = T;
355
356 /// Dereferences the value.
357 ///
358 /// This method will block the calling thread if another initialization
359 /// routine is currently running.
360 ///
361 /// # Panics
362 ///
363 /// If the initialization closure panics (the one that is passed to the [`new()`] method), the
364 /// panic is propagated to the caller, and the lock becomes poisoned. This will cause all future
365 /// accesses of the lock (via [`force()`] or a dereference) to panic.
366 ///
367 /// [`new()`]: LazyLock::new
368 /// [`force()`]: LazyLock::force
369 #[inline]
370 fn deref(&self) -> &T {
371 LazyLock::force(self)
372 }
373}
374
375#[stable(feature = "lazy_deref_mut", since = "1.89.0")]
376impl<T, F: FnOnce() -> T> DerefMut for LazyLock<T, F> {
377 /// # Panics
378 ///
379 /// If the initialization closure panics (the one that is passed to the [`new()`] method), the
380 /// panic is propagated to the caller, and the lock becomes poisoned. This will cause all future
381 /// accesses of the lock (via [`force()`] or a dereference) to panic.
382 ///
383 /// [`new()`]: LazyLock::new
384 /// [`force()`]: LazyLock::force
385 #[inline]
386 fn deref_mut(&mut self) -> &mut T {
387 LazyLock::force_mut(self)
388 }
389}
390
391#[stable(feature = "lazy_cell", since = "1.80.0")]
392impl<T: Default> Default for LazyLock<T> {
393 /// Creates a new lazy value using `Default` as the initializing function.
394 #[inline]
395 fn default() -> LazyLock<T> {
396 LazyLock::new(T::default)
397 }
398}
399
400#[stable(feature = "lazy_cell", since = "1.80.0")]
401impl<T: fmt::Debug, F> fmt::Debug for LazyLock<T, F> {
402 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
403 let mut d = f.debug_tuple("LazyLock");
404 match LazyLock::get(self) {
405 Some(v) => d.field(v),
406 None => d.field(&format_args!("<uninit>")),
407 };
408 d.finish()
409 }
410}
411
412#[cold]
413#[inline(never)]
414fn panic_poisoned() -> ! {
415 panic!("LazyLock instance has previously been poisoned")
416}
417
418// We never create a `&F` from a `&LazyLock<T, F>` so it is fine
419// to not impl `Sync` for `F`.
420#[stable(feature = "lazy_cell", since = "1.80.0")]
421unsafe impl<T: Sync + Send, F: Send> Sync for LazyLock<T, F> {}
422// auto-derived `Send` impl is OK.
423
424#[stable(feature = "lazy_cell", since = "1.80.0")]
425impl<T: RefUnwindSafe + UnwindSafe, F: UnwindSafe> RefUnwindSafe for LazyLock<T, F> {}
426#[stable(feature = "lazy_cell", since = "1.80.0")]
427impl<T: UnwindSafe, F: UnwindSafe> UnwindSafe for LazyLock<T, F> {}