]> git.lizzy.rs Git - rust.git/blob - library/std/src/sync/once_lock.rs
Rollup merge of #101534 - rust-lang:notriddle/rustdoc-flex-direction, r=GuillaumeGomez
[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::sync::Once;
7
8 /// A synchronization primitive which can be written to only once.
9 ///
10 /// This type is a thread-safe `OnceCell`.
11 ///
12 /// # Examples
13 ///
14 /// ```
15 /// #![feature(once_cell)]
16 ///
17 /// use std::sync::OnceLock;
18 ///
19 /// static CELL: OnceLock<String> = OnceLock::new();
20 /// assert!(CELL.get().is_none());
21 ///
22 /// std::thread::spawn(|| {
23 ///     let value: &String = CELL.get_or_init(|| {
24 ///         "Hello, World!".to_string()
25 ///     });
26 ///     assert_eq!(value, "Hello, World!");
27 /// }).join().unwrap();
28 ///
29 /// let value: Option<&String> = CELL.get();
30 /// assert!(value.is_some());
31 /// assert_eq!(value.unwrap().as_str(), "Hello, World!");
32 /// ```
33 #[unstable(feature = "once_cell", issue = "74465")]
34 pub struct OnceLock<T> {
35     once: Once,
36     // Whether or not the value is initialized is tracked by `state_and_queue`.
37     value: UnsafeCell<MaybeUninit<T>>,
38     /// `PhantomData` to make sure dropck understands we're dropping T in our Drop impl.
39     ///
40     /// ```compile_fail,E0597
41     /// #![feature(once_cell)]
42     ///
43     /// use std::sync::OnceLock;
44     ///
45     /// struct A<'a>(&'a str);
46     ///
47     /// impl<'a> Drop for A<'a> {
48     ///     fn drop(&mut self) {}
49     /// }
50     ///
51     /// let cell = OnceLock::new();
52     /// {
53     ///     let s = String::new();
54     ///     let _ = cell.set(A(&s));
55     /// }
56     /// ```
57     _marker: PhantomData<T>,
58 }
59
60 impl<T> OnceLock<T> {
61     /// Creates a new empty cell.
62     #[unstable(feature = "once_cell", issue = "74465")]
63     #[must_use]
64     pub const fn new() -> OnceLock<T> {
65         OnceLock {
66             once: Once::new(),
67             value: UnsafeCell::new(MaybeUninit::uninit()),
68             _marker: PhantomData,
69         }
70     }
71
72     /// Gets the reference to the underlying value.
73     ///
74     /// Returns `None` if the cell is empty, or being initialized. This
75     /// method never blocks.
76     #[unstable(feature = "once_cell", issue = "74465")]
77     pub fn get(&self) -> Option<&T> {
78         if self.is_initialized() {
79             // Safe b/c checked is_initialized
80             Some(unsafe { self.get_unchecked() })
81         } else {
82             None
83         }
84     }
85
86     /// Gets the mutable reference to the underlying value.
87     ///
88     /// Returns `None` if the cell is empty. This method never blocks.
89     #[unstable(feature = "once_cell", issue = "74465")]
90     pub fn get_mut(&mut self) -> Option<&mut T> {
91         if self.is_initialized() {
92             // Safe b/c checked is_initialized and we have a unique access
93             Some(unsafe { self.get_unchecked_mut() })
94         } else {
95             None
96         }
97     }
98
99     /// Sets the contents of this cell to `value`.
100     ///
101     /// May block if another thread is currently attempting to initialize the cell. The cell is
102     /// guaranteed to contain a value when set returns, though not necessarily the one provided.
103     ///
104     /// Returns `Ok(())` if the cell's value was set by this call.
105     ///
106     /// # Examples
107     ///
108     /// ```
109     /// #![feature(once_cell)]
110     ///
111     /// use std::sync::OnceLock;
112     ///
113     /// static CELL: OnceLock<i32> = OnceLock::new();
114     ///
115     /// fn main() {
116     ///     assert!(CELL.get().is_none());
117     ///
118     ///     std::thread::spawn(|| {
119     ///         assert_eq!(CELL.set(92), Ok(()));
120     ///     }).join().unwrap();
121     ///
122     ///     assert_eq!(CELL.set(62), Err(62));
123     ///     assert_eq!(CELL.get(), Some(&92));
124     /// }
125     /// ```
126     #[unstable(feature = "once_cell", issue = "74465")]
127     pub fn set(&self, value: T) -> Result<(), T> {
128         let mut value = Some(value);
129         self.get_or_init(|| value.take().unwrap());
130         match value {
131             None => Ok(()),
132             Some(value) => Err(value),
133         }
134     }
135
136     /// Gets the contents of the cell, initializing it with `f` if the cell
137     /// was empty.
138     ///
139     /// Many threads may call `get_or_init` concurrently with different
140     /// initializing functions, but it is guaranteed that only one function
141     /// will be executed.
142     ///
143     /// # Panics
144     ///
145     /// If `f` panics, the panic is propagated to the caller, and the cell
146     /// remains uninitialized.
147     ///
148     /// It is an error to reentrantly initialize the cell from `f`. The
149     /// exact outcome is unspecified. Current implementation deadlocks, but
150     /// this may be changed to a panic in the future.
151     ///
152     /// # Examples
153     ///
154     /// ```
155     /// #![feature(once_cell)]
156     ///
157     /// use std::sync::OnceLock;
158     ///
159     /// let cell = OnceLock::new();
160     /// let value = cell.get_or_init(|| 92);
161     /// assert_eq!(value, &92);
162     /// let value = cell.get_or_init(|| unreachable!());
163     /// assert_eq!(value, &92);
164     /// ```
165     #[unstable(feature = "once_cell", issue = "74465")]
166     pub fn get_or_init<F>(&self, f: F) -> &T
167     where
168         F: FnOnce() -> T,
169     {
170         match self.get_or_try_init(|| Ok::<T, !>(f())) {
171             Ok(val) => val,
172         }
173     }
174
175     /// Gets the contents of the cell, initializing it with `f` if
176     /// the cell was empty. If the cell was empty and `f` failed, an
177     /// error is returned.
178     ///
179     /// # Panics
180     ///
181     /// If `f` panics, the panic is propagated to the caller, and
182     /// the cell remains uninitialized.
183     ///
184     /// It is an error to reentrantly initialize the cell from `f`.
185     /// The exact outcome is unspecified. Current implementation
186     /// deadlocks, but this may be changed to a panic in the future.
187     ///
188     /// # Examples
189     ///
190     /// ```
191     /// #![feature(once_cell)]
192     ///
193     /// use std::sync::OnceLock;
194     ///
195     /// let cell = OnceLock::new();
196     /// assert_eq!(cell.get_or_try_init(|| Err(())), Err(()));
197     /// assert!(cell.get().is_none());
198     /// let value = cell.get_or_try_init(|| -> Result<i32, ()> {
199     ///     Ok(92)
200     /// });
201     /// assert_eq!(value, Ok(&92));
202     /// assert_eq!(cell.get(), Some(&92))
203     /// ```
204     #[unstable(feature = "once_cell", issue = "74465")]
205     pub fn get_or_try_init<F, E>(&self, f: F) -> Result<&T, E>
206     where
207         F: FnOnce() -> Result<T, E>,
208     {
209         // Fast path check
210         // NOTE: We need to perform an acquire on the state in this method
211         // in order to correctly synchronize `LazyLock::force`. This is
212         // currently done by calling `self.get()`, which in turn calls
213         // `self.is_initialized()`, which in turn performs the acquire.
214         if let Some(value) = self.get() {
215             return Ok(value);
216         }
217         self.initialize(f)?;
218
219         debug_assert!(self.is_initialized());
220
221         // SAFETY: The inner value has been initialized
222         Ok(unsafe { self.get_unchecked() })
223     }
224
225     /// Consumes the `OnceLock`, returning the wrapped value. Returns
226     /// `None` if the cell was empty.
227     ///
228     /// # Examples
229     ///
230     /// ```
231     /// #![feature(once_cell)]
232     ///
233     /// use std::sync::OnceLock;
234     ///
235     /// let cell: OnceLock<String> = OnceLock::new();
236     /// assert_eq!(cell.into_inner(), None);
237     ///
238     /// let cell = OnceLock::new();
239     /// cell.set("hello".to_string()).unwrap();
240     /// assert_eq!(cell.into_inner(), Some("hello".to_string()));
241     /// ```
242     #[unstable(feature = "once_cell", issue = "74465")]
243     pub fn into_inner(mut self) -> Option<T> {
244         self.take()
245     }
246
247     /// Takes the value out of this `OnceLock`, moving it back to an uninitialized state.
248     ///
249     /// Has no effect and returns `None` if the `OnceLock` hasn't been initialized.
250     ///
251     /// Safety is guaranteed by requiring a mutable reference.
252     ///
253     /// # Examples
254     ///
255     /// ```
256     /// #![feature(once_cell)]
257     ///
258     /// use std::sync::OnceLock;
259     ///
260     /// let mut cell: OnceLock<String> = OnceLock::new();
261     /// assert_eq!(cell.take(), None);
262     ///
263     /// let mut cell = OnceLock::new();
264     /// cell.set("hello".to_string()).unwrap();
265     /// assert_eq!(cell.take(), Some("hello".to_string()));
266     /// assert_eq!(cell.get(), None);
267     /// ```
268     #[unstable(feature = "once_cell", issue = "74465")]
269     pub fn take(&mut self) -> Option<T> {
270         if self.is_initialized() {
271             self.once = Once::new();
272             // SAFETY: `self.value` is initialized and contains a valid `T`.
273             // `self.once` is reset, so `is_initialized()` will be false again
274             // which prevents the value from being read twice.
275             unsafe { Some((&mut *self.value.get()).assume_init_read()) }
276         } else {
277             None
278         }
279     }
280
281     #[inline]
282     fn is_initialized(&self) -> bool {
283         self.once.is_completed()
284     }
285
286     #[cold]
287     fn initialize<F, E>(&self, f: F) -> Result<(), E>
288     where
289         F: FnOnce() -> Result<T, E>,
290     {
291         let mut res: Result<(), E> = Ok(());
292         let slot = &self.value;
293
294         // Ignore poisoning from other threads
295         // If another thread panics, then we'll be able to run our closure
296         self.once.call_once_force(|p| {
297             match f() {
298                 Ok(value) => {
299                     unsafe { (&mut *slot.get()).write(value) };
300                 }
301                 Err(e) => {
302                     res = Err(e);
303
304                     // Treat the underlying `Once` as poisoned since we
305                     // failed to initialize our value. Calls
306                     p.poison();
307                 }
308             }
309         });
310         res
311     }
312
313     /// # Safety
314     ///
315     /// The value must be initialized
316     unsafe fn get_unchecked(&self) -> &T {
317         debug_assert!(self.is_initialized());
318         (&*self.value.get()).assume_init_ref()
319     }
320
321     /// # Safety
322     ///
323     /// The value must be initialized
324     unsafe fn get_unchecked_mut(&mut self) -> &mut T {
325         debug_assert!(self.is_initialized());
326         (&mut *self.value.get()).assume_init_mut()
327     }
328 }
329
330 // Why do we need `T: Send`?
331 // Thread A creates a `OnceLock` and shares it with
332 // scoped thread B, which fills the cell, which is
333 // then destroyed by A. That is, destructor observes
334 // a sent value.
335 #[unstable(feature = "once_cell", issue = "74465")]
336 unsafe impl<T: Sync + Send> Sync for OnceLock<T> {}
337 #[unstable(feature = "once_cell", issue = "74465")]
338 unsafe impl<T: Send> Send for OnceLock<T> {}
339
340 #[unstable(feature = "once_cell", issue = "74465")]
341 impl<T: RefUnwindSafe + UnwindSafe> RefUnwindSafe for OnceLock<T> {}
342 #[unstable(feature = "once_cell", issue = "74465")]
343 impl<T: UnwindSafe> UnwindSafe for OnceLock<T> {}
344
345 #[unstable(feature = "once_cell", issue = "74465")]
346 #[rustc_const_unstable(feature = "const_default_impls", issue = "87864")]
347 impl<T> const Default for OnceLock<T> {
348     /// Creates a new empty cell.
349     ///
350     /// # Example
351     ///
352     /// ```
353     /// #![feature(once_cell)]
354     ///
355     /// use std::sync::OnceLock;
356     ///
357     /// fn main() {
358     ///     assert_eq!(OnceLock::<()>::new(), OnceLock::default());
359     /// }
360     /// ```
361     fn default() -> OnceLock<T> {
362         OnceLock::new()
363     }
364 }
365
366 #[unstable(feature = "once_cell", issue = "74465")]
367 impl<T: fmt::Debug> fmt::Debug for OnceLock<T> {
368     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
369         match self.get() {
370             Some(v) => f.debug_tuple("Once").field(v).finish(),
371             None => f.write_str("Once(Uninit)"),
372         }
373     }
374 }
375
376 #[unstable(feature = "once_cell", issue = "74465")]
377 impl<T: Clone> Clone for OnceLock<T> {
378     fn clone(&self) -> OnceLock<T> {
379         let cell = Self::new();
380         if let Some(value) = self.get() {
381             match cell.set(value.clone()) {
382                 Ok(()) => (),
383                 Err(_) => unreachable!(),
384             }
385         }
386         cell
387     }
388 }
389
390 #[unstable(feature = "once_cell", issue = "74465")]
391 impl<T> From<T> for OnceLock<T> {
392     /// Create a new cell with its contents set to `value`.
393     ///
394     /// # Example
395     ///
396     /// ```
397     /// #![feature(once_cell)]
398     ///
399     /// use std::sync::OnceLock;
400     ///
401     /// # fn main() -> Result<(), i32> {
402     /// let a = OnceLock::from(3);
403     /// let b = OnceLock::new();
404     /// b.set(3)?;
405     /// assert_eq!(a, b);
406     /// Ok(())
407     /// # }
408     /// ```
409     fn from(value: T) -> Self {
410         let cell = Self::new();
411         match cell.set(value) {
412             Ok(()) => cell,
413             Err(_) => unreachable!(),
414         }
415     }
416 }
417
418 #[unstable(feature = "once_cell", issue = "74465")]
419 impl<T: PartialEq> PartialEq for OnceLock<T> {
420     fn eq(&self, other: &OnceLock<T>) -> bool {
421         self.get() == other.get()
422     }
423 }
424
425 #[unstable(feature = "once_cell", issue = "74465")]
426 impl<T: Eq> Eq for OnceLock<T> {}
427
428 #[unstable(feature = "once_cell", issue = "74465")]
429 unsafe impl<#[may_dangle] T> Drop for OnceLock<T> {
430     fn drop(&mut self) {
431         if self.is_initialized() {
432             // SAFETY: The cell is initialized and being dropped, so it can't
433             // be accessed again. We also don't touch the `T` other than
434             // dropping it, which validates our usage of #[may_dangle].
435             unsafe { (&mut *self.value.get()).assume_init_drop() };
436         }
437     }
438 }
439
440 #[cfg(test)]
441 mod tests;