std/sync/once_lock.rs
1use crate::cell::UnsafeCell;
2use crate::fmt;
3use crate::marker::PhantomData;
4use crate::mem::MaybeUninit;
5use crate::panic::{RefUnwindSafe, UnwindSafe};
6use crate::sync::Once;
7
8/// A synchronization primitive which can nominally be written to only once.
9///
10/// This type is a thread-safe [`OnceCell`], and can be used in statics.
11/// In many simple cases, you can use [`LazyLock<T, F>`] instead to get the benefits of this type
12/// with less effort: `LazyLock<T, F>` "looks like" `&T` because it initializes with `F` on deref!
13/// Where OnceLock shines is when LazyLock is too simple to support a given case, as LazyLock
14/// doesn't allow additional inputs to its function after you call [`LazyLock::new(|| ...)`].
15///
16/// A `OnceLock` can be thought of as a safe abstraction over uninitialized data that becomes
17/// initialized once written.
18///
19/// Unlike [`Mutex`](crate::sync::Mutex), `OnceLock` is never poisoned on panic.
20///
21/// [`OnceCell`]: crate::cell::OnceCell
22/// [`LazyLock<T, F>`]: crate::sync::LazyLock
23/// [`LazyLock::new(|| ...)`]: crate::sync::LazyLock::new
24///
25/// # Examples
26///
27/// Writing to a `OnceLock` from a separate thread:
28///
29/// ```
30/// use std::sync::OnceLock;
31///
32/// static CELL: OnceLock<usize> = OnceLock::new();
33///
34/// // `OnceLock` has not been written to yet.
35/// assert!(CELL.get().is_none());
36///
37/// // Spawn a thread and write to `OnceLock`.
38/// std::thread::spawn(|| {
39/// let value = CELL.get_or_init(|| 12345);
40/// assert_eq!(value, &12345);
41/// })
42/// .join()
43/// .unwrap();
44///
45/// // `OnceLock` now contains the value.
46/// assert_eq!(
47/// CELL.get(),
48/// Some(&12345),
49/// );
50/// ```
51///
52/// You can use `OnceLock` to implement a type that requires "append-only" logic:
53///
54/// ```
55/// use std::sync::{OnceLock, atomic::{AtomicU32, Ordering}};
56/// use std::thread;
57///
58/// struct OnceList<T> {
59/// data: OnceLock<T>,
60/// next: OnceLock<Box<OnceList<T>>>,
61/// }
62/// impl<T> OnceList<T> {
63/// const fn new() -> OnceList<T> {
64/// OnceList { data: OnceLock::new(), next: OnceLock::new() }
65/// }
66/// fn push(&self, value: T) {
67/// // FIXME: this impl is concise, but is also slow for long lists or many threads.
68/// // as an exercise, consider how you might improve on it while preserving the behavior
69/// if let Err(value) = self.data.set(value) {
70/// let next = self.next.get_or_init(|| Box::new(OnceList::new()));
71/// next.push(value)
72/// };
73/// }
74/// fn contains(&self, example: &T) -> bool
75/// where
76/// T: PartialEq,
77/// {
78/// self.data.get().map(|item| item == example).filter(|v| *v).unwrap_or_else(|| {
79/// self.next.get().map(|next| next.contains(example)).unwrap_or(false)
80/// })
81/// }
82/// }
83///
84/// // Let's exercise this new Sync append-only list by doing a little counting
85/// static LIST: OnceList<u32> = OnceList::new();
86/// static COUNTER: AtomicU32 = AtomicU32::new(0);
87///
88/// # const LEN: u32 = if cfg!(miri) { 50 } else { 1000 };
89/// # /*
90/// const LEN: u32 = 1000;
91/// # */
92/// thread::scope(|s| {
93/// for _ in 0..thread::available_parallelism().unwrap().get() {
94/// s.spawn(|| {
95/// while let i @ 0..LEN = COUNTER.fetch_add(1, Ordering::Relaxed) {
96/// LIST.push(i);
97/// }
98/// });
99/// }
100/// });
101///
102/// for i in 0..LEN {
103/// assert!(LIST.contains(&i));
104/// }
105///
106/// ```
107#[stable(feature = "once_cell", since = "1.70.0")]
108pub struct OnceLock<T> {
109 // FIXME(nonpoison_once): switch to nonpoison version once it is available
110 once: Once,
111 // Whether or not the value is initialized is tracked by `once.is_completed()`.
112 value: UnsafeCell<MaybeUninit<T>>,
113 /// `PhantomData` to make sure dropck understands we're dropping T in our Drop impl.
114 ///
115 /// ```compile_fail,E0597
116 /// use std::sync::OnceLock;
117 ///
118 /// struct A<'a>(&'a str);
119 ///
120 /// impl<'a> Drop for A<'a> {
121 /// fn drop(&mut self) {}
122 /// }
123 ///
124 /// let cell = OnceLock::new();
125 /// {
126 /// let s = String::new();
127 /// let _ = cell.set(A(&s));
128 /// }
129 /// ```
130 _marker: PhantomData<T>,
131}
132
133impl<T> OnceLock<T> {
134 /// Creates a new uninitialized cell.
135 #[inline]
136 #[must_use]
137 #[stable(feature = "once_cell", since = "1.70.0")]
138 #[rustc_const_stable(feature = "once_cell", since = "1.70.0")]
139 pub const fn new() -> OnceLock<T> {
140 OnceLock {
141 once: Once::new(),
142 value: UnsafeCell::new(MaybeUninit::uninit()),
143 _marker: PhantomData,
144 }
145 }
146
147 /// Gets the reference to the underlying value.
148 ///
149 /// Returns `None` if the cell is uninitialized, or being initialized.
150 /// This method never blocks.
151 #[inline]
152 #[stable(feature = "once_cell", since = "1.70.0")]
153 pub fn get(&self) -> Option<&T> {
154 if self.is_initialized() {
155 // Safe b/c checked is_initialized
156 Some(unsafe { self.get_unchecked() })
157 } else {
158 None
159 }
160 }
161
162 /// Gets the mutable reference to the underlying value.
163 ///
164 /// Returns `None` if the cell is uninitialized.
165 ///
166 /// This method never blocks. Since it borrows the `OnceLock` mutably,
167 /// it is statically guaranteed that no active borrows to the `OnceLock`
168 /// exist, including from other threads.
169 #[inline]
170 #[stable(feature = "once_cell", since = "1.70.0")]
171 pub fn get_mut(&mut self) -> Option<&mut T> {
172 if self.is_initialized() {
173 // Safe b/c checked is_initialized and we have a unique access
174 Some(unsafe { self.get_unchecked_mut() })
175 } else {
176 None
177 }
178 }
179
180 /// Blocks the current thread until the cell is initialized.
181 ///
182 /// # Example
183 ///
184 /// Waiting for a computation on another thread to finish:
185 /// ```rust
186 /// use std::thread;
187 /// use std::sync::OnceLock;
188 ///
189 /// let value = OnceLock::new();
190 ///
191 /// thread::scope(|s| {
192 /// s.spawn(|| value.set(1 + 1));
193 ///
194 /// let result = value.wait();
195 /// assert_eq!(result, &2);
196 /// })
197 /// ```
198 #[inline]
199 #[stable(feature = "once_wait", since = "1.86.0")]
200 pub fn wait(&self) -> &T {
201 self.once.wait_force();
202
203 unsafe { self.get_unchecked() }
204 }
205
206 /// Initializes the contents of the cell to `value`.
207 ///
208 /// May block if another thread is currently attempting to initialize the cell. The cell is
209 /// guaranteed to contain a value when `set` returns, though not necessarily the one provided.
210 ///
211 /// Returns `Ok(())` if the cell was uninitialized and
212 /// `Err(value)` if the cell was already initialized.
213 ///
214 /// # Examples
215 ///
216 /// ```
217 /// use std::sync::OnceLock;
218 ///
219 /// static CELL: OnceLock<i32> = OnceLock::new();
220 ///
221 /// fn main() {
222 /// assert!(CELL.get().is_none());
223 ///
224 /// std::thread::spawn(|| {
225 /// assert_eq!(CELL.set(92), Ok(()));
226 /// }).join().unwrap();
227 ///
228 /// assert_eq!(CELL.set(62), Err(62));
229 /// assert_eq!(CELL.get(), Some(&92));
230 /// }
231 /// ```
232 #[inline]
233 #[stable(feature = "once_cell", since = "1.70.0")]
234 pub fn set(&self, value: T) -> Result<(), T> {
235 match self.try_insert(value) {
236 Ok(_) => Ok(()),
237 Err((_, value)) => Err(value),
238 }
239 }
240
241 /// Initializes the contents of the cell to `value` if the cell was uninitialized,
242 /// then returns a reference to it.
243 ///
244 /// May block if another thread is currently attempting to initialize the cell. The cell is
245 /// guaranteed to contain a value when `try_insert` returns, though not necessarily the
246 /// one provided.
247 ///
248 /// Returns `Ok(&value)` if the cell was uninitialized and
249 /// `Err((¤t_value, value))` if it was already initialized.
250 ///
251 /// # Examples
252 ///
253 /// ```
254 /// #![feature(once_cell_try_insert)]
255 ///
256 /// use std::sync::OnceLock;
257 ///
258 /// static CELL: OnceLock<i32> = OnceLock::new();
259 ///
260 /// fn main() {
261 /// assert!(CELL.get().is_none());
262 ///
263 /// std::thread::spawn(|| {
264 /// assert_eq!(CELL.try_insert(92), Ok(&92));
265 /// }).join().unwrap();
266 ///
267 /// assert_eq!(CELL.try_insert(62), Err((&92, 62)));
268 /// assert_eq!(CELL.get(), Some(&92));
269 /// }
270 /// ```
271 #[inline]
272 #[unstable(feature = "once_cell_try_insert", issue = "116693")]
273 pub fn try_insert(&self, value: T) -> Result<&T, (&T, T)> {
274 let mut value = Some(value);
275 let res = self.get_or_init(|| value.take().unwrap());
276 match value {
277 None => Ok(res),
278 Some(value) => Err((res, value)),
279 }
280 }
281
282 /// Gets the contents of the cell, initializing it to `f()` if the cell
283 /// was uninitialized.
284 ///
285 /// Many threads may call `get_or_init` concurrently with different
286 /// initializing functions, but it is guaranteed that only one function
287 /// will be executed if the function doesn't panic.
288 ///
289 /// # Panics
290 ///
291 /// If `f()` panics, the panic is propagated to the caller, and the cell
292 /// remains uninitialized.
293 ///
294 /// It is an error to reentrantly initialize the cell from `f`. The
295 /// exact outcome is unspecified. Current implementation deadlocks, but
296 /// this may be changed to a panic in the future.
297 ///
298 /// # Examples
299 ///
300 /// ```
301 /// use std::sync::OnceLock;
302 ///
303 /// let cell = OnceLock::new();
304 /// let value = cell.get_or_init(|| 92);
305 /// assert_eq!(value, &92);
306 /// let value = cell.get_or_init(|| unreachable!());
307 /// assert_eq!(value, &92);
308 /// ```
309 #[inline]
310 #[stable(feature = "once_cell", since = "1.70.0")]
311 pub fn get_or_init<F>(&self, f: F) -> &T
312 where
313 F: FnOnce() -> T,
314 {
315 match self.get_or_try_init(|| Ok::<T, !>(f())) {
316 Ok(val) => val,
317 }
318 }
319
320 /// Gets the mutable reference of the contents of the cell, initializing
321 /// it to `f()` if the cell was uninitialized.
322 ///
323 /// This method never blocks. Since it borrows the `OnceLock` mutably,
324 /// it is statically guaranteed that no active borrows to the `OnceLock`
325 /// exist, including from other threads.
326 ///
327 /// # Panics
328 ///
329 /// If `f()` panics, the panic is propagated to the caller, and the cell
330 /// remains uninitialized.
331 ///
332 /// # Examples
333 ///
334 /// ```
335 /// #![feature(once_cell_get_mut)]
336 ///
337 /// use std::sync::OnceLock;
338 ///
339 /// let mut cell = OnceLock::new();
340 /// let value = cell.get_mut_or_init(|| 92);
341 /// assert_eq!(*value, 92);
342 ///
343 /// *value += 2;
344 /// assert_eq!(*value, 94);
345 ///
346 /// let value = cell.get_mut_or_init(|| unreachable!());
347 /// assert_eq!(*value, 94);
348 /// ```
349 #[inline]
350 #[unstable(feature = "once_cell_get_mut", issue = "121641")]
351 pub fn get_mut_or_init<F>(&mut self, f: F) -> &mut T
352 where
353 F: FnOnce() -> T,
354 {
355 match self.get_mut_or_try_init(|| Ok::<T, !>(f())) {
356 Ok(val) => val,
357 }
358 }
359
360 /// Gets the contents of the cell, initializing it to `f()` if
361 /// the cell was uninitialized. If the cell was uninitialized
362 /// and `f()` failed, an error is returned.
363 ///
364 /// # Panics
365 ///
366 /// If `f()` panics, the panic is propagated to the caller, and
367 /// the cell remains uninitialized.
368 ///
369 /// It is an error to reentrantly initialize the cell from `f`.
370 /// The exact outcome is unspecified. Current implementation
371 /// deadlocks, but this may be changed to a panic in the future.
372 ///
373 /// # Examples
374 ///
375 /// ```
376 /// #![feature(once_cell_try)]
377 ///
378 /// use std::sync::OnceLock;
379 ///
380 /// let cell = OnceLock::new();
381 /// assert_eq!(cell.get_or_try_init(|| Err(())), Err(()));
382 /// assert!(cell.get().is_none());
383 /// let value = cell.get_or_try_init(|| -> Result<i32, ()> {
384 /// Ok(92)
385 /// });
386 /// assert_eq!(value, Ok(&92));
387 /// assert_eq!(cell.get(), Some(&92))
388 /// ```
389 #[inline]
390 #[unstable(feature = "once_cell_try", issue = "109737")]
391 pub fn get_or_try_init<F, E>(&self, f: F) -> Result<&T, E>
392 where
393 F: FnOnce() -> Result<T, E>,
394 {
395 // Fast path check
396 // NOTE: We need to perform an acquire on the state in this method
397 // in order to correctly synchronize `LazyLock::force`. This is
398 // currently done by calling `self.get()`, which in turn calls
399 // `self.is_initialized()`, which in turn performs the acquire.
400 if let Some(value) = self.get() {
401 return Ok(value);
402 }
403 self.initialize(f)?;
404
405 debug_assert!(self.is_initialized());
406
407 // SAFETY: The inner value has been initialized
408 Ok(unsafe { self.get_unchecked() })
409 }
410
411 /// Gets the mutable reference of the contents of the cell, initializing
412 /// it to `f()` if the cell was uninitialized. If the cell was uninitialized
413 /// and `f()` failed, an error is returned.
414 ///
415 /// This method never blocks. Since it borrows the `OnceLock` mutably,
416 /// it is statically guaranteed that no active borrows to the `OnceLock`
417 /// exist, including from other threads.
418 ///
419 /// # Panics
420 ///
421 /// If `f()` panics, the panic is propagated to the caller, and
422 /// the cell remains uninitialized.
423 ///
424 /// # Examples
425 ///
426 /// ```
427 /// #![feature(once_cell_get_mut)]
428 ///
429 /// use std::sync::OnceLock;
430 ///
431 /// let mut cell: OnceLock<u32> = OnceLock::new();
432 ///
433 /// // Failed attempts to initialize the cell do not change its contents
434 /// assert!(cell.get_mut_or_try_init(|| "not a number!".parse()).is_err());
435 /// assert!(cell.get().is_none());
436 ///
437 /// let value = cell.get_mut_or_try_init(|| "1234".parse());
438 /// assert_eq!(value, Ok(&mut 1234));
439 /// *value.unwrap() += 2;
440 /// assert_eq!(cell.get(), Some(&1236))
441 /// ```
442 #[inline]
443 #[unstable(feature = "once_cell_get_mut", issue = "121641")]
444 pub fn get_mut_or_try_init<F, E>(&mut self, f: F) -> Result<&mut T, E>
445 where
446 F: FnOnce() -> Result<T, E>,
447 {
448 if self.get().is_none() {
449 self.initialize(f)?;
450 }
451 debug_assert!(self.is_initialized());
452 // SAFETY: The inner value has been initialized
453 Ok(unsafe { self.get_unchecked_mut() })
454 }
455
456 /// Consumes the `OnceLock`, returning the wrapped value. Returns
457 /// `None` if the cell was uninitialized.
458 ///
459 /// # Examples
460 ///
461 /// ```
462 /// use std::sync::OnceLock;
463 ///
464 /// let cell: OnceLock<String> = OnceLock::new();
465 /// assert_eq!(cell.into_inner(), None);
466 ///
467 /// let cell = OnceLock::new();
468 /// cell.set("hello".to_string()).unwrap();
469 /// assert_eq!(cell.into_inner(), Some("hello".to_string()));
470 /// ```
471 #[inline]
472 #[stable(feature = "once_cell", since = "1.70.0")]
473 pub fn into_inner(mut self) -> Option<T> {
474 self.take()
475 }
476
477 /// Takes the value out of this `OnceLock`, moving it back to an uninitialized state.
478 ///
479 /// Has no effect and returns `None` if the `OnceLock` was uninitialized.
480 ///
481 /// Since this method borrows the `OnceLock` mutably, it is statically guaranteed that
482 /// no active borrows to the `OnceLock` exist, including from other threads.
483 ///
484 /// # Examples
485 ///
486 /// ```
487 /// use std::sync::OnceLock;
488 ///
489 /// let mut cell: OnceLock<String> = OnceLock::new();
490 /// assert_eq!(cell.take(), None);
491 ///
492 /// let mut cell = OnceLock::new();
493 /// cell.set("hello".to_string()).unwrap();
494 /// assert_eq!(cell.take(), Some("hello".to_string()));
495 /// assert_eq!(cell.get(), None);
496 /// ```
497 #[inline]
498 #[stable(feature = "once_cell", since = "1.70.0")]
499 pub fn take(&mut self) -> Option<T> {
500 if self.is_initialized() {
501 self.once = Once::new();
502 // SAFETY: `self.value` is initialized and contains a valid `T`.
503 // `self.once` is reset, so `is_initialized()` will be false again
504 // which prevents the value from being read twice.
505 unsafe { Some((&mut *self.value.get()).assume_init_read()) }
506 } else {
507 None
508 }
509 }
510
511 #[inline]
512 fn is_initialized(&self) -> bool {
513 self.once.is_completed()
514 }
515
516 #[cold]
517 #[optimize(size)]
518 fn initialize<F, E>(&self, f: F) -> Result<(), E>
519 where
520 F: FnOnce() -> Result<T, E>,
521 {
522 let mut res: Result<(), E> = Ok(());
523 let slot = &self.value;
524
525 // Ignore poisoning from other threads
526 // If another thread panics, then we'll be able to run our closure
527 self.once.call_once_force(|p| {
528 match f() {
529 Ok(value) => {
530 unsafe { (&mut *slot.get()).write(value) };
531 }
532 Err(e) => {
533 res = Err(e);
534
535 // Treat the underlying `Once` as poisoned since we
536 // failed to initialize our value.
537 p.poison();
538 }
539 }
540 });
541 res
542 }
543
544 /// # Safety
545 ///
546 /// The cell must be initialized
547 #[inline]
548 unsafe fn get_unchecked(&self) -> &T {
549 debug_assert!(self.is_initialized());
550 unsafe { (&*self.value.get()).assume_init_ref() }
551 }
552
553 /// # Safety
554 ///
555 /// The cell must be initialized
556 #[inline]
557 unsafe fn get_unchecked_mut(&mut self) -> &mut T {
558 debug_assert!(self.is_initialized());
559 unsafe { (&mut *self.value.get()).assume_init_mut() }
560 }
561}
562
563// Why do we need `T: Send`?
564// Thread A creates a `OnceLock` and shares it with
565// scoped thread B, which fills the cell, which is
566// then destroyed by A. That is, destructor observes
567// a sent value.
568#[stable(feature = "once_cell", since = "1.70.0")]
569unsafe impl<T: Sync + Send> Sync for OnceLock<T> {}
570#[stable(feature = "once_cell", since = "1.70.0")]
571unsafe impl<T: Send> Send for OnceLock<T> {}
572
573#[stable(feature = "once_cell", since = "1.70.0")]
574impl<T: RefUnwindSafe + UnwindSafe> RefUnwindSafe for OnceLock<T> {}
575#[stable(feature = "once_cell", since = "1.70.0")]
576impl<T: UnwindSafe> UnwindSafe for OnceLock<T> {}
577
578#[stable(feature = "once_cell", since = "1.70.0")]
579impl<T> Default for OnceLock<T> {
580 /// Creates a new uninitialized cell.
581 ///
582 /// # Example
583 ///
584 /// ```
585 /// use std::sync::OnceLock;
586 ///
587 /// fn main() {
588 /// assert_eq!(OnceLock::<()>::new(), OnceLock::default());
589 /// }
590 /// ```
591 #[inline]
592 fn default() -> OnceLock<T> {
593 OnceLock::new()
594 }
595}
596
597#[stable(feature = "once_cell", since = "1.70.0")]
598impl<T: fmt::Debug> fmt::Debug for OnceLock<T> {
599 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
600 let mut d = f.debug_tuple("OnceLock");
601 match self.get() {
602 Some(v) => d.field(v),
603 None => d.field(&format_args!("<uninit>")),
604 };
605 d.finish()
606 }
607}
608
609#[stable(feature = "once_cell", since = "1.70.0")]
610impl<T: Clone> Clone for OnceLock<T> {
611 #[inline]
612 fn clone(&self) -> OnceLock<T> {
613 let cell = Self::new();
614 if let Some(value) = self.get() {
615 match cell.set(value.clone()) {
616 Ok(()) => (),
617 Err(_) => unreachable!(),
618 }
619 }
620 cell
621 }
622}
623
624#[stable(feature = "once_cell", since = "1.70.0")]
625impl<T> From<T> for OnceLock<T> {
626 /// Creates a new cell with its contents set to `value`.
627 ///
628 /// # Example
629 ///
630 /// ```
631 /// use std::sync::OnceLock;
632 ///
633 /// # fn main() -> Result<(), i32> {
634 /// let a = OnceLock::from(3);
635 /// let b = OnceLock::new();
636 /// b.set(3)?;
637 /// assert_eq!(a, b);
638 /// Ok(())
639 /// # }
640 /// ```
641 #[inline]
642 fn from(value: T) -> Self {
643 let cell = Self::new();
644 match cell.set(value) {
645 Ok(()) => cell,
646 Err(_) => unreachable!(),
647 }
648 }
649}
650
651#[stable(feature = "once_cell", since = "1.70.0")]
652impl<T: PartialEq> PartialEq for OnceLock<T> {
653 /// Equality for two `OnceLock`s.
654 ///
655 /// Two `OnceLock`s are equal if they either both contain values and their
656 /// values are equal, or if neither contains a value.
657 ///
658 /// # Examples
659 ///
660 /// ```
661 /// use std::sync::OnceLock;
662 ///
663 /// let five = OnceLock::new();
664 /// five.set(5).unwrap();
665 ///
666 /// let also_five = OnceLock::new();
667 /// also_five.set(5).unwrap();
668 ///
669 /// assert!(five == also_five);
670 ///
671 /// assert!(OnceLock::<u32>::new() == OnceLock::<u32>::new());
672 /// ```
673 #[inline]
674 fn eq(&self, other: &OnceLock<T>) -> bool {
675 self.get() == other.get()
676 }
677}
678
679#[stable(feature = "once_cell", since = "1.70.0")]
680impl<T: Eq> Eq for OnceLock<T> {}
681
682#[stable(feature = "once_cell", since = "1.70.0")]
683unsafe impl<#[may_dangle] T> Drop for OnceLock<T> {
684 #[inline]
685 fn drop(&mut self) {
686 if self.is_initialized() {
687 // SAFETY: The cell is initialized and being dropped, so it can't
688 // be accessed again. We also don't touch the `T` other than
689 // dropping it, which validates our usage of #[may_dangle].
690 unsafe { (&mut *self.value.get()).assume_init_drop() };
691 }
692 }
693}