1 | use crate::cell::UnsafeCell; |
2 | use crate::fmt; |
3 | use crate::marker::PhantomData; |
4 | use crate::mem::MaybeUninit; |
5 | use crate::panic::{RefUnwindSafe, UnwindSafe}; |
6 | use crate::sync::Once; |
7 | |
8 | /// A synchronization primitive which can be written to only once. |
9 | /// |
10 | /// This type is a thread-safe [`OnceCell`], and can be used in statics. |
11 | /// |
12 | /// [`OnceCell`]: crate::cell::OnceCell |
13 | /// |
14 | /// # Examples |
15 | /// |
16 | /// Using `OnceLock` to store a function’s previously computed value (a.k.a. |
17 | /// ‘lazy static’ or ‘memoizing’): |
18 | /// |
19 | /// ``` |
20 | /// use std::sync::OnceLock; |
21 | /// |
22 | /// struct DeepThought { |
23 | /// answer: String, |
24 | /// } |
25 | /// |
26 | /// impl DeepThought { |
27 | /// # fn great_question() -> String { |
28 | /// # "42" .to_string() |
29 | /// # } |
30 | /// # |
31 | /// fn new() -> Self { |
32 | /// Self { |
33 | /// // M3 Ultra takes about 16 million years in --release config |
34 | /// answer: Self::great_question(), |
35 | /// } |
36 | /// } |
37 | /// } |
38 | /// |
39 | /// fn computation() -> &'static DeepThought { |
40 | /// // n.b. static items do not call [`Drop`] on program termination, so if |
41 | /// // [`DeepThought`] impls Drop, that will not be used for this instance. |
42 | /// static COMPUTATION: OnceLock<DeepThought> = OnceLock::new(); |
43 | /// COMPUTATION.get_or_init(|| DeepThought::new()) |
44 | /// } |
45 | /// |
46 | /// // The `DeepThought` is built, stored in the `OnceLock`, and returned. |
47 | /// let _ = computation().answer; |
48 | /// // The `DeepThought` is retrieved from the `OnceLock` and returned. |
49 | /// let _ = computation().answer; |
50 | /// ``` |
51 | /// |
52 | /// Writing to a `OnceLock` from a separate thread: |
53 | /// |
54 | /// ``` |
55 | /// use std::sync::OnceLock; |
56 | /// |
57 | /// static CELL: OnceLock<usize> = OnceLock::new(); |
58 | /// |
59 | /// // `OnceLock` has not been written to yet. |
60 | /// assert!(CELL.get().is_none()); |
61 | /// |
62 | /// // Spawn a thread and write to `OnceLock`. |
63 | /// std::thread::spawn(|| { |
64 | /// let value = CELL.get_or_init(|| 12345); |
65 | /// assert_eq!(value, &12345); |
66 | /// }) |
67 | /// .join() |
68 | /// .unwrap(); |
69 | /// |
70 | /// // `OnceLock` now contains the value. |
71 | /// assert_eq!( |
72 | /// CELL.get(), |
73 | /// Some(&12345), |
74 | /// ); |
75 | /// ``` |
76 | #[stable (feature = "once_cell" , since = "1.70.0" )] |
77 | pub struct OnceLock<T> { |
78 | once: Once, |
79 | // Whether or not the value is initialized is tracked by `once.is_completed()`. |
80 | value: UnsafeCell<MaybeUninit<T>>, |
81 | /// `PhantomData` to make sure dropck understands we're dropping T in our Drop impl. |
82 | /// |
83 | /// ```compile_fail,E0597 |
84 | /// use std::sync::OnceLock; |
85 | /// |
86 | /// struct A<'a>(&'a str); |
87 | /// |
88 | /// impl<'a> Drop for A<'a> { |
89 | /// fn drop(&mut self) {} |
90 | /// } |
91 | /// |
92 | /// let cell = OnceLock::new(); |
93 | /// { |
94 | /// let s = String::new(); |
95 | /// let _ = cell.set(A(&s)); |
96 | /// } |
97 | /// ``` |
98 | _marker: PhantomData<T>, |
99 | } |
100 | |
101 | impl<T> OnceLock<T> { |
102 | /// Creates a new empty cell. |
103 | #[inline ] |
104 | #[must_use ] |
105 | #[stable (feature = "once_cell" , since = "1.70.0" )] |
106 | #[rustc_const_stable (feature = "once_cell" , since = "1.70.0" )] |
107 | pub const fn new() -> OnceLock<T> { |
108 | OnceLock { |
109 | once: Once::new(), |
110 | value: UnsafeCell::new(MaybeUninit::uninit()), |
111 | _marker: PhantomData, |
112 | } |
113 | } |
114 | |
115 | /// Gets the reference to the underlying value. |
116 | /// |
117 | /// Returns `None` if the cell is empty, or being initialized. This |
118 | /// method never blocks. |
119 | #[inline ] |
120 | #[stable (feature = "once_cell" , since = "1.70.0" )] |
121 | pub fn get(&self) -> Option<&T> { |
122 | if self.is_initialized() { |
123 | // Safe b/c checked is_initialized |
124 | Some(unsafe { self.get_unchecked() }) |
125 | } else { |
126 | None |
127 | } |
128 | } |
129 | |
130 | /// Gets the mutable reference to the underlying value. |
131 | /// |
132 | /// Returns `None` if the cell is empty. This method never blocks. |
133 | #[inline ] |
134 | #[stable (feature = "once_cell" , since = "1.70.0" )] |
135 | pub fn get_mut(&mut self) -> Option<&mut T> { |
136 | if self.is_initialized() { |
137 | // Safe b/c checked is_initialized and we have a unique access |
138 | Some(unsafe { self.get_unchecked_mut() }) |
139 | } else { |
140 | None |
141 | } |
142 | } |
143 | |
144 | /// Sets the contents of this cell to `value`. |
145 | /// |
146 | /// May block if another thread is currently attempting to initialize the cell. The cell is |
147 | /// guaranteed to contain a value when set returns, though not necessarily the one provided. |
148 | /// |
149 | /// Returns `Ok(())` if the cell's value was set by this call. |
150 | /// |
151 | /// # Examples |
152 | /// |
153 | /// ``` |
154 | /// use std::sync::OnceLock; |
155 | /// |
156 | /// static CELL: OnceLock<i32> = OnceLock::new(); |
157 | /// |
158 | /// fn main() { |
159 | /// assert!(CELL.get().is_none()); |
160 | /// |
161 | /// std::thread::spawn(|| { |
162 | /// assert_eq!(CELL.set(92), Ok(())); |
163 | /// }).join().unwrap(); |
164 | /// |
165 | /// assert_eq!(CELL.set(62), Err(62)); |
166 | /// assert_eq!(CELL.get(), Some(&92)); |
167 | /// } |
168 | /// ``` |
169 | #[inline ] |
170 | #[stable (feature = "once_cell" , since = "1.70.0" )] |
171 | pub fn set(&self, value: T) -> Result<(), T> { |
172 | match self.try_insert(value) { |
173 | Ok(_) => Ok(()), |
174 | Err((_, value)) => Err(value), |
175 | } |
176 | } |
177 | |
178 | /// Sets the contents of this cell to `value` if the cell was empty, then |
179 | /// returns a reference to it. |
180 | /// |
181 | /// May block if another thread is currently attempting to initialize the cell. The cell is |
182 | /// guaranteed to contain a value when set returns, though not necessarily the one provided. |
183 | /// |
184 | /// Returns `Ok(&value)` if the cell was empty and `Err(¤t_value, value)` if it was full. |
185 | /// |
186 | /// # Examples |
187 | /// |
188 | /// ``` |
189 | /// #![feature(once_cell_try_insert)] |
190 | /// |
191 | /// use std::sync::OnceLock; |
192 | /// |
193 | /// static CELL: OnceLock<i32> = OnceLock::new(); |
194 | /// |
195 | /// fn main() { |
196 | /// assert!(CELL.get().is_none()); |
197 | /// |
198 | /// std::thread::spawn(|| { |
199 | /// assert_eq!(CELL.try_insert(92), Ok(&92)); |
200 | /// }).join().unwrap(); |
201 | /// |
202 | /// assert_eq!(CELL.try_insert(62), Err((&92, 62))); |
203 | /// assert_eq!(CELL.get(), Some(&92)); |
204 | /// } |
205 | /// ``` |
206 | #[inline ] |
207 | #[unstable (feature = "once_cell_try_insert" , issue = "116693" )] |
208 | pub fn try_insert(&self, value: T) -> Result<&T, (&T, T)> { |
209 | let mut value = Some(value); |
210 | let res = self.get_or_init(|| value.take().unwrap()); |
211 | match value { |
212 | None => Ok(res), |
213 | Some(value) => Err((res, value)), |
214 | } |
215 | } |
216 | |
217 | /// Gets the contents of the cell, initializing it with `f` if the cell |
218 | /// was empty. |
219 | /// |
220 | /// Many threads may call `get_or_init` concurrently with different |
221 | /// initializing functions, but it is guaranteed that only one function |
222 | /// will be executed. |
223 | /// |
224 | /// # Panics |
225 | /// |
226 | /// If `f` panics, the panic is propagated to the caller, and the cell |
227 | /// remains uninitialized. |
228 | /// |
229 | /// It is an error to reentrantly initialize the cell from `f`. The |
230 | /// exact outcome is unspecified. Current implementation deadlocks, but |
231 | /// this may be changed to a panic in the future. |
232 | /// |
233 | /// # Examples |
234 | /// |
235 | /// ``` |
236 | /// use std::sync::OnceLock; |
237 | /// |
238 | /// let cell = OnceLock::new(); |
239 | /// let value = cell.get_or_init(|| 92); |
240 | /// assert_eq!(value, &92); |
241 | /// let value = cell.get_or_init(|| unreachable!()); |
242 | /// assert_eq!(value, &92); |
243 | /// ``` |
244 | #[inline ] |
245 | #[stable (feature = "once_cell" , since = "1.70.0" )] |
246 | pub fn get_or_init<F>(&self, f: F) -> &T |
247 | where |
248 | F: FnOnce() -> T, |
249 | { |
250 | match self.get_or_try_init(|| Ok::<T, !>(f())) { |
251 | Ok(val) => val, |
252 | } |
253 | } |
254 | |
255 | /// Gets the mutable reference of the contents of the cell, initializing |
256 | /// it with `f` if the cell was empty. |
257 | /// |
258 | /// Many threads may call `get_mut_or_init` concurrently with different |
259 | /// initializing functions, but it is guaranteed that only one function |
260 | /// will be executed. |
261 | /// |
262 | /// # Panics |
263 | /// |
264 | /// If `f` panics, the panic is propagated to the caller, and the cell |
265 | /// remains uninitialized. |
266 | /// |
267 | /// # Examples |
268 | /// |
269 | /// ``` |
270 | /// #![feature(once_cell_get_mut)] |
271 | /// |
272 | /// use std::sync::OnceLock; |
273 | /// |
274 | /// let mut cell = OnceLock::new(); |
275 | /// let value = cell.get_mut_or_init(|| 92); |
276 | /// assert_eq!(*value, 92); |
277 | /// |
278 | /// *value += 2; |
279 | /// assert_eq!(*value, 94); |
280 | /// |
281 | /// let value = cell.get_mut_or_init(|| unreachable!()); |
282 | /// assert_eq!(*value, 94); |
283 | /// ``` |
284 | #[inline ] |
285 | #[unstable (feature = "once_cell_get_mut" , issue = "121641" )] |
286 | pub fn get_mut_or_init<F>(&mut self, f: F) -> &mut T |
287 | where |
288 | F: FnOnce() -> T, |
289 | { |
290 | match self.get_mut_or_try_init(|| Ok::<T, !>(f())) { |
291 | Ok(val) => val, |
292 | } |
293 | } |
294 | |
295 | /// Gets the contents of the cell, initializing it with `f` if |
296 | /// the cell was empty. If the cell was empty and `f` failed, an |
297 | /// error is returned. |
298 | /// |
299 | /// # Panics |
300 | /// |
301 | /// If `f` panics, the panic is propagated to the caller, and |
302 | /// the cell remains uninitialized. |
303 | /// |
304 | /// It is an error to reentrantly initialize the cell from `f`. |
305 | /// The exact outcome is unspecified. Current implementation |
306 | /// deadlocks, but this may be changed to a panic in the future. |
307 | /// |
308 | /// # Examples |
309 | /// |
310 | /// ``` |
311 | /// #![feature(once_cell_try)] |
312 | /// |
313 | /// use std::sync::OnceLock; |
314 | /// |
315 | /// let cell = OnceLock::new(); |
316 | /// assert_eq!(cell.get_or_try_init(|| Err(())), Err(())); |
317 | /// assert!(cell.get().is_none()); |
318 | /// let value = cell.get_or_try_init(|| -> Result<i32, ()> { |
319 | /// Ok(92) |
320 | /// }); |
321 | /// assert_eq!(value, Ok(&92)); |
322 | /// assert_eq!(cell.get(), Some(&92)) |
323 | /// ``` |
324 | #[inline ] |
325 | #[unstable (feature = "once_cell_try" , issue = "109737" )] |
326 | pub fn get_or_try_init<F, E>(&self, f: F) -> Result<&T, E> |
327 | where |
328 | F: FnOnce() -> Result<T, E>, |
329 | { |
330 | // Fast path check |
331 | // NOTE: We need to perform an acquire on the state in this method |
332 | // in order to correctly synchronize `LazyLock::force`. This is |
333 | // currently done by calling `self.get()`, which in turn calls |
334 | // `self.is_initialized()`, which in turn performs the acquire. |
335 | if let Some(value) = self.get() { |
336 | return Ok(value); |
337 | } |
338 | self.initialize(f)?; |
339 | |
340 | debug_assert!(self.is_initialized()); |
341 | |
342 | // SAFETY: The inner value has been initialized |
343 | Ok(unsafe { self.get_unchecked() }) |
344 | } |
345 | |
346 | /// Gets the mutable reference of the contents of the cell, initializing |
347 | /// it with `f` if the cell was empty. If the cell was empty and `f` failed, |
348 | /// an error is returned. |
349 | /// |
350 | /// # Panics |
351 | /// |
352 | /// If `f` panics, the panic is propagated to the caller, and |
353 | /// the cell remains uninitialized. |
354 | /// |
355 | /// # Examples |
356 | /// |
357 | /// ``` |
358 | /// #![feature(once_cell_get_mut)] |
359 | /// |
360 | /// use std::sync::OnceLock; |
361 | /// |
362 | /// let mut cell: OnceLock<u32> = OnceLock::new(); |
363 | /// |
364 | /// // Failed initializers do not change the value |
365 | /// assert!(cell.get_mut_or_try_init(|| "not a number!" .parse()).is_err()); |
366 | /// assert!(cell.get().is_none()); |
367 | /// |
368 | /// let value = cell.get_mut_or_try_init(|| "1234" .parse()); |
369 | /// assert_eq!(value, Ok(&mut 1234)); |
370 | /// *value.unwrap() += 2; |
371 | /// assert_eq!(cell.get(), Some(&1236)) |
372 | /// ``` |
373 | #[inline ] |
374 | #[unstable (feature = "once_cell_get_mut" , issue = "121641" )] |
375 | pub fn get_mut_or_try_init<F, E>(&mut self, f: F) -> Result<&mut T, E> |
376 | where |
377 | F: FnOnce() -> Result<T, E>, |
378 | { |
379 | if self.get().is_none() { |
380 | self.initialize(f)?; |
381 | } |
382 | debug_assert!(self.is_initialized()); |
383 | // SAFETY: The inner value has been initialized |
384 | Ok(unsafe { self.get_unchecked_mut() }) |
385 | } |
386 | |
387 | /// Consumes the `OnceLock`, returning the wrapped value. Returns |
388 | /// `None` if the cell was empty. |
389 | /// |
390 | /// # Examples |
391 | /// |
392 | /// ``` |
393 | /// use std::sync::OnceLock; |
394 | /// |
395 | /// let cell: OnceLock<String> = OnceLock::new(); |
396 | /// assert_eq!(cell.into_inner(), None); |
397 | /// |
398 | /// let cell = OnceLock::new(); |
399 | /// cell.set("hello" .to_string()).unwrap(); |
400 | /// assert_eq!(cell.into_inner(), Some("hello" .to_string())); |
401 | /// ``` |
402 | #[inline ] |
403 | #[stable (feature = "once_cell" , since = "1.70.0" )] |
404 | pub fn into_inner(mut self) -> Option<T> { |
405 | self.take() |
406 | } |
407 | |
408 | /// Takes the value out of this `OnceLock`, moving it back to an uninitialized state. |
409 | /// |
410 | /// Has no effect and returns `None` if the `OnceLock` hasn't been initialized. |
411 | /// |
412 | /// Safety is guaranteed by requiring a mutable reference. |
413 | /// |
414 | /// # Examples |
415 | /// |
416 | /// ``` |
417 | /// use std::sync::OnceLock; |
418 | /// |
419 | /// let mut cell: OnceLock<String> = OnceLock::new(); |
420 | /// assert_eq!(cell.take(), None); |
421 | /// |
422 | /// let mut cell = OnceLock::new(); |
423 | /// cell.set("hello" .to_string()).unwrap(); |
424 | /// assert_eq!(cell.take(), Some("hello" .to_string())); |
425 | /// assert_eq!(cell.get(), None); |
426 | /// ``` |
427 | #[inline ] |
428 | #[stable (feature = "once_cell" , since = "1.70.0" )] |
429 | pub fn take(&mut self) -> Option<T> { |
430 | if self.is_initialized() { |
431 | self.once = Once::new(); |
432 | // SAFETY: `self.value` is initialized and contains a valid `T`. |
433 | // `self.once` is reset, so `is_initialized()` will be false again |
434 | // which prevents the value from being read twice. |
435 | unsafe { Some((&mut *self.value.get()).assume_init_read()) } |
436 | } else { |
437 | None |
438 | } |
439 | } |
440 | |
441 | #[inline ] |
442 | fn is_initialized(&self) -> bool { |
443 | self.once.is_completed() |
444 | } |
445 | |
446 | #[cold ] |
447 | fn initialize<F, E>(&self, f: F) -> Result<(), E> |
448 | where |
449 | F: FnOnce() -> Result<T, E>, |
450 | { |
451 | let mut res: Result<(), E> = Ok(()); |
452 | let slot = &self.value; |
453 | |
454 | // Ignore poisoning from other threads |
455 | // If another thread panics, then we'll be able to run our closure |
456 | self.once.call_once_force(|p| { |
457 | match f() { |
458 | Ok(value) => { |
459 | unsafe { (&mut *slot.get()).write(value) }; |
460 | } |
461 | Err(e) => { |
462 | res = Err(e); |
463 | |
464 | // Treat the underlying `Once` as poisoned since we |
465 | // failed to initialize our value. Calls |
466 | p.poison(); |
467 | } |
468 | } |
469 | }); |
470 | res |
471 | } |
472 | |
473 | /// # Safety |
474 | /// |
475 | /// The value must be initialized |
476 | #[inline ] |
477 | unsafe fn get_unchecked(&self) -> &T { |
478 | debug_assert!(self.is_initialized()); |
479 | (&*self.value.get()).assume_init_ref() |
480 | } |
481 | |
482 | /// # Safety |
483 | /// |
484 | /// The value must be initialized |
485 | #[inline ] |
486 | unsafe fn get_unchecked_mut(&mut self) -> &mut T { |
487 | debug_assert!(self.is_initialized()); |
488 | (&mut *self.value.get()).assume_init_mut() |
489 | } |
490 | } |
491 | |
492 | // Why do we need `T: Send`? |
493 | // Thread A creates a `OnceLock` and shares it with |
494 | // scoped thread B, which fills the cell, which is |
495 | // then destroyed by A. That is, destructor observes |
496 | // a sent value. |
497 | #[stable (feature = "once_cell" , since = "1.70.0" )] |
498 | unsafe impl<T: Sync + Send> Sync for OnceLock<T> {} |
499 | #[stable (feature = "once_cell" , since = "1.70.0" )] |
500 | unsafe impl<T: Send> Send for OnceLock<T> {} |
501 | |
502 | #[stable (feature = "once_cell" , since = "1.70.0" )] |
503 | impl<T: RefUnwindSafe + UnwindSafe> RefUnwindSafe for OnceLock<T> {} |
504 | #[stable (feature = "once_cell" , since = "1.70.0" )] |
505 | impl<T: UnwindSafe> UnwindSafe for OnceLock<T> {} |
506 | |
507 | #[stable (feature = "once_cell" , since = "1.70.0" )] |
508 | impl<T> Default for OnceLock<T> { |
509 | /// Creates a new empty cell. |
510 | /// |
511 | /// # Example |
512 | /// |
513 | /// ``` |
514 | /// use std::sync::OnceLock; |
515 | /// |
516 | /// fn main() { |
517 | /// assert_eq!(OnceLock::<()>::new(), OnceLock::default()); |
518 | /// } |
519 | /// ``` |
520 | #[inline ] |
521 | fn default() -> OnceLock<T> { |
522 | OnceLock::new() |
523 | } |
524 | } |
525 | |
526 | #[stable (feature = "once_cell" , since = "1.70.0" )] |
527 | impl<T: fmt::Debug> fmt::Debug for OnceLock<T> { |
528 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
529 | let mut d: DebugTuple<'_, '_> = f.debug_tuple(name:"OnceLock" ); |
530 | match self.get() { |
531 | Some(v: &T) => d.field(v), |
532 | None => d.field(&format_args!("<uninit>" )), |
533 | }; |
534 | d.finish() |
535 | } |
536 | } |
537 | |
538 | #[stable (feature = "once_cell" , since = "1.70.0" )] |
539 | impl<T: Clone> Clone for OnceLock<T> { |
540 | #[inline ] |
541 | fn clone(&self) -> OnceLock<T> { |
542 | let cell: OnceLock = Self::new(); |
543 | if let Some(value: &T) = self.get() { |
544 | match cell.set(value.clone()) { |
545 | Ok(()) => (), |
546 | Err(_) => unreachable!(), |
547 | } |
548 | } |
549 | cell |
550 | } |
551 | } |
552 | |
553 | #[stable (feature = "once_cell" , since = "1.70.0" )] |
554 | impl<T> From<T> for OnceLock<T> { |
555 | /// Create a new cell with its contents set to `value`. |
556 | /// |
557 | /// # Example |
558 | /// |
559 | /// ``` |
560 | /// use std::sync::OnceLock; |
561 | /// |
562 | /// # fn main() -> Result<(), i32> { |
563 | /// let a = OnceLock::from(3); |
564 | /// let b = OnceLock::new(); |
565 | /// b.set(3)?; |
566 | /// assert_eq!(a, b); |
567 | /// Ok(()) |
568 | /// # } |
569 | /// ``` |
570 | #[inline ] |
571 | fn from(value: T) -> Self { |
572 | let cell = Self::new(); |
573 | match cell.set(value) { |
574 | Ok(()) => cell, |
575 | Err(_) => unreachable!(), |
576 | } |
577 | } |
578 | } |
579 | |
580 | #[stable (feature = "once_cell" , since = "1.70.0" )] |
581 | impl<T: PartialEq> PartialEq for OnceLock<T> { |
582 | #[inline ] |
583 | fn eq(&self, other: &OnceLock<T>) -> bool { |
584 | self.get() == other.get() |
585 | } |
586 | } |
587 | |
588 | #[stable (feature = "once_cell" , since = "1.70.0" )] |
589 | impl<T: Eq> Eq for OnceLock<T> {} |
590 | |
591 | #[stable (feature = "once_cell" , since = "1.70.0" )] |
592 | unsafe impl<#[may_dangle ] T> Drop for OnceLock<T> { |
593 | #[inline ] |
594 | fn drop(&mut self) { |
595 | if self.is_initialized() { |
596 | // SAFETY: The cell is initialized and being dropped, so it can't |
597 | // be accessed again. We also don't touch the `T` other than |
598 | // dropping it, which validates our usage of #[may_dangle]. |
599 | unsafe { (&mut *self.value.get()).assume_init_drop() }; |
600 | } |
601 | } |
602 | } |
603 | |
604 | #[cfg (test)] |
605 | mod tests; |
606 | |