1 use crate::cell::UnsafeCell;
3 use crate::marker::PhantomData;
4 use crate::mem::MaybeUninit;
5 use crate::panic::{RefUnwindSafe, UnwindSafe};
9 /// A synchronization primitive which can be written to only once.
11 /// This type is a thread-safe `OnceCell`.
16 /// #![feature(once_cell)]
18 /// use std::sync::OnceLock;
20 /// static CELL: OnceLock<String> = OnceLock::new();
21 /// assert!(CELL.get().is_none());
23 /// std::thread::spawn(|| {
24 /// let value: &String = CELL.get_or_init(|| {
25 /// "Hello, World!".to_string()
27 /// assert_eq!(value, "Hello, World!");
28 /// }).join().unwrap();
30 /// let value: Option<&String> = CELL.get();
31 /// assert!(value.is_some());
32 /// assert_eq!(value.unwrap().as_str(), "Hello, World!");
34 #[unstable(feature = "once_cell", issue = "74465")]
35 pub struct OnceLock<T> {
37 // Whether or not the value is initialized is tracked by `state_and_queue`.
38 value: UnsafeCell<MaybeUninit<T>>,
39 /// `PhantomData` to make sure dropck understands we're dropping T in our Drop impl.
41 /// ```compile_fail,E0597
42 /// #![feature(once_cell)]
44 /// use std::sync::OnceLock;
46 /// struct A<'a>(&'a str);
48 /// impl<'a> Drop for A<'a> {
49 /// fn drop(&mut self) {}
52 /// let cell = OnceLock::new();
54 /// let s = String::new();
55 /// let _ = cell.set(A(&s));
58 _marker: PhantomData<T>,
62 /// Creates a new empty cell.
63 #[unstable(feature = "once_cell", issue = "74465")]
65 pub const fn new() -> OnceLock<T> {
68 value: UnsafeCell::new(MaybeUninit::uninit()),
73 /// Gets the reference to the underlying value.
75 /// Returns `None` if the cell is empty, or being initialized. This
76 /// method never blocks.
77 #[unstable(feature = "once_cell", issue = "74465")]
78 pub fn get(&self) -> Option<&T> {
79 if self.is_initialized() {
80 // Safe b/c checked is_initialized
81 Some(unsafe { self.get_unchecked() })
87 /// Gets the mutable reference to the underlying value.
89 /// Returns `None` if the cell is empty. This method never blocks.
90 #[unstable(feature = "once_cell", issue = "74465")]
91 pub fn get_mut(&mut self) -> Option<&mut T> {
92 if self.is_initialized() {
93 // Safe b/c checked is_initialized and we have a unique access
94 Some(unsafe { self.get_unchecked_mut() })
100 /// Sets the contents of this cell to `value`.
102 /// May block if another thread is currently attempting to initialize the cell. The cell is
103 /// guaranteed to contain a value when set returns, though not necessarily the one provided.
105 /// Returns `Ok(())` if the cell's value was set by this call.
110 /// #![feature(once_cell)]
112 /// use std::sync::OnceLock;
114 /// static CELL: OnceLock<i32> = OnceLock::new();
117 /// assert!(CELL.get().is_none());
119 /// std::thread::spawn(|| {
120 /// assert_eq!(CELL.set(92), Ok(()));
121 /// }).join().unwrap();
123 /// assert_eq!(CELL.set(62), Err(62));
124 /// assert_eq!(CELL.get(), Some(&92));
127 #[unstable(feature = "once_cell", issue = "74465")]
128 pub fn set(&self, value: T) -> Result<(), T> {
129 let mut value = Some(value);
130 self.get_or_init(|| value.take().unwrap());
133 Some(value) => Err(value),
137 /// Gets the contents of the cell, initializing it with `f` if the cell
140 /// Many threads may call `get_or_init` concurrently with different
141 /// initializing functions, but it is guaranteed that only one function
142 /// will be executed.
146 /// If `f` panics, the panic is propagated to the caller, and the cell
147 /// remains uninitialized.
149 /// It is an error to reentrantly initialize the cell from `f`. The
150 /// exact outcome is unspecified. Current implementation deadlocks, but
151 /// this may be changed to a panic in the future.
156 /// #![feature(once_cell)]
158 /// use std::sync::OnceLock;
160 /// let cell = OnceLock::new();
161 /// let value = cell.get_or_init(|| 92);
162 /// assert_eq!(value, &92);
163 /// let value = cell.get_or_init(|| unreachable!());
164 /// assert_eq!(value, &92);
166 #[unstable(feature = "once_cell", issue = "74465")]
167 pub fn get_or_init<F>(&self, f: F) -> &T
171 match self.get_or_try_init(|| Ok::<T, !>(f())) {
176 /// Gets the contents of the cell, initializing it with `f` if
177 /// the cell was empty. If the cell was empty and `f` failed, an
178 /// error is returned.
182 /// If `f` panics, the panic is propagated to the caller, and
183 /// the cell remains uninitialized.
185 /// It is an error to reentrantly initialize the cell from `f`.
186 /// The exact outcome is unspecified. Current implementation
187 /// deadlocks, but this may be changed to a panic in the future.
192 /// #![feature(once_cell)]
194 /// use std::sync::OnceLock;
196 /// let cell = OnceLock::new();
197 /// assert_eq!(cell.get_or_try_init(|| Err(())), Err(()));
198 /// assert!(cell.get().is_none());
199 /// let value = cell.get_or_try_init(|| -> Result<i32, ()> {
202 /// assert_eq!(value, Ok(&92));
203 /// assert_eq!(cell.get(), Some(&92))
205 #[unstable(feature = "once_cell", issue = "74465")]
206 pub fn get_or_try_init<F, E>(&self, f: F) -> Result<&T, E>
208 F: FnOnce() -> Result<T, E>,
211 // NOTE: We need to perform an acquire on the state in this method
212 // in order to correctly synchronize `LazyLock::force`. This is
213 // currently done by calling `self.get()`, which in turn calls
214 // `self.is_initialized()`, which in turn performs the acquire.
215 if let Some(value) = self.get() {
220 debug_assert!(self.is_initialized());
222 // SAFETY: The inner value has been initialized
223 Ok(unsafe { self.get_unchecked() })
226 /// Internal-only API that gets the contents of the cell, initializing it
227 /// in two steps with `f` and `g` if the cell was empty.
229 /// `f` is called to construct the value, which is then moved into the cell
230 /// and given as a (pinned) mutable reference to `g` to finish
233 /// This allows `g` to inspect an manipulate the value after it has been
234 /// moved into its final place in the cell, but before the cell is
235 /// considered initialized.
239 /// If `f` or `g` panics, the panic is propagated to the caller, and the
240 /// cell remains uninitialized.
242 /// With the current implementation, if `g` panics, the value from `f` will
243 /// not be dropped. This should probably be fixed if this is ever used for
244 /// a type where this matters.
246 /// It is an error to reentrantly initialize the cell from `f`. The exact
247 /// outcome is unspecified. Current implementation deadlocks, but this may
248 /// be changed to a panic in the future.
249 pub(crate) fn get_or_init_pin<F, G>(self: Pin<&Self>, f: F, g: G) -> Pin<&T>
252 G: FnOnce(Pin<&mut T>),
254 if let Some(value) = self.get_ref().get() {
255 // SAFETY: The inner value was already initialized, and will not be
257 return unsafe { Pin::new_unchecked(value) };
260 let slot = &self.value;
262 // Ignore poisoning from other threads
263 // If another thread panics, then we'll be able to run our closure
264 self.once.call_once_force(|_| {
266 // SAFETY: We use the Once (self.once) to guarantee unique access
267 // to the UnsafeCell (slot).
268 let value: &mut T = unsafe { (&mut *slot.get()).write(value) };
269 // SAFETY: The value has been written to its final place in
270 // self.value. We do not to move it anymore, which we promise here
271 // with a Pin<&mut T>.
272 g(unsafe { Pin::new_unchecked(value) });
275 // SAFETY: The inner value has been initialized, and will not be moved
277 unsafe { Pin::new_unchecked(self.get_ref().get_unchecked()) }
280 /// Consumes the `OnceLock`, returning the wrapped value. Returns
281 /// `None` if the cell was empty.
286 /// #![feature(once_cell)]
288 /// use std::sync::OnceLock;
290 /// let cell: OnceLock<String> = OnceLock::new();
291 /// assert_eq!(cell.into_inner(), None);
293 /// let cell = OnceLock::new();
294 /// cell.set("hello".to_string()).unwrap();
295 /// assert_eq!(cell.into_inner(), Some("hello".to_string()));
297 #[unstable(feature = "once_cell", issue = "74465")]
298 pub fn into_inner(mut self) -> Option<T> {
302 /// Takes the value out of this `OnceLock`, moving it back to an uninitialized state.
304 /// Has no effect and returns `None` if the `OnceLock` hasn't been initialized.
306 /// Safety is guaranteed by requiring a mutable reference.
311 /// #![feature(once_cell)]
313 /// use std::sync::OnceLock;
315 /// let mut cell: OnceLock<String> = OnceLock::new();
316 /// assert_eq!(cell.take(), None);
318 /// let mut cell = OnceLock::new();
319 /// cell.set("hello".to_string()).unwrap();
320 /// assert_eq!(cell.take(), Some("hello".to_string()));
321 /// assert_eq!(cell.get(), None);
323 #[unstable(feature = "once_cell", issue = "74465")]
324 pub fn take(&mut self) -> Option<T> {
325 if self.is_initialized() {
326 self.once = Once::new();
327 // SAFETY: `self.value` is initialized and contains a valid `T`.
328 // `self.once` is reset, so `is_initialized()` will be false again
329 // which prevents the value from being read twice.
330 unsafe { Some((&mut *self.value.get()).assume_init_read()) }
337 fn is_initialized(&self) -> bool {
338 self.once.is_completed()
342 fn initialize<F, E>(&self, f: F) -> Result<(), E>
344 F: FnOnce() -> Result<T, E>,
346 let mut res: Result<(), E> = Ok(());
347 let slot = &self.value;
349 // Ignore poisoning from other threads
350 // If another thread panics, then we'll be able to run our closure
351 self.once.call_once_force(|p| {
354 unsafe { (&mut *slot.get()).write(value) };
359 // Treat the underlying `Once` as poisoned since we
360 // failed to initialize our value. Calls
370 /// The value must be initialized
371 unsafe fn get_unchecked(&self) -> &T {
372 debug_assert!(self.is_initialized());
373 (&*self.value.get()).assume_init_ref()
378 /// The value must be initialized
379 unsafe fn get_unchecked_mut(&mut self) -> &mut T {
380 debug_assert!(self.is_initialized());
381 (&mut *self.value.get()).assume_init_mut()
385 // Why do we need `T: Send`?
386 // Thread A creates a `OnceLock` and shares it with
387 // scoped thread B, which fills the cell, which is
388 // then destroyed by A. That is, destructor observes
390 #[unstable(feature = "once_cell", issue = "74465")]
391 unsafe impl<T: Sync + Send> Sync for OnceLock<T> {}
392 #[unstable(feature = "once_cell", issue = "74465")]
393 unsafe impl<T: Send> Send for OnceLock<T> {}
395 #[unstable(feature = "once_cell", issue = "74465")]
396 impl<T: RefUnwindSafe + UnwindSafe> RefUnwindSafe for OnceLock<T> {}
397 #[unstable(feature = "once_cell", issue = "74465")]
398 impl<T: UnwindSafe> UnwindSafe for OnceLock<T> {}
400 #[unstable(feature = "once_cell", issue = "74465")]
401 #[rustc_const_unstable(feature = "const_default_impls", issue = "87864")]
402 impl<T> const Default for OnceLock<T> {
403 /// Creates a new empty cell.
408 /// #![feature(once_cell)]
410 /// use std::sync::OnceLock;
413 /// assert_eq!(OnceLock::<()>::new(), OnceLock::default());
416 fn default() -> OnceLock<T> {
421 #[unstable(feature = "once_cell", issue = "74465")]
422 impl<T: fmt::Debug> fmt::Debug for OnceLock<T> {
423 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
425 Some(v) => f.debug_tuple("Once").field(v).finish(),
426 None => f.write_str("Once(Uninit)"),
431 #[unstable(feature = "once_cell", issue = "74465")]
432 impl<T: Clone> Clone for OnceLock<T> {
433 fn clone(&self) -> OnceLock<T> {
434 let cell = Self::new();
435 if let Some(value) = self.get() {
436 match cell.set(value.clone()) {
438 Err(_) => unreachable!(),
445 #[unstable(feature = "once_cell", issue = "74465")]
446 impl<T> From<T> for OnceLock<T> {
447 /// Create a new cell with its contents set to `value`.
452 /// #![feature(once_cell)]
454 /// use std::sync::OnceLock;
456 /// # fn main() -> Result<(), i32> {
457 /// let a = OnceLock::from(3);
458 /// let b = OnceLock::new();
460 /// assert_eq!(a, b);
464 fn from(value: T) -> Self {
465 let cell = Self::new();
466 match cell.set(value) {
468 Err(_) => unreachable!(),
473 #[unstable(feature = "once_cell", issue = "74465")]
474 impl<T: PartialEq> PartialEq for OnceLock<T> {
475 fn eq(&self, other: &OnceLock<T>) -> bool {
476 self.get() == other.get()
480 #[unstable(feature = "once_cell", issue = "74465")]
481 impl<T: Eq> Eq for OnceLock<T> {}
483 #[unstable(feature = "once_cell", issue = "74465")]
484 unsafe impl<#[may_dangle] T> Drop for OnceLock<T> {
486 if self.is_initialized() {
487 // SAFETY: The cell is initialized and being dropped, so it can't
488 // be accessed again. We also don't touch the `T` other than
489 // dropping it, which validates our usage of #[may_dangle].
490 unsafe { (&mut *self.value.get()).assume_init_drop() };