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