1 | use super::poison::once::ExclusiveState; |
2 | use crate::cell::UnsafeCell; |
3 | use crate::mem::ManuallyDrop; |
4 | use crate::ops::{Deref, DerefMut}; |
5 | use crate::panic::{RefUnwindSafe, UnwindSafe}; |
6 | use crate::sync::Once; |
7 | use 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. |
14 | union 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" )] |
65 | pub 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 | |
71 | impl<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 | |
229 | impl<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" )] |
289 | impl<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" )] |
302 | impl<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_deref_mut" , since = "CURRENT_RUSTC_VERSION" )] |
317 | impl<T, F: FnOnce() -> T> DerefMut for LazyLock<T, F> { |
318 | #[inline ] |
319 | fn deref_mut(&mut self) -> &mut T { |
320 | LazyLock::force_mut(self) |
321 | } |
322 | } |
323 | |
324 | #[stable (feature = "lazy_cell" , since = "1.80.0" )] |
325 | impl<T: Default> Default for LazyLock<T> { |
326 | /// Creates a new lazy value using `Default` as the initializing function. |
327 | #[inline ] |
328 | fn default() -> LazyLock<T> { |
329 | LazyLock::new(T::default) |
330 | } |
331 | } |
332 | |
333 | #[stable (feature = "lazy_cell" , since = "1.80.0" )] |
334 | impl<T: fmt::Debug, F> fmt::Debug for LazyLock<T, F> { |
335 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
336 | let mut d: DebugTuple<'_, '_> = f.debug_tuple(name:"LazyLock" ); |
337 | match LazyLock::get(self) { |
338 | Some(v: &T) => d.field(v), |
339 | None => d.field(&format_args!("<uninit>" )), |
340 | }; |
341 | d.finish() |
342 | } |
343 | } |
344 | |
345 | #[cold ] |
346 | #[inline (never)] |
347 | fn panic_poisoned() -> ! { |
348 | panic!("LazyLock instance has previously been poisoned" ) |
349 | } |
350 | |
351 | // We never create a `&F` from a `&LazyLock<T, F>` so it is fine |
352 | // to not impl `Sync` for `F`. |
353 | #[stable (feature = "lazy_cell" , since = "1.80.0" )] |
354 | unsafe impl<T: Sync + Send, F: Send> Sync for LazyLock<T, F> {} |
355 | // auto-derived `Send` impl is OK. |
356 | |
357 | #[stable (feature = "lazy_cell" , since = "1.80.0" )] |
358 | impl<T: RefUnwindSafe + UnwindSafe, F: UnwindSafe> RefUnwindSafe for LazyLock<T, F> {} |
359 | #[stable (feature = "lazy_cell" , since = "1.80.0" )] |
360 | impl<T: UnwindSafe, F: UnwindSafe> UnwindSafe for LazyLock<T, F> {} |
361 | |