]> git.lizzy.rs Git - rust.git/blob - library/std/src/sync/once_lock.rs
Rollup merge of #100092 - compiler-errors:issue-100075, r=oli-obk
[rust.git] / library / std / src / sync / once_lock.rs
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::pin::Pin;
7 use crate::sync::Once;
8
9 /// A synchronization primitive which can be written to only once.
10 ///
11 /// This type is a thread-safe `OnceCell`.
12 ///
13 /// # Examples
14 ///
15 /// ```
16 /// #![feature(once_cell)]
17 ///
18 /// use std::sync::OnceLock;
19 ///
20 /// static CELL: OnceLock<String> = OnceLock::new();
21 /// assert!(CELL.get().is_none());
22 ///
23 /// std::thread::spawn(|| {
24 ///     let value: &String = CELL.get_or_init(|| {
25 ///         "Hello, World!".to_string()
26 ///     });
27 ///     assert_eq!(value, "Hello, World!");
28 /// }).join().unwrap();
29 ///
30 /// let value: Option<&String> = CELL.get();
31 /// assert!(value.is_some());
32 /// assert_eq!(value.unwrap().as_str(), "Hello, World!");
33 /// ```
34 #[unstable(feature = "once_cell", issue = "74465")]
35 pub struct OnceLock<T> {
36     once: Once,
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.
40     ///
41     /// ```compile_fail,E0597
42     /// #![feature(once_cell)]
43     ///
44     /// use std::sync::OnceLock;
45     ///
46     /// struct A<'a>(&'a str);
47     ///
48     /// impl<'a> Drop for A<'a> {
49     ///     fn drop(&mut self) {}
50     /// }
51     ///
52     /// let cell = OnceLock::new();
53     /// {
54     ///     let s = String::new();
55     ///     let _ = cell.set(A(&s));
56     /// }
57     /// ```
58     _marker: PhantomData<T>,
59 }
60
61 impl<T> OnceLock<T> {
62     /// Creates a new empty cell.
63     #[unstable(feature = "once_cell", issue = "74465")]
64     #[must_use]
65     pub const fn new() -> OnceLock<T> {
66         OnceLock {
67             once: Once::new(),
68             value: UnsafeCell::new(MaybeUninit::uninit()),
69             _marker: PhantomData,
70         }
71     }
72
73     /// Gets the reference to the underlying value.
74     ///
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() })
82         } else {
83             None
84         }
85     }
86
87     /// Gets the mutable reference to the underlying value.
88     ///
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() })
95         } else {
96             None
97         }
98     }
99
100     /// Sets the contents of this cell to `value`.
101     ///
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.
104     ///
105     /// Returns `Ok(())` if the cell's value was set by this call.
106     ///
107     /// # Examples
108     ///
109     /// ```
110     /// #![feature(once_cell)]
111     ///
112     /// use std::sync::OnceLock;
113     ///
114     /// static CELL: OnceLock<i32> = OnceLock::new();
115     ///
116     /// fn main() {
117     ///     assert!(CELL.get().is_none());
118     ///
119     ///     std::thread::spawn(|| {
120     ///         assert_eq!(CELL.set(92), Ok(()));
121     ///     }).join().unwrap();
122     ///
123     ///     assert_eq!(CELL.set(62), Err(62));
124     ///     assert_eq!(CELL.get(), Some(&92));
125     /// }
126     /// ```
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());
131         match value {
132             None => Ok(()),
133             Some(value) => Err(value),
134         }
135     }
136
137     /// Gets the contents of the cell, initializing it with `f` if the cell
138     /// was empty.
139     ///
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.
143     ///
144     /// # Panics
145     ///
146     /// If `f` panics, the panic is propagated to the caller, and the cell
147     /// remains uninitialized.
148     ///
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.
152     ///
153     /// # Examples
154     ///
155     /// ```
156     /// #![feature(once_cell)]
157     ///
158     /// use std::sync::OnceLock;
159     ///
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);
165     /// ```
166     #[unstable(feature = "once_cell", issue = "74465")]
167     pub fn get_or_init<F>(&self, f: F) -> &T
168     where
169         F: FnOnce() -> T,
170     {
171         match self.get_or_try_init(|| Ok::<T, !>(f())) {
172             Ok(val) => val,
173         }
174     }
175
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.
179     ///
180     /// # Panics
181     ///
182     /// If `f` panics, the panic is propagated to the caller, and
183     /// the cell remains uninitialized.
184     ///
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.
188     ///
189     /// # Examples
190     ///
191     /// ```
192     /// #![feature(once_cell)]
193     ///
194     /// use std::sync::OnceLock;
195     ///
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, ()> {
200     ///     Ok(92)
201     /// });
202     /// assert_eq!(value, Ok(&92));
203     /// assert_eq!(cell.get(), Some(&92))
204     /// ```
205     #[unstable(feature = "once_cell", issue = "74465")]
206     pub fn get_or_try_init<F, E>(&self, f: F) -> Result<&T, E>
207     where
208         F: FnOnce() -> Result<T, E>,
209     {
210         // Fast path check
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() {
216             return Ok(value);
217         }
218         self.initialize(f)?;
219
220         debug_assert!(self.is_initialized());
221
222         // SAFETY: The inner value has been initialized
223         Ok(unsafe { self.get_unchecked() })
224     }
225
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.
228     ///
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
231     /// initialization.
232     ///
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.
236     ///
237     /// # Panics
238     ///
239     /// If `f` or `g` panics, the panic is propagated to the caller, and the
240     /// cell remains uninitialized.
241     ///
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.
245     ///
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>
250     where
251         F: FnOnce() -> T,
252         G: FnOnce(Pin<&mut T>),
253     {
254         if let Some(value) = self.get_ref().get() {
255             // SAFETY: The inner value was already initialized, and will not be
256             // moved anymore.
257             return unsafe { Pin::new_unchecked(value) };
258         }
259
260         let slot = &self.value;
261
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(|_| {
265             let value = f();
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) });
273         });
274
275         // SAFETY: The inner value has been initialized, and will not be moved
276         // anymore.
277         unsafe { Pin::new_unchecked(self.get_ref().get_unchecked()) }
278     }
279
280     /// Consumes the `OnceLock`, returning the wrapped value. Returns
281     /// `None` if the cell was empty.
282     ///
283     /// # Examples
284     ///
285     /// ```
286     /// #![feature(once_cell)]
287     ///
288     /// use std::sync::OnceLock;
289     ///
290     /// let cell: OnceLock<String> = OnceLock::new();
291     /// assert_eq!(cell.into_inner(), None);
292     ///
293     /// let cell = OnceLock::new();
294     /// cell.set("hello".to_string()).unwrap();
295     /// assert_eq!(cell.into_inner(), Some("hello".to_string()));
296     /// ```
297     #[unstable(feature = "once_cell", issue = "74465")]
298     pub fn into_inner(mut self) -> Option<T> {
299         self.take()
300     }
301
302     /// Takes the value out of this `OnceLock`, moving it back to an uninitialized state.
303     ///
304     /// Has no effect and returns `None` if the `OnceLock` hasn't been initialized.
305     ///
306     /// Safety is guaranteed by requiring a mutable reference.
307     ///
308     /// # Examples
309     ///
310     /// ```
311     /// #![feature(once_cell)]
312     ///
313     /// use std::sync::OnceLock;
314     ///
315     /// let mut cell: OnceLock<String> = OnceLock::new();
316     /// assert_eq!(cell.take(), None);
317     ///
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);
322     /// ```
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()) }
331         } else {
332             None
333         }
334     }
335
336     #[inline]
337     fn is_initialized(&self) -> bool {
338         self.once.is_completed()
339     }
340
341     #[cold]
342     fn initialize<F, E>(&self, f: F) -> Result<(), E>
343     where
344         F: FnOnce() -> Result<T, E>,
345     {
346         let mut res: Result<(), E> = Ok(());
347         let slot = &self.value;
348
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| {
352             match f() {
353                 Ok(value) => {
354                     unsafe { (&mut *slot.get()).write(value) };
355                 }
356                 Err(e) => {
357                     res = Err(e);
358
359                     // Treat the underlying `Once` as poisoned since we
360                     // failed to initialize our value. Calls
361                     p.poison();
362                 }
363             }
364         });
365         res
366     }
367
368     /// # Safety
369     ///
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()
374     }
375
376     /// # Safety
377     ///
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()
382     }
383 }
384
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
389 // a sent value.
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> {}
394
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> {}
399
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.
404     ///
405     /// # Example
406     ///
407     /// ```
408     /// #![feature(once_cell)]
409     ///
410     /// use std::sync::OnceLock;
411     ///
412     /// fn main() {
413     ///     assert_eq!(OnceLock::<()>::new(), OnceLock::default());
414     /// }
415     /// ```
416     fn default() -> OnceLock<T> {
417         OnceLock::new()
418     }
419 }
420
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 {
424         match self.get() {
425             Some(v) => f.debug_tuple("Once").field(v).finish(),
426             None => f.write_str("Once(Uninit)"),
427         }
428     }
429 }
430
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()) {
437                 Ok(()) => (),
438                 Err(_) => unreachable!(),
439             }
440         }
441         cell
442     }
443 }
444
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`.
448     ///
449     /// # Example
450     ///
451     /// ```
452     /// #![feature(once_cell)]
453     ///
454     /// use std::sync::OnceLock;
455     ///
456     /// # fn main() -> Result<(), i32> {
457     /// let a = OnceLock::from(3);
458     /// let b = OnceLock::new();
459     /// b.set(3)?;
460     /// assert_eq!(a, b);
461     /// Ok(())
462     /// # }
463     /// ```
464     fn from(value: T) -> Self {
465         let cell = Self::new();
466         match cell.set(value) {
467             Ok(()) => cell,
468             Err(_) => unreachable!(),
469         }
470     }
471 }
472
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()
477     }
478 }
479
480 #[unstable(feature = "once_cell", issue = "74465")]
481 impl<T: Eq> Eq for OnceLock<T> {}
482
483 #[unstable(feature = "once_cell", issue = "74465")]
484 unsafe impl<#[may_dangle] T> Drop for OnceLock<T> {
485     fn drop(&mut self) {
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() };
491         }
492     }
493 }
494
495 #[cfg(test)]
496 mod tests;