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 #[rustc_should_not_be_called_on_const_items]
154 pub fn get(&self) -> Option<&T> {
155 if self.is_initialized() {
156 // Safe b/c checked is_initialized
157 Some(unsafe { self.get_unchecked() })
158 } else {
159 None
160 }
161 }
162
163 /// Gets the mutable reference to the underlying value.
164 ///
165 /// Returns `None` if the cell is uninitialized.
166 ///
167 /// This method never blocks. Since it borrows the `OnceLock` mutably,
168 /// it is statically guaranteed that no active borrows to the `OnceLock`
169 /// exist, including from other threads.
170 #[inline]
171 #[stable(feature = "once_cell", since = "1.70.0")]
172 pub fn get_mut(&mut self) -> Option<&mut T> {
173 if self.is_initialized() {
174 // Safe b/c checked is_initialized and we have a unique access
175 Some(unsafe { self.get_unchecked_mut() })
176 } else {
177 None
178 }
179 }
180
181 /// Blocks the current thread until the cell is initialized.
182 ///
183 /// # Example
184 ///
185 /// Waiting for a computation on another thread to finish:
186 /// ```rust
187 /// use std::thread;
188 /// use std::sync::OnceLock;
189 ///
190 /// let value = OnceLock::new();
191 ///
192 /// thread::scope(|s| {
193 /// s.spawn(|| value.set(1 + 1));
194 ///
195 /// let result = value.wait();
196 /// assert_eq!(result, &2);
197 /// })
198 /// ```
199 #[inline]
200 #[stable(feature = "once_wait", since = "1.86.0")]
201 #[rustc_should_not_be_called_on_const_items]
202 pub fn wait(&self) -> &T {
203 self.once.wait_force();
204
205 unsafe { self.get_unchecked() }
206 }
207
208 /// Initializes the contents of the cell to `value`.
209 ///
210 /// May block if another thread is currently attempting to initialize the cell. The cell is
211 /// guaranteed to contain a value when `set` returns, though not necessarily the one provided.
212 ///
213 /// Returns `Ok(())` if the cell was uninitialized and
214 /// `Err(value)` if the cell was already initialized.
215 ///
216 /// # Examples
217 ///
218 /// ```
219 /// use std::sync::OnceLock;
220 ///
221 /// static CELL: OnceLock<i32> = OnceLock::new();
222 ///
223 /// fn main() {
224 /// assert!(CELL.get().is_none());
225 ///
226 /// std::thread::spawn(|| {
227 /// assert_eq!(CELL.set(92), Ok(()));
228 /// }).join().unwrap();
229 ///
230 /// assert_eq!(CELL.set(62), Err(62));
231 /// assert_eq!(CELL.get(), Some(&92));
232 /// }
233 /// ```
234 #[inline]
235 #[stable(feature = "once_cell", since = "1.70.0")]
236 #[rustc_should_not_be_called_on_const_items]
237 pub fn set(&self, value: T) -> Result<(), T> {
238 match self.try_insert(value) {
239 Ok(_) => Ok(()),
240 Err((_, value)) => Err(value),
241 }
242 }
243
244 /// Initializes the contents of the cell to `value` if the cell was uninitialized,
245 /// then returns a reference to it.
246 ///
247 /// May block if another thread is currently attempting to initialize the cell. The cell is
248 /// guaranteed to contain a value when `try_insert` returns, though not necessarily the
249 /// one provided.
250 ///
251 /// Returns `Ok(&value)` if the cell was uninitialized and
252 /// `Err((¤t_value, value))` if it was already initialized.
253 ///
254 /// # Examples
255 ///
256 /// ```
257 /// #![feature(once_cell_try_insert)]
258 ///
259 /// use std::sync::OnceLock;
260 ///
261 /// static CELL: OnceLock<i32> = OnceLock::new();
262 ///
263 /// fn main() {
264 /// assert!(CELL.get().is_none());
265 ///
266 /// std::thread::spawn(|| {
267 /// assert_eq!(CELL.try_insert(92), Ok(&92));
268 /// }).join().unwrap();
269 ///
270 /// assert_eq!(CELL.try_insert(62), Err((&92, 62)));
271 /// assert_eq!(CELL.get(), Some(&92));
272 /// }
273 /// ```
274 #[inline]
275 #[unstable(feature = "once_cell_try_insert", issue = "116693")]
276 #[rustc_should_not_be_called_on_const_items]
277 pub fn try_insert(&self, value: T) -> Result<&T, (&T, T)> {
278 let mut value = Some(value);
279 let res = self.get_or_init(|| value.take().unwrap());
280 match value {
281 None => Ok(res),
282 Some(value) => Err((res, value)),
283 }
284 }
285
286 /// Gets the contents of the cell, initializing it to `f()` if the cell
287 /// was uninitialized.
288 ///
289 /// Many threads may call `get_or_init` concurrently with different
290 /// initializing functions, but it is guaranteed that only one function
291 /// will be executed if the function doesn't panic.
292 ///
293 /// # Panics
294 ///
295 /// If `f()` panics, the panic is propagated to the caller, and the cell
296 /// remains uninitialized.
297 ///
298 /// It is an error to reentrantly initialize the cell from `f`. The
299 /// exact outcome is unspecified. Current implementation deadlocks, but
300 /// this may be changed to a panic in the future.
301 ///
302 /// # Examples
303 ///
304 /// ```
305 /// use std::sync::OnceLock;
306 ///
307 /// let cell = OnceLock::new();
308 /// let value = cell.get_or_init(|| 92);
309 /// assert_eq!(value, &92);
310 /// let value = cell.get_or_init(|| unreachable!());
311 /// assert_eq!(value, &92);
312 /// ```
313 #[inline]
314 #[stable(feature = "once_cell", since = "1.70.0")]
315 #[rustc_should_not_be_called_on_const_items]
316 pub fn get_or_init<F>(&self, f: F) -> &T
317 where
318 F: FnOnce() -> T,
319 {
320 match self.get_or_try_init(|| Ok::<T, !>(f())) {
321 Ok(val) => val,
322 }
323 }
324
325 /// Gets the mutable reference of the contents of the cell, initializing
326 /// it to `f()` if the cell was uninitialized.
327 ///
328 /// This method never blocks. Since it borrows the `OnceLock` mutably,
329 /// it is statically guaranteed that no active borrows to the `OnceLock`
330 /// exist, including from other threads.
331 ///
332 /// # Panics
333 ///
334 /// If `f()` panics, the panic is propagated to the caller, and the cell
335 /// remains uninitialized.
336 ///
337 /// # Examples
338 ///
339 /// ```
340 /// #![feature(once_cell_get_mut)]
341 ///
342 /// use std::sync::OnceLock;
343 ///
344 /// let mut cell = OnceLock::new();
345 /// let value = cell.get_mut_or_init(|| 92);
346 /// assert_eq!(*value, 92);
347 ///
348 /// *value += 2;
349 /// assert_eq!(*value, 94);
350 ///
351 /// let value = cell.get_mut_or_init(|| unreachable!());
352 /// assert_eq!(*value, 94);
353 /// ```
354 #[inline]
355 #[unstable(feature = "once_cell_get_mut", issue = "121641")]
356 pub fn get_mut_or_init<F>(&mut self, f: F) -> &mut T
357 where
358 F: FnOnce() -> T,
359 {
360 match self.get_mut_or_try_init(|| Ok::<T, !>(f())) {
361 Ok(val) => val,
362 }
363 }
364
365 /// Gets the contents of the cell, initializing it to `f()` if
366 /// the cell was uninitialized. If the cell was uninitialized
367 /// and `f()` failed, an error is returned.
368 ///
369 /// # Panics
370 ///
371 /// If `f()` panics, the panic is propagated to the caller, and
372 /// the cell remains uninitialized.
373 ///
374 /// It is an error to reentrantly initialize the cell from `f`.
375 /// The exact outcome is unspecified. Current implementation
376 /// deadlocks, but this may be changed to a panic in the future.
377 ///
378 /// # Examples
379 ///
380 /// ```
381 /// #![feature(once_cell_try)]
382 ///
383 /// use std::sync::OnceLock;
384 ///
385 /// let cell = OnceLock::new();
386 /// assert_eq!(cell.get_or_try_init(|| Err(())), Err(()));
387 /// assert!(cell.get().is_none());
388 /// let value = cell.get_or_try_init(|| -> Result<i32, ()> {
389 /// Ok(92)
390 /// });
391 /// assert_eq!(value, Ok(&92));
392 /// assert_eq!(cell.get(), Some(&92))
393 /// ```
394 #[inline]
395 #[unstable(feature = "once_cell_try", issue = "109737")]
396 #[rustc_should_not_be_called_on_const_items]
397 pub fn get_or_try_init<F, E>(&self, f: F) -> Result<&T, E>
398 where
399 F: FnOnce() -> Result<T, E>,
400 {
401 // Fast path check
402 // NOTE: We need to perform an acquire on the state in this method
403 // in order to correctly synchronize `LazyLock::force`. This is
404 // currently done by calling `self.get()`, which in turn calls
405 // `self.is_initialized()`, which in turn performs the acquire.
406 if let Some(value) = self.get() {
407 return Ok(value);
408 }
409 self.initialize(f)?;
410
411 debug_assert!(self.is_initialized());
412
413 // SAFETY: The inner value has been initialized
414 Ok(unsafe { self.get_unchecked() })
415 }
416
417 /// Gets the mutable reference of the contents of the cell, initializing
418 /// it to `f()` if the cell was uninitialized. If the cell was uninitialized
419 /// and `f()` failed, an error is returned.
420 ///
421 /// This method never blocks. Since it borrows the `OnceLock` mutably,
422 /// it is statically guaranteed that no active borrows to the `OnceLock`
423 /// exist, including from other threads.
424 ///
425 /// # Panics
426 ///
427 /// If `f()` panics, the panic is propagated to the caller, and
428 /// the cell remains uninitialized.
429 ///
430 /// # Examples
431 ///
432 /// ```
433 /// #![feature(once_cell_get_mut)]
434 ///
435 /// use std::sync::OnceLock;
436 ///
437 /// let mut cell: OnceLock<u32> = OnceLock::new();
438 ///
439 /// // Failed attempts to initialize the cell do not change its contents
440 /// assert!(cell.get_mut_or_try_init(|| "not a number!".parse()).is_err());
441 /// assert!(cell.get().is_none());
442 ///
443 /// let value = cell.get_mut_or_try_init(|| "1234".parse());
444 /// assert_eq!(value, Ok(&mut 1234));
445 /// *value.unwrap() += 2;
446 /// assert_eq!(cell.get(), Some(&1236))
447 /// ```
448 #[inline]
449 #[unstable(feature = "once_cell_get_mut", issue = "121641")]
450 pub fn get_mut_or_try_init<F, E>(&mut self, f: F) -> Result<&mut T, E>
451 where
452 F: FnOnce() -> Result<T, E>,
453 {
454 if self.get().is_none() {
455 self.initialize(f)?;
456 }
457 debug_assert!(self.is_initialized());
458 // SAFETY: The inner value has been initialized
459 Ok(unsafe { self.get_unchecked_mut() })
460 }
461
462 /// Consumes the `OnceLock`, returning the wrapped value. Returns
463 /// `None` if the cell was uninitialized.
464 ///
465 /// # Examples
466 ///
467 /// ```
468 /// use std::sync::OnceLock;
469 ///
470 /// let cell: OnceLock<String> = OnceLock::new();
471 /// assert_eq!(cell.into_inner(), None);
472 ///
473 /// let cell = OnceLock::new();
474 /// cell.set("hello".to_string()).unwrap();
475 /// assert_eq!(cell.into_inner(), Some("hello".to_string()));
476 /// ```
477 #[inline]
478 #[stable(feature = "once_cell", since = "1.70.0")]
479 pub fn into_inner(mut self) -> Option<T> {
480 self.take()
481 }
482
483 /// Takes the value out of this `OnceLock`, moving it back to an uninitialized state.
484 ///
485 /// Has no effect and returns `None` if the `OnceLock` was uninitialized.
486 ///
487 /// Since this method borrows the `OnceLock` mutably, it is statically guaranteed that
488 /// no active borrows to the `OnceLock` exist, including from other threads.
489 ///
490 /// # Examples
491 ///
492 /// ```
493 /// use std::sync::OnceLock;
494 ///
495 /// let mut cell: OnceLock<String> = OnceLock::new();
496 /// assert_eq!(cell.take(), None);
497 ///
498 /// let mut cell = OnceLock::new();
499 /// cell.set("hello".to_string()).unwrap();
500 /// assert_eq!(cell.take(), Some("hello".to_string()));
501 /// assert_eq!(cell.get(), None);
502 /// ```
503 #[inline]
504 #[stable(feature = "once_cell", since = "1.70.0")]
505 pub fn take(&mut self) -> Option<T> {
506 if self.is_initialized() {
507 self.once = Once::new();
508 // SAFETY: `self.value` is initialized and contains a valid `T`.
509 // `self.once` is reset, so `is_initialized()` will be false again
510 // which prevents the value from being read twice.
511 unsafe { Some((&mut *self.value.get()).assume_init_read()) }
512 } else {
513 None
514 }
515 }
516
517 #[inline]
518 fn is_initialized(&self) -> bool {
519 self.once.is_completed()
520 }
521
522 #[cold]
523 #[optimize(size)]
524 fn initialize<F, E>(&self, f: F) -> Result<(), E>
525 where
526 F: FnOnce() -> Result<T, E>,
527 {
528 let mut res: Result<(), E> = Ok(());
529 let slot = &self.value;
530
531 // Ignore poisoning from other threads
532 // If another thread panics, then we'll be able to run our closure
533 self.once.call_once_force(|p| {
534 match f() {
535 Ok(value) => {
536 unsafe { (&mut *slot.get()).write(value) };
537 }
538 Err(e) => {
539 res = Err(e);
540
541 // Treat the underlying `Once` as poisoned since we
542 // failed to initialize our value.
543 p.poison();
544 }
545 }
546 });
547 res
548 }
549
550 /// # Safety
551 ///
552 /// The cell must be initialized
553 #[inline]
554 unsafe fn get_unchecked(&self) -> &T {
555 debug_assert!(self.is_initialized());
556 unsafe { (&*self.value.get()).assume_init_ref() }
557 }
558
559 /// # Safety
560 ///
561 /// The cell must be initialized
562 #[inline]
563 unsafe fn get_unchecked_mut(&mut self) -> &mut T {
564 debug_assert!(self.is_initialized());
565 unsafe { (&mut *self.value.get()).assume_init_mut() }
566 }
567}
568
569// Why do we need `T: Send`?
570// Thread A creates a `OnceLock` and shares it with
571// scoped thread B, which fills the cell, which is
572// then destroyed by A. That is, destructor observes
573// a sent value.
574#[stable(feature = "once_cell", since = "1.70.0")]
575unsafe impl<T: Sync + Send> Sync for OnceLock<T> {}
576#[stable(feature = "once_cell", since = "1.70.0")]
577unsafe impl<T: Send> Send for OnceLock<T> {}
578
579#[stable(feature = "once_cell", since = "1.70.0")]
580impl<T: RefUnwindSafe + UnwindSafe> RefUnwindSafe for OnceLock<T> {}
581#[stable(feature = "once_cell", since = "1.70.0")]
582impl<T: UnwindSafe> UnwindSafe for OnceLock<T> {}
583
584#[stable(feature = "once_cell", since = "1.70.0")]
585impl<T> Default for OnceLock<T> {
586 /// Creates a new uninitialized cell.
587 ///
588 /// # Example
589 ///
590 /// ```
591 /// use std::sync::OnceLock;
592 ///
593 /// fn main() {
594 /// assert_eq!(OnceLock::<()>::new(), OnceLock::default());
595 /// }
596 /// ```
597 #[inline]
598 fn default() -> OnceLock<T> {
599 OnceLock::new()
600 }
601}
602
603#[stable(feature = "once_cell", since = "1.70.0")]
604impl<T: fmt::Debug> fmt::Debug for OnceLock<T> {
605 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
606 let mut d = f.debug_tuple("OnceLock");
607 match self.get() {
608 Some(v) => d.field(v),
609 None => d.field(&format_args!("<uninit>")),
610 };
611 d.finish()
612 }
613}
614
615#[stable(feature = "once_cell", since = "1.70.0")]
616impl<T: Clone> Clone for OnceLock<T> {
617 #[inline]
618 fn clone(&self) -> OnceLock<T> {
619 let cell = Self::new();
620 if let Some(value) = self.get() {
621 match cell.set(value.clone()) {
622 Ok(()) => (),
623 Err(_) => unreachable!(),
624 }
625 }
626 cell
627 }
628}
629
630#[stable(feature = "once_cell", since = "1.70.0")]
631impl<T> From<T> for OnceLock<T> {
632 /// Creates a new cell with its contents set to `value`.
633 ///
634 /// # Example
635 ///
636 /// ```
637 /// use std::sync::OnceLock;
638 ///
639 /// # fn main() -> Result<(), i32> {
640 /// let a = OnceLock::from(3);
641 /// let b = OnceLock::new();
642 /// b.set(3)?;
643 /// assert_eq!(a, b);
644 /// Ok(())
645 /// # }
646 /// ```
647 #[inline]
648 fn from(value: T) -> Self {
649 let cell = Self::new();
650 match cell.set(value) {
651 Ok(()) => cell,
652 Err(_) => unreachable!(),
653 }
654 }
655}
656
657#[stable(feature = "once_cell", since = "1.70.0")]
658impl<T: PartialEq> PartialEq for OnceLock<T> {
659 /// Equality for two `OnceLock`s.
660 ///
661 /// Two `OnceLock`s are equal if they either both contain values and their
662 /// values are equal, or if neither contains a value.
663 ///
664 /// # Examples
665 ///
666 /// ```
667 /// use std::sync::OnceLock;
668 ///
669 /// let five = OnceLock::new();
670 /// five.set(5).unwrap();
671 ///
672 /// let also_five = OnceLock::new();
673 /// also_five.set(5).unwrap();
674 ///
675 /// assert!(five == also_five);
676 ///
677 /// assert!(OnceLock::<u32>::new() == OnceLock::<u32>::new());
678 /// ```
679 #[inline]
680 fn eq(&self, other: &OnceLock<T>) -> bool {
681 self.get() == other.get()
682 }
683}
684
685#[stable(feature = "once_cell", since = "1.70.0")]
686impl<T: Eq> Eq for OnceLock<T> {}
687
688#[stable(feature = "once_cell", since = "1.70.0")]
689unsafe impl<#[may_dangle] T> Drop for OnceLock<T> {
690 #[inline]
691 fn drop(&mut self) {
692 if self.is_initialized() {
693 // SAFETY: The cell is initialized and being dropped, so it can't
694 // be accessed again. We also don't touch the `T` other than
695 // dropping it, which validates our usage of #[may_dangle].
696 unsafe { (&mut *self.value.get()).assume_init_drop() };
697 }
698 }
699}