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