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> {}