about summary refs log tree commit diff
path: root/library/std/src/sync/lazy_lock.rs
diff options
context:
space:
mode:
authorAlex Saveau <saveau.alexandre@gmail.com>2022-12-26 00:52:58 -0800
committerAlex Saveau <saveau.alexandre@gmail.com>2023-04-14 13:15:11 -0700
commitd9256f94a987a008484caab5acf5a6e06c24ecd3 (patch)
tree130636bb4e12ab64e3139e091432bb63ab531cb7 /library/std/src/sync/lazy_lock.rs
parent660c966ff941ddf995d3251df32508b383cd4cee (diff)
downloadrust-d9256f94a987a008484caab5acf5a6e06c24ecd3.tar.gz
rust-d9256f94a987a008484caab5acf5a6e06c24ecd3.zip
Add Lazy{Cell,Lock}::into_inner
Signed-off-by: Alex Saveau <saveau.alexandre@gmail.com>
Diffstat (limited to 'library/std/src/sync/lazy_lock.rs')
-rw-r--r--library/std/src/sync/lazy_lock.rs38
1 files changed, 37 insertions, 1 deletions
diff --git a/library/std/src/sync/lazy_lock.rs b/library/std/src/sync/lazy_lock.rs
index 8e9ea293ce4..a6bc468b092 100644
--- a/library/std/src/sync/lazy_lock.rs
+++ b/library/std/src/sync/lazy_lock.rs
@@ -1,9 +1,9 @@
 use crate::cell::UnsafeCell;
-use crate::fmt;
 use crate::mem::ManuallyDrop;
 use crate::ops::Deref;
 use crate::panic::{RefUnwindSafe, UnwindSafe};
 use crate::sync::Once;
+use crate::{fmt, ptr};
 
 use super::once::ExclusiveState;
 
@@ -69,6 +69,42 @@ impl<T, F: FnOnce() -> T> LazyLock<T, F> {
         LazyLock { once: Once::new(), data: UnsafeCell::new(Data { f: ManuallyDrop::new(f) }) }
     }
 
+    /// Consumes this `LazyLock` returning the stored value.
+    ///
+    /// Returns `Ok(value)` if `Lazy` is initialized and `Err(f)` otherwise.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(lazy_cell)]
+    /// #![feature(lazy_cell_consume)]
+    ///
+    /// use std::sync::LazyLock;
+    ///
+    /// let hello = "Hello, World!".to_string();
+    ///
+    /// let lazy = LazyLock::new(|| hello.to_uppercase());
+    ///
+    /// assert_eq!(&*lazy, "HELLO, WORLD!");
+    /// assert_eq!(LazyLock::into_inner(lazy).ok(), Some("HELLO, WORLD!".to_string()));
+    /// ```
+    #[unstable(feature = "lazy_cell_consume", issue = "109736")]
+    pub fn into_inner(mut this: Self) -> Result<T, F> {
+        let state = this.once.state();
+        match state {
+            ExclusiveState::Poisoned => panic!("LazyLock instance has previously been poisoned"),
+            state => {
+                let this = ManuallyDrop::new(this);
+                let data = unsafe { ptr::read(&this.data) }.into_inner();
+                match state {
+                    ExclusiveState::Incomplete => Err(ManuallyDrop::into_inner(unsafe { data.f })),
+                    ExclusiveState::Complete => Ok(ManuallyDrop::into_inner(unsafe { data.value })),
+                    ExclusiveState::Poisoned => unreachable!(),
+                }
+            }
+        }
+    }
+
     /// Forces the evaluation of this lazy value and
     /// returns a reference to result. This is equivalent
     /// to the `Deref` impl, but is explicit.