about summary refs log tree commit diff
path: root/src/liballoc/sync.rs
diff options
context:
space:
mode:
authorSimon Sapin <simon.sapin@exyr.org>2019-07-06 17:19:58 +0200
committerSimon Sapin <simon.sapin@exyr.org>2019-08-16 17:11:18 +0200
commit7b02b9f8ec2850ac687ee5c7d869a626e09d22cb (patch)
tree3c5a4f49589032d666c3b87aeca4a72bd392688c /src/liballoc/sync.rs
parent1613fdae37df044f2c254d25d356b3a57eb61a50 (diff)
downloadrust-7b02b9f8ec2850ac687ee5c7d869a626e09d22cb.tar.gz
rust-7b02b9f8ec2850ac687ee5c7d869a626e09d22cb.zip
Add new_uninit and assume_init on Box, Rc, and Arc
Diffstat (limited to 'src/liballoc/sync.rs')
-rw-r--r--src/liballoc/sync.rs81
1 files changed, 81 insertions, 0 deletions
diff --git a/src/liballoc/sync.rs b/src/liballoc/sync.rs
index 4cd8e1fd4dd..8c63c81ee27 100644
--- a/src/liballoc/sync.rs
+++ b/src/liballoc/sync.rs
@@ -311,6 +311,43 @@ impl<T> Arc<T> {
         Self::from_inner(Box::into_raw_non_null(x))
     }
 
+    /// Construct a Arc box with uninitialized contents.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(new_uninit)]
+    /// #![feature(get_mut_unchecked)]
+    ///
+    /// use std::sync::Arc;
+    ///
+    /// let mut five = Arc::<u32>::new_uninit();
+    ///
+    /// let five = unsafe {
+    ///     // Deferred initialization:
+    ///     Arc::get_mut_unchecked(&mut five).as_mut_ptr().write(5);
+    ///
+    ///     Arc::assume_init(five)
+    /// };
+    ///
+    /// assert_eq!(*five, 5)
+    /// ```
+    #[unstable(feature = "new_uninit", issue = "0")]
+    pub fn new_uninit() -> Arc<mem::MaybeUninit<T>> {
+        let layout = Layout::new::<ArcInner<mem::MaybeUninit<T>>>();
+        unsafe {
+            let mut ptr = Global.alloc(layout)
+                .unwrap_or_else(|_| handle_alloc_error(layout))
+                .cast::<ArcInner<mem::MaybeUninit<T>>>();
+            ptr::write(&mut ptr.as_mut().strong, atomic::AtomicUsize::new(1));
+            ptr::write(&mut ptr.as_mut().weak, atomic::AtomicUsize::new(1));
+            Arc {
+                ptr,
+                phantom: PhantomData,
+            }
+        }
+    }
+
     /// Constructs a new `Pin<Arc<T>>`. If `T` does not implement `Unpin`, then
     /// `data` will be pinned in memory and unable to be moved.
     #[stable(feature = "pin", since = "1.33.0")]
@@ -361,6 +398,48 @@ impl<T> Arc<T> {
     }
 }
 
+impl<T> Arc<mem::MaybeUninit<T>> {
+    /// Convert to `Arc<T>`.
+    ///
+    /// # Safety
+    ///
+    /// As with [`MaybeUninit::assume_init`],
+    /// it is up to the caller to guarantee that the value
+    /// really is in an initialized state.
+    /// Calling this when the content is not yet fully initialized
+    /// causes immediate undefined behavior.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(new_uninit)]
+    /// #![feature(get_mut_unchecked)]
+    ///
+    /// use std::sync::Arc;
+    ///
+    /// let mut five = Arc::<u32>::new_uninit();
+    ///
+    /// let five = unsafe {
+    ///     // Deferred initialization:
+    ///     Arc::get_mut_unchecked(&mut five).as_mut_ptr().write(5);
+    ///
+    ///     Arc::assume_init(five)
+    /// };
+    ///
+    /// assert_eq!(*five, 5)
+    /// ```
+    #[unstable(feature = "new_uninit", issue = "0")]
+    #[inline]
+    pub unsafe fn assume_init(this: Self) -> Arc<T> {
+        let ptr = this.ptr.cast();
+        mem::forget(this);
+        Arc {
+            ptr,
+            phantom: PhantomData,
+        }
+    }
+}
+
 impl<T: ?Sized> Arc<T> {
     /// Consumes the `Arc`, returning the wrapped pointer.
     ///
@@ -967,6 +1046,8 @@ impl<T: ?Sized> Arc<T> {
     /// # Examples
     ///
     /// ```
+    /// #![feature(get_mut_unchecked)]
+    ///
     /// use std::sync::Arc;
     ///
     /// let mut x = Arc::new(String::new());