]> git.lizzy.rs Git - rust.git/blob - library/std/src/lazy.rs
Auto merge of #84039 - jyn514:uplift-atomic-ordering, r=wesleywiser
[rust.git] / library / std / src / lazy.rs
1 //! Lazy values and one-time initialization of static data.
2
3 #[cfg(test)]
4 mod tests;
5
6 use crate::{
7     cell::{Cell, UnsafeCell},
8     fmt,
9     marker::PhantomData,
10     mem::MaybeUninit,
11     ops::{Deref, Drop},
12     panic::{RefUnwindSafe, UnwindSafe},
13     pin::Pin,
14     sync::Once,
15 };
16
17 #[doc(inline)]
18 #[unstable(feature = "once_cell", issue = "74465")]
19 pub use core::lazy::*;
20
21 /// A synchronization primitive which can be written to only once.
22 ///
23 /// This type is a thread-safe `OnceCell`.
24 ///
25 /// # Examples
26 ///
27 /// ```
28 /// #![feature(once_cell)]
29 ///
30 /// use std::lazy::SyncOnceCell;
31 ///
32 /// static CELL: SyncOnceCell<String> = SyncOnceCell::new();
33 /// assert!(CELL.get().is_none());
34 ///
35 /// std::thread::spawn(|| {
36 ///     let value: &String = CELL.get_or_init(|| {
37 ///         "Hello, World!".to_string()
38 ///     });
39 ///     assert_eq!(value, "Hello, World!");
40 /// }).join().unwrap();
41 ///
42 /// let value: Option<&String> = CELL.get();
43 /// assert!(value.is_some());
44 /// assert_eq!(value.unwrap().as_str(), "Hello, World!");
45 /// ```
46 #[unstable(feature = "once_cell", issue = "74465")]
47 pub struct SyncOnceCell<T> {
48     once: Once,
49     // Whether or not the value is initialized is tracked by `state_and_queue`.
50     value: UnsafeCell<MaybeUninit<T>>,
51     /// `PhantomData` to make sure dropck understands we're dropping T in our Drop impl.
52     ///
53     /// ```compile_fail,E0597
54     /// #![feature(once_cell)]
55     ///
56     /// use std::lazy::SyncOnceCell;
57     ///
58     /// struct A<'a>(&'a str);
59     ///
60     /// impl<'a> Drop for A<'a> {
61     ///     fn drop(&mut self) {}
62     /// }
63     ///
64     /// let cell = SyncOnceCell::new();
65     /// {
66     ///     let s = String::new();
67     ///     let _ = cell.set(A(&s));
68     /// }
69     /// ```
70     _marker: PhantomData<T>,
71 }
72
73 // Why do we need `T: Send`?
74 // Thread A creates a `SyncOnceCell` and shares it with
75 // scoped thread B, which fills the cell, which is
76 // then destroyed by A. That is, destructor observes
77 // a sent value.
78 #[unstable(feature = "once_cell", issue = "74465")]
79 unsafe impl<T: Sync + Send> Sync for SyncOnceCell<T> {}
80 #[unstable(feature = "once_cell", issue = "74465")]
81 unsafe impl<T: Send> Send for SyncOnceCell<T> {}
82
83 #[unstable(feature = "once_cell", issue = "74465")]
84 impl<T: RefUnwindSafe + UnwindSafe> RefUnwindSafe for SyncOnceCell<T> {}
85 #[unstable(feature = "once_cell", issue = "74465")]
86 impl<T: UnwindSafe> UnwindSafe for SyncOnceCell<T> {}
87
88 #[unstable(feature = "once_cell", issue = "74465")]
89 impl<T> Default for SyncOnceCell<T> {
90     /// Creates a new empty cell.
91     ///
92     /// # Example
93     ///
94     /// ```
95     /// #![feature(once_cell)]
96     ///
97     /// use std::lazy::SyncOnceCell;
98     ///
99     /// fn main() {
100     ///     assert_eq!(SyncOnceCell::<()>::new(), SyncOnceCell::default());
101     /// }
102     /// ```
103     fn default() -> SyncOnceCell<T> {
104         SyncOnceCell::new()
105     }
106 }
107
108 #[unstable(feature = "once_cell", issue = "74465")]
109 impl<T: fmt::Debug> fmt::Debug for SyncOnceCell<T> {
110     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
111         match self.get() {
112             Some(v) => f.debug_tuple("Once").field(v).finish(),
113             None => f.write_str("Once(Uninit)"),
114         }
115     }
116 }
117
118 #[unstable(feature = "once_cell", issue = "74465")]
119 impl<T: Clone> Clone for SyncOnceCell<T> {
120     fn clone(&self) -> SyncOnceCell<T> {
121         let cell = Self::new();
122         if let Some(value) = self.get() {
123             match cell.set(value.clone()) {
124                 Ok(()) => (),
125                 Err(_) => unreachable!(),
126             }
127         }
128         cell
129     }
130 }
131
132 #[unstable(feature = "once_cell", issue = "74465")]
133 impl<T> From<T> for SyncOnceCell<T> {
134     /// Create a new cell with its contents set to `value`.
135     ///
136     /// # Example
137     ///
138     /// ```
139     /// #![feature(once_cell)]
140     ///
141     /// use std::lazy::SyncOnceCell;
142     ///
143     /// # fn main() -> Result<(), i32> {
144     /// let a = SyncOnceCell::from(3);
145     /// let b = SyncOnceCell::new();
146     /// b.set(3)?;
147     /// assert_eq!(a, b);
148     /// Ok(())
149     /// # }
150     /// ```
151     fn from(value: T) -> Self {
152         let cell = Self::new();
153         match cell.set(value) {
154             Ok(()) => cell,
155             Err(_) => unreachable!(),
156         }
157     }
158 }
159
160 #[unstable(feature = "once_cell", issue = "74465")]
161 impl<T: PartialEq> PartialEq for SyncOnceCell<T> {
162     fn eq(&self, other: &SyncOnceCell<T>) -> bool {
163         self.get() == other.get()
164     }
165 }
166
167 #[unstable(feature = "once_cell", issue = "74465")]
168 impl<T: Eq> Eq for SyncOnceCell<T> {}
169
170 impl<T> SyncOnceCell<T> {
171     /// Creates a new empty cell.
172     #[unstable(feature = "once_cell", issue = "74465")]
173     pub const fn new() -> SyncOnceCell<T> {
174         SyncOnceCell {
175             once: Once::new(),
176             value: UnsafeCell::new(MaybeUninit::uninit()),
177             _marker: PhantomData,
178         }
179     }
180
181     /// Gets the reference to the underlying value.
182     ///
183     /// Returns `None` if the cell is empty, or being initialized. This
184     /// method never blocks.
185     #[unstable(feature = "once_cell", issue = "74465")]
186     pub fn get(&self) -> Option<&T> {
187         if self.is_initialized() {
188             // Safe b/c checked is_initialized
189             Some(unsafe { self.get_unchecked() })
190         } else {
191             None
192         }
193     }
194
195     /// Gets the mutable reference to the underlying value.
196     ///
197     /// Returns `None` if the cell is empty. This method never blocks.
198     #[unstable(feature = "once_cell", issue = "74465")]
199     pub fn get_mut(&mut self) -> Option<&mut T> {
200         if self.is_initialized() {
201             // Safe b/c checked is_initialized and we have a unique access
202             Some(unsafe { self.get_unchecked_mut() })
203         } else {
204             None
205         }
206     }
207
208     /// Sets the contents of this 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's value was set by this call.
214     ///
215     /// # Examples
216     ///
217     /// ```
218     /// #![feature(once_cell)]
219     ///
220     /// use std::lazy::SyncOnceCell;
221     ///
222     /// static CELL: SyncOnceCell<i32> = SyncOnceCell::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     #[unstable(feature = "once_cell", issue = "74465")]
236     pub fn set(&self, value: T) -> Result<(), T> {
237         let mut value = Some(value);
238         self.get_or_init(|| value.take().unwrap());
239         match value {
240             None => Ok(()),
241             Some(value) => Err(value),
242         }
243     }
244
245     /// Gets the contents of the cell, initializing it with `f` if the cell
246     /// was empty.
247     ///
248     /// Many threads may call `get_or_init` concurrently with different
249     /// initializing functions, but it is guaranteed that only one function
250     /// will be executed.
251     ///
252     /// # Panics
253     ///
254     /// If `f` panics, the panic is propagated to the caller, and the cell
255     /// remains uninitialized.
256     ///
257     /// It is an error to reentrantly initialize the cell from `f`. The
258     /// exact outcome is unspecified. Current implementation deadlocks, but
259     /// this may be changed to a panic in the future.
260     ///
261     /// # Examples
262     ///
263     /// ```
264     /// #![feature(once_cell)]
265     ///
266     /// use std::lazy::SyncOnceCell;
267     ///
268     /// let cell = SyncOnceCell::new();
269     /// let value = cell.get_or_init(|| 92);
270     /// assert_eq!(value, &92);
271     /// let value = cell.get_or_init(|| unreachable!());
272     /// assert_eq!(value, &92);
273     /// ```
274     #[unstable(feature = "once_cell", issue = "74465")]
275     pub fn get_or_init<F>(&self, f: F) -> &T
276     where
277         F: FnOnce() -> T,
278     {
279         match self.get_or_try_init(|| Ok::<T, !>(f())) {
280             Ok(val) => val,
281         }
282     }
283
284     /// Gets the contents of the cell, initializing it with `f` if
285     /// the cell was empty. If the cell was empty and `f` failed, an
286     /// error is returned.
287     ///
288     /// # Panics
289     ///
290     /// If `f` panics, the panic is propagated to the caller, and
291     /// the cell remains uninitialized.
292     ///
293     /// It is an error to reentrantly initialize the cell from `f`.
294     /// The exact outcome is unspecified. Current implementation
295     /// deadlocks, but this may be changed to a panic in the future.
296     ///
297     /// # Examples
298     ///
299     /// ```
300     /// #![feature(once_cell)]
301     ///
302     /// use std::lazy::SyncOnceCell;
303     ///
304     /// let cell = SyncOnceCell::new();
305     /// assert_eq!(cell.get_or_try_init(|| Err(())), Err(()));
306     /// assert!(cell.get().is_none());
307     /// let value = cell.get_or_try_init(|| -> Result<i32, ()> {
308     ///     Ok(92)
309     /// });
310     /// assert_eq!(value, Ok(&92));
311     /// assert_eq!(cell.get(), Some(&92))
312     /// ```
313     #[unstable(feature = "once_cell", issue = "74465")]
314     pub fn get_or_try_init<F, E>(&self, f: F) -> Result<&T, E>
315     where
316         F: FnOnce() -> Result<T, E>,
317     {
318         // Fast path check
319         // NOTE: We need to perform an acquire on the state in this method
320         // in order to correctly synchronize `SyncLazy::force`. This is
321         // currently done by calling `self.get()`, which in turn calls
322         // `self.is_initialized()`, which in turn performs the acquire.
323         if let Some(value) = self.get() {
324             return Ok(value);
325         }
326         self.initialize(f)?;
327
328         debug_assert!(self.is_initialized());
329
330         // SAFETY: The inner value has been initialized
331         Ok(unsafe { self.get_unchecked() })
332     }
333
334     /// Internal-only API that gets the contents of the cell, initializing it
335     /// in two steps with `f` and `g` if the cell was empty.
336     ///
337     /// `f` is called to construct the value, which is then moved into the cell
338     /// and given as a (pinned) mutable reference to `g` to finish
339     /// initialization.
340     ///
341     /// This allows `g` to inspect an manipulate the value after it has been
342     /// moved into its final place in the cell, but before the cell is
343     /// considered initialized.
344     ///
345     /// # Panics
346     ///
347     /// If `f` or `g` panics, the panic is propagated to the caller, and the
348     /// cell remains uninitialized.
349     ///
350     /// With the current implementation, if `g` panics, the value from `f` will
351     /// not be dropped. This should probably be fixed if this is ever used for
352     /// a type where this matters.
353     ///
354     /// It is an error to reentrantly initialize the cell from `f`. The exact
355     /// outcome is unspecified. Current implementation deadlocks, but this may
356     /// be changed to a panic in the future.
357     pub(crate) fn get_or_init_pin<F, G>(self: Pin<&Self>, f: F, g: G) -> Pin<&T>
358     where
359         F: FnOnce() -> T,
360         G: FnOnce(Pin<&mut T>),
361     {
362         if let Some(value) = self.get_ref().get() {
363             // SAFETY: The inner value was already initialized, and will not be
364             // moved anymore.
365             return unsafe { Pin::new_unchecked(value) };
366         }
367
368         let slot = &self.value;
369
370         // Ignore poisoning from other threads
371         // If another thread panics, then we'll be able to run our closure
372         self.once.call_once_force(|_| {
373             let value = f();
374             // SAFETY: We use the Once (self.once) to guarantee unique access
375             // to the UnsafeCell (slot).
376             let value: &mut T = unsafe { (&mut *slot.get()).write(value) };
377             // SAFETY: The value has been written to its final place in
378             // self.value. We do not to move it anymore, which we promise here
379             // with a Pin<&mut T>.
380             g(unsafe { Pin::new_unchecked(value) });
381         });
382
383         // SAFETY: The inner value has been initialized, and will not be moved
384         // anymore.
385         unsafe { Pin::new_unchecked(self.get_ref().get_unchecked()) }
386     }
387
388     /// Consumes the `SyncOnceCell`, returning the wrapped value. Returns
389     /// `None` if the cell was empty.
390     ///
391     /// # Examples
392     ///
393     /// ```
394     /// #![feature(once_cell)]
395     ///
396     /// use std::lazy::SyncOnceCell;
397     ///
398     /// let cell: SyncOnceCell<String> = SyncOnceCell::new();
399     /// assert_eq!(cell.into_inner(), None);
400     ///
401     /// let cell = SyncOnceCell::new();
402     /// cell.set("hello".to_string()).unwrap();
403     /// assert_eq!(cell.into_inner(), Some("hello".to_string()));
404     /// ```
405     #[unstable(feature = "once_cell", issue = "74465")]
406     pub fn into_inner(mut self) -> Option<T> {
407         self.take()
408     }
409
410     /// Takes the value out of this `SyncOnceCell`, moving it back to an uninitialized state.
411     ///
412     /// Has no effect and returns `None` if the `SyncOnceCell` hasn't been initialized.
413     ///
414     /// Safety is guaranteed by requiring a mutable reference.
415     ///
416     /// # Examples
417     ///
418     /// ```
419     /// #![feature(once_cell)]
420     ///
421     /// use std::lazy::SyncOnceCell;
422     ///
423     /// let mut cell: SyncOnceCell<String> = SyncOnceCell::new();
424     /// assert_eq!(cell.take(), None);
425     ///
426     /// let mut cell = SyncOnceCell::new();
427     /// cell.set("hello".to_string()).unwrap();
428     /// assert_eq!(cell.take(), Some("hello".to_string()));
429     /// assert_eq!(cell.get(), None);
430     /// ```
431     #[unstable(feature = "once_cell", issue = "74465")]
432     pub fn take(&mut self) -> Option<T> {
433         if self.is_initialized() {
434             self.once = Once::new();
435             // SAFETY: `self.value` is initialized and contains a valid `T`.
436             // `self.once` is reset, so `is_initialized()` will be false again
437             // which prevents the value from being read twice.
438             unsafe { Some((&mut *self.value.get()).assume_init_read()) }
439         } else {
440             None
441         }
442     }
443
444     #[inline]
445     fn is_initialized(&self) -> bool {
446         self.once.is_completed()
447     }
448
449     #[cold]
450     fn initialize<F, E>(&self, f: F) -> Result<(), E>
451     where
452         F: FnOnce() -> Result<T, E>,
453     {
454         let mut res: Result<(), E> = Ok(());
455         let slot = &self.value;
456
457         // Ignore poisoning from other threads
458         // If another thread panics, then we'll be able to run our closure
459         self.once.call_once_force(|p| {
460             match f() {
461                 Ok(value) => {
462                     unsafe { (&mut *slot.get()).write(value) };
463                 }
464                 Err(e) => {
465                     res = Err(e);
466
467                     // Treat the underlying `Once` as poisoned since we
468                     // failed to initialize our value. Calls
469                     p.poison();
470                 }
471             }
472         });
473         res
474     }
475
476     /// # Safety
477     ///
478     /// The value must be initialized
479     unsafe fn get_unchecked(&self) -> &T {
480         debug_assert!(self.is_initialized());
481         (&*self.value.get()).assume_init_ref()
482     }
483
484     /// # Safety
485     ///
486     /// The value must be initialized
487     unsafe fn get_unchecked_mut(&mut self) -> &mut T {
488         debug_assert!(self.is_initialized());
489         (&mut *self.value.get()).assume_init_mut()
490     }
491 }
492
493 unsafe impl<#[may_dangle] T> Drop for SyncOnceCell<T> {
494     fn drop(&mut self) {
495         if self.is_initialized() {
496             // SAFETY: The cell is initialized and being dropped, so it can't
497             // be accessed again. We also don't touch the `T` other than
498             // dropping it, which validates our usage of #[may_dangle].
499             unsafe { (&mut *self.value.get()).assume_init_drop() };
500         }
501     }
502 }
503
504 /// A value which is initialized on the first access.
505 ///
506 /// This type is a thread-safe `Lazy`, and can be used in statics.
507 ///
508 /// # Examples
509 ///
510 /// ```
511 /// #![feature(once_cell)]
512 ///
513 /// use std::collections::HashMap;
514 ///
515 /// use std::lazy::SyncLazy;
516 ///
517 /// static HASHMAP: SyncLazy<HashMap<i32, String>> = SyncLazy::new(|| {
518 ///     println!("initializing");
519 ///     let mut m = HashMap::new();
520 ///     m.insert(13, "Spica".to_string());
521 ///     m.insert(74, "Hoyten".to_string());
522 ///     m
523 /// });
524 ///
525 /// fn main() {
526 ///     println!("ready");
527 ///     std::thread::spawn(|| {
528 ///         println!("{:?}", HASHMAP.get(&13));
529 ///     }).join().unwrap();
530 ///     println!("{:?}", HASHMAP.get(&74));
531 ///
532 ///     // Prints:
533 ///     //   ready
534 ///     //   initializing
535 ///     //   Some("Spica")
536 ///     //   Some("Hoyten")
537 /// }
538 /// ```
539 #[unstable(feature = "once_cell", issue = "74465")]
540 pub struct SyncLazy<T, F = fn() -> T> {
541     cell: SyncOnceCell<T>,
542     init: Cell<Option<F>>,
543 }
544
545 #[unstable(feature = "once_cell", issue = "74465")]
546 impl<T: fmt::Debug, F> fmt::Debug for SyncLazy<T, F> {
547     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
548         f.debug_struct("Lazy").field("cell", &self.cell).finish_non_exhaustive()
549     }
550 }
551
552 // We never create a `&F` from a `&SyncLazy<T, F>` so it is fine
553 // to not impl `Sync` for `F`
554 // we do create a `&mut Option<F>` in `force`, but this is
555 // properly synchronized, so it only happens once
556 // so it also does not contribute to this impl.
557 #[unstable(feature = "once_cell", issue = "74465")]
558 unsafe impl<T, F: Send> Sync for SyncLazy<T, F> where SyncOnceCell<T>: Sync {}
559 // auto-derived `Send` impl is OK.
560
561 #[unstable(feature = "once_cell", issue = "74465")]
562 impl<T, F: UnwindSafe> RefUnwindSafe for SyncLazy<T, F> where SyncOnceCell<T>: RefUnwindSafe {}
563 #[unstable(feature = "once_cell", issue = "74465")]
564 impl<T, F: UnwindSafe> UnwindSafe for SyncLazy<T, F> where SyncOnceCell<T>: UnwindSafe {}
565
566 impl<T, F> SyncLazy<T, F> {
567     /// Creates a new lazy value with the given initializing
568     /// function.
569     #[unstable(feature = "once_cell", issue = "74465")]
570     pub const fn new(f: F) -> SyncLazy<T, F> {
571         SyncLazy { cell: SyncOnceCell::new(), init: Cell::new(Some(f)) }
572     }
573 }
574
575 impl<T, F: FnOnce() -> T> SyncLazy<T, F> {
576     /// Forces the evaluation of this lazy value and
577     /// returns a reference to result. This is equivalent
578     /// to the `Deref` impl, but is explicit.
579     ///
580     /// # Examples
581     ///
582     /// ```
583     /// #![feature(once_cell)]
584     ///
585     /// use std::lazy::SyncLazy;
586     ///
587     /// let lazy = SyncLazy::new(|| 92);
588     ///
589     /// assert_eq!(SyncLazy::force(&lazy), &92);
590     /// assert_eq!(&*lazy, &92);
591     /// ```
592     #[unstable(feature = "once_cell", issue = "74465")]
593     pub fn force(this: &SyncLazy<T, F>) -> &T {
594         this.cell.get_or_init(|| match this.init.take() {
595             Some(f) => f(),
596             None => panic!("Lazy instance has previously been poisoned"),
597         })
598     }
599 }
600
601 #[unstable(feature = "once_cell", issue = "74465")]
602 impl<T, F: FnOnce() -> T> Deref for SyncLazy<T, F> {
603     type Target = T;
604     fn deref(&self) -> &T {
605         SyncLazy::force(self)
606     }
607 }
608
609 #[unstable(feature = "once_cell", issue = "74465")]
610 impl<T: Default> Default for SyncLazy<T> {
611     /// Creates a new lazy value using `Default` as the initializing function.
612     fn default() -> SyncLazy<T> {
613         SyncLazy::new(T::default)
614     }
615 }