Add new_uninit and assume_init on Box, Rc, and Arc
This commit is contained in:
parent
1613fdae37
commit
7b02b9f8ec
@ -93,6 +93,7 @@ use core::ops::{
|
||||
use core::ptr::{self, NonNull, Unique};
|
||||
use core::task::{Context, Poll};
|
||||
|
||||
use crate::alloc;
|
||||
use crate::vec::Vec;
|
||||
use crate::raw_vec::RawVec;
|
||||
use crate::str::from_boxed_utf8_unchecked;
|
||||
@ -121,6 +122,32 @@ impl<T> Box<T> {
|
||||
box x
|
||||
}
|
||||
|
||||
/// Construct a new box with uninitialized contents.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(new_uninit)]
|
||||
///
|
||||
/// let mut five = Box::<u32>::new_uninit();
|
||||
///
|
||||
/// let five = unsafe {
|
||||
/// // Deferred initialization:
|
||||
/// five.as_mut_ptr().write(5);
|
||||
///
|
||||
/// Box::assume_init(five)
|
||||
/// };
|
||||
///
|
||||
/// assert_eq!(*five, 5)
|
||||
/// ```
|
||||
#[unstable(feature = "new_uninit", issue = "0")]
|
||||
pub fn new_uninit() -> Box<mem::MaybeUninit<T>> {
|
||||
let layout = alloc::Layout::new::<mem::MaybeUninit<T>>();
|
||||
let ptr = unsafe { alloc::alloc(layout) };
|
||||
let unique = Unique::new(ptr).unwrap_or_else(|| alloc::handle_alloc_error(layout));
|
||||
Box(unique.cast())
|
||||
}
|
||||
|
||||
/// Constructs a new `Pin<Box<T>>`. If `T` does not implement `Unpin`, then
|
||||
/// `x` will be pinned in memory and unable to be moved.
|
||||
#[stable(feature = "pin", since = "1.33.0")]
|
||||
@ -130,6 +157,40 @@ impl<T> Box<T> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Box<mem::MaybeUninit<T>> {
|
||||
/// Convert to `Box<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)]
|
||||
///
|
||||
/// let mut five = Box::<u32>::new_uninit();
|
||||
///
|
||||
/// let five: Box<u32> = unsafe {
|
||||
/// // Deferred initialization:
|
||||
/// five.as_mut_ptr().write(5);
|
||||
///
|
||||
/// Box::assume_init(five)
|
||||
/// };
|
||||
///
|
||||
/// assert_eq!(*five, 5)
|
||||
/// ```
|
||||
#[unstable(feature = "new_uninit", issue = "0")]
|
||||
#[inline]
|
||||
pub unsafe fn assume_init(this: Self) -> Box<T> {
|
||||
Box(Box::into_unique(this).cast())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: ?Sized> Box<T> {
|
||||
/// Constructs a box from a raw pointer.
|
||||
///
|
||||
|
@ -327,6 +327,43 @@ impl<T> Rc<T> {
|
||||
}))
|
||||
}
|
||||
|
||||
/// Construct a new Rc with uninitialized contents.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(new_uninit)]
|
||||
/// #![feature(get_mut_unchecked)]
|
||||
///
|
||||
/// use std::rc::Rc;
|
||||
///
|
||||
/// let mut five = Rc::<u32>::new_uninit();
|
||||
///
|
||||
/// let five = unsafe {
|
||||
/// // Deferred initialization:
|
||||
/// Rc::get_mut_unchecked(&mut five).as_mut_ptr().write(5);
|
||||
///
|
||||
/// Rc::assume_init(five)
|
||||
/// };
|
||||
///
|
||||
/// assert_eq!(*five, 5)
|
||||
/// ```
|
||||
#[unstable(feature = "new_uninit", issue = "0")]
|
||||
pub fn new_uninit() -> Rc<mem::MaybeUninit<T>> {
|
||||
let layout = Layout::new::<RcBox<mem::MaybeUninit<T>>>();
|
||||
unsafe {
|
||||
let mut ptr = Global.alloc(layout)
|
||||
.unwrap_or_else(|_| handle_alloc_error(layout))
|
||||
.cast::<RcBox<mem::MaybeUninit<T>>>();
|
||||
ptr::write(&mut ptr.as_mut().strong, Cell::new(1));
|
||||
ptr::write(&mut ptr.as_mut().weak, Cell::new(1));
|
||||
Rc {
|
||||
ptr,
|
||||
phantom: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Constructs a new `Pin<Rc<T>>`. If `T` does not implement `Unpin`, then
|
||||
/// `value` will be pinned in memory and unable to be moved.
|
||||
#[stable(feature = "pin", since = "1.33.0")]
|
||||
@ -377,6 +414,48 @@ impl<T> Rc<T> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Rc<mem::MaybeUninit<T>> {
|
||||
/// Convert to `Rc<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::rc::Rc;
|
||||
///
|
||||
/// let mut five = Rc::<u32>::new_uninit();
|
||||
///
|
||||
/// let five = unsafe {
|
||||
/// // Deferred initialization:
|
||||
/// Rc::get_mut_unchecked(&mut five).as_mut_ptr().write(5);
|
||||
///
|
||||
/// Rc::assume_init(five)
|
||||
/// };
|
||||
///
|
||||
/// assert_eq!(*five, 5)
|
||||
/// ```
|
||||
#[unstable(feature = "new_uninit", issue = "0")]
|
||||
#[inline]
|
||||
pub unsafe fn assume_init(this: Self) -> Rc<T> {
|
||||
let ptr = this.ptr.cast();
|
||||
mem::forget(this);
|
||||
Rc {
|
||||
ptr,
|
||||
phantom: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: ?Sized> Rc<T> {
|
||||
/// Consumes the `Rc`, returning the wrapped pointer.
|
||||
///
|
||||
@ -582,6 +661,8 @@ impl<T: ?Sized> Rc<T> {
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(get_mut_unchecked)]
|
||||
///
|
||||
/// use std::rc::Rc;
|
||||
///
|
||||
/// let mut x = Rc::new(String::new());
|
||||
|
@ -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());
|
||||
|
@ -122,6 +122,14 @@ impl<T: ?Sized> Unique<T> {
|
||||
pub unsafe fn as_mut(&mut self) -> &mut T {
|
||||
&mut *self.as_ptr()
|
||||
}
|
||||
|
||||
/// Cast to a pointer of another type
|
||||
#[inline]
|
||||
pub const fn cast<U>(self) -> Unique<U> {
|
||||
unsafe {
|
||||
Unique::new_unchecked(self.as_ptr() as *mut U)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "ptr_internals", issue = "0")]
|
||||
|
Loading…
x
Reference in New Issue
Block a user