Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New zeroed slice #75171

Merged
merged 3 commits into from
Aug 22, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions library/alloc/src/boxed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,29 @@ impl<T> Box<[T]> {
pub fn new_uninit_slice(len: usize) -> Box<[mem::MaybeUninit<T>]> {
unsafe { RawVec::with_capacity(len).into_box(len) }
}

/// Constructs a new boxed slice with uninitialized contents, with the memory
/// being filled with `0` bytes.
///
/// See [`MaybeUninit::zeroed`][zeroed] for examples of correct and incorrect usage
/// of this method.
///
/// # Examples
///
/// ```
/// #![feature(new_uninit)]
///
/// let values = Box::<[u32]>::new_zeroed_slice(3);
/// let values = unsafe { values.assume_init() };
///
/// assert_eq!(*values, [0, 0, 0])
/// ```
///
/// [zeroed]: ../../std/mem/union.MaybeUninit.html#method.zeroed
#[unstable(feature = "new_uninit", issue = "63291")]
pub fn new_zeroed_slice(len: usize) -> Box<[mem::MaybeUninit<T>]> {
unsafe { RawVec::with_capacity_zeroed(len).into_box(len) }
}
}

impl<T> Box<mem::MaybeUninit<T>> {
Expand Down
73 changes: 58 additions & 15 deletions library/alloc/src/rc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -250,7 +250,7 @@ use core::pin::Pin;
use core::ptr::{self, NonNull};
use core::slice::from_raw_parts_mut;

use crate::alloc::{box_free, handle_alloc_error, AllocRef, Global, Layout};
use crate::alloc::{box_free, handle_alloc_error, AllocErr, AllocRef, Global, Layout};
use crate::borrow::{Cow, ToOwned};
use crate::string::String;
use crate::vec::Vec;
Expand Down Expand Up @@ -352,9 +352,11 @@ impl<T> Rc<T> {
#[unstable(feature = "new_uninit", issue = "63291")]
pub fn new_uninit() -> Rc<mem::MaybeUninit<T>> {
unsafe {
Rc::from_ptr(Rc::allocate_for_layout(Layout::new::<T>(), |mem| {
mem as *mut RcBox<mem::MaybeUninit<T>>
}))
Rc::from_ptr(Rc::allocate_for_layout(
Layout::new::<T>(),
|layout| Global.alloc(layout),
|mem| mem as *mut RcBox<mem::MaybeUninit<T>>,
))
}
}

Expand All @@ -381,9 +383,11 @@ impl<T> Rc<T> {
#[unstable(feature = "new_uninit", issue = "63291")]
pub fn new_zeroed() -> Rc<mem::MaybeUninit<T>> {
unsafe {
let mut uninit = Self::new_uninit();
ptr::write_bytes::<T>(Rc::get_mut_unchecked(&mut uninit).as_mut_ptr(), 0, 1);
uninit
Rc::from_ptr(Rc::allocate_for_layout(
Layout::new::<T>(),
|layout| Global.alloc_zeroed(layout),
|mem| mem as *mut RcBox<mem::MaybeUninit<T>>,
))
}
}

Expand Down Expand Up @@ -465,6 +469,40 @@ impl<T> Rc<[T]> {
pub fn new_uninit_slice(len: usize) -> Rc<[mem::MaybeUninit<T>]> {
unsafe { Rc::from_ptr(Rc::allocate_for_slice(len)) }
}

/// Constructs a new reference-counted slice with uninitialized contents, with the memory being
/// filled with `0` bytes.
///
/// See [`MaybeUninit::zeroed`][zeroed] for examples of correct and
/// incorrect usage of this method.
///
/// # Examples
///
/// ```
/// #![feature(new_uninit)]
///
/// use std::rc::Rc;
///
/// let values = Rc::<[u32]>::new_zeroed_slice(3);
/// let values = unsafe { values.assume_init() };
///
/// assert_eq!(*values, [0, 0, 0])
/// ```
///
/// [zeroed]: ../../std/mem/union.MaybeUninit.html#method.zeroed
#[unstable(feature = "new_uninit", issue = "63291")]
pub fn new_zeroed_slice(len: usize) -> Rc<[mem::MaybeUninit<T>]> {
unsafe {
Rc::from_ptr(Rc::allocate_for_layout(
Layout::array::<T>(len).unwrap(),
|layout| Global.alloc_zeroed(layout),
|mem| {
ptr::slice_from_raw_parts_mut(mem as *mut T, len)
as *mut RcBox<[mem::MaybeUninit<T>]>
},
))
}
}
}

impl<T> Rc<mem::MaybeUninit<T>> {
Expand Down Expand Up @@ -919,6 +957,7 @@ impl<T: ?Sized> Rc<T> {
/// and must return back a (potentially fat)-pointer for the `RcBox<T>`.
unsafe fn allocate_for_layout(
value_layout: Layout,
allocate: impl FnOnce(Layout) -> Result<NonNull<[u8]>, AllocErr>,
mem_to_rcbox: impl FnOnce(*mut u8) -> *mut RcBox<T>,
) -> *mut RcBox<T> {
// Calculate layout using the given value layout.
Expand All @@ -928,7 +967,7 @@ impl<T: ?Sized> Rc<T> {
let layout = Layout::new::<RcBox<()>>().extend(value_layout).unwrap().0.pad_to_align();

// Allocate for the layout.
let ptr = Global.alloc(layout).unwrap_or_else(|_| handle_alloc_error(layout));
let ptr = allocate(layout).unwrap_or_else(|_| handle_alloc_error(layout));

// Initialize the RcBox
let inner = mem_to_rcbox(ptr.as_non_null_ptr().as_ptr());
Expand All @@ -946,9 +985,11 @@ impl<T: ?Sized> Rc<T> {
unsafe fn allocate_for_ptr(ptr: *const T) -> *mut RcBox<T> {
// Allocate for the `RcBox<T>` using the given value.
unsafe {
Self::allocate_for_layout(Layout::for_value(&*ptr), |mem| {
set_data_ptr(ptr as *mut T, mem) as *mut RcBox<T>
})
Self::allocate_for_layout(
Layout::for_value(&*ptr),
|layout| Global.alloc(layout),
|mem| set_data_ptr(ptr as *mut T, mem) as *mut RcBox<T>,
)
}
}

Expand Down Expand Up @@ -979,9 +1020,11 @@ impl<T> Rc<[T]> {
/// Allocates an `RcBox<[T]>` with the given length.
unsafe fn allocate_for_slice(len: usize) -> *mut RcBox<[T]> {
unsafe {
Self::allocate_for_layout(Layout::array::<T>(len).unwrap(), |mem| {
ptr::slice_from_raw_parts_mut(mem as *mut T, len) as *mut RcBox<[T]>
})
Self::allocate_for_layout(
Layout::array::<T>(len).unwrap(),
|layout| Global.alloc(layout),
|mem| ptr::slice_from_raw_parts_mut(mem as *mut T, len) as *mut RcBox<[T]>,
)
}
}
}
Expand Down Expand Up @@ -2090,7 +2133,7 @@ impl<T: ?Sized> AsRef<T> for Rc<T> {
#[stable(feature = "pin", since = "1.33.0")]
impl<T: ?Sized> Unpin for Rc<T> {}

/// Get the offset within an `ArcInner` for
/// Get the offset within an `RcBox` for
/// a payload of type described by a pointer.
///
/// # Safety
Expand Down
73 changes: 58 additions & 15 deletions library/alloc/src/sync.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ use core::slice::from_raw_parts_mut;
use core::sync::atomic;
use core::sync::atomic::Ordering::{Acquire, Relaxed, Release, SeqCst};

use crate::alloc::{box_free, handle_alloc_error, AllocRef, Global, Layout};
use crate::alloc::{box_free, handle_alloc_error, AllocErr, AllocRef, Global, Layout};
use crate::borrow::{Cow, ToOwned};
use crate::boxed::Box;
use crate::rc::is_dangling;
Expand Down Expand Up @@ -352,9 +352,11 @@ impl<T> Arc<T> {
#[unstable(feature = "new_uninit", issue = "63291")]
pub fn new_uninit() -> Arc<mem::MaybeUninit<T>> {
unsafe {
Arc::from_ptr(Arc::allocate_for_layout(Layout::new::<T>(), |mem| {
mem as *mut ArcInner<mem::MaybeUninit<T>>
}))
Arc::from_ptr(Arc::allocate_for_layout(
Layout::new::<T>(),
|layout| Global.alloc(layout),
|mem| mem as *mut ArcInner<mem::MaybeUninit<T>>,
))
}
}

Expand All @@ -381,9 +383,11 @@ impl<T> Arc<T> {
#[unstable(feature = "new_uninit", issue = "63291")]
pub fn new_zeroed() -> Arc<mem::MaybeUninit<T>> {
unsafe {
let mut uninit = Self::new_uninit();
ptr::write_bytes::<T>(Arc::get_mut_unchecked(&mut uninit).as_mut_ptr(), 0, 1);
uninit
Arc::from_ptr(Arc::allocate_for_layout(
Layout::new::<T>(),
|layout| Global.alloc_zeroed(layout),
|mem| mem as *mut ArcInner<mem::MaybeUninit<T>>,
))
}
}

Expand Down Expand Up @@ -437,7 +441,7 @@ impl<T> Arc<T> {
}

impl<T> Arc<[T]> {
/// Constructs a new reference-counted slice with uninitialized contents.
/// Constructs a new atomically reference-counted slice with uninitialized contents.
///
/// # Examples
///
Expand All @@ -464,6 +468,40 @@ impl<T> Arc<[T]> {
pub fn new_uninit_slice(len: usize) -> Arc<[mem::MaybeUninit<T>]> {
unsafe { Arc::from_ptr(Arc::allocate_for_slice(len)) }
}

/// Constructs a new atomically reference-counted slice with uninitialized contents, with the memory being
/// filled with `0` bytes.
///
/// See [`MaybeUninit::zeroed`][zeroed] for examples of correct and
/// incorrect usage of this method.
///
/// # Examples
///
/// ```
/// #![feature(new_uninit)]
///
/// use std::sync::Arc;
///
/// let values = Arc::<[u32]>::new_zeroed_slice(3);
/// let values = unsafe { values.assume_init() };
///
/// assert_eq!(*values, [0, 0, 0])
/// ```
///
/// [zeroed]: ../../std/mem/union.MaybeUninit.html#method.zeroed
#[unstable(feature = "new_uninit", issue = "63291")]
pub fn new_zeroed_slice(len: usize) -> Arc<[mem::MaybeUninit<T>]> {
unsafe {
Arc::from_ptr(Arc::allocate_for_layout(
Layout::array::<T>(len).unwrap(),
|layout| Global.alloc_zeroed(layout),
|mem| {
ptr::slice_from_raw_parts_mut(mem as *mut T, len)
as *mut ArcInner<[mem::MaybeUninit<T>]>
},
))
}
}
}

impl<T> Arc<mem::MaybeUninit<T>> {
Expand Down Expand Up @@ -875,6 +913,7 @@ impl<T: ?Sized> Arc<T> {
/// and must return back a (potentially fat)-pointer for the `ArcInner<T>`.
unsafe fn allocate_for_layout(
value_layout: Layout,
allocate: impl FnOnce(Layout) -> Result<NonNull<[u8]>, AllocErr>,
mem_to_arcinner: impl FnOnce(*mut u8) -> *mut ArcInner<T>,
) -> *mut ArcInner<T> {
// Calculate layout using the given value layout.
Expand All @@ -883,7 +922,7 @@ impl<T: ?Sized> Arc<T> {
// reference (see #54908).
let layout = Layout::new::<ArcInner<()>>().extend(value_layout).unwrap().0.pad_to_align();

let ptr = Global.alloc(layout).unwrap_or_else(|_| handle_alloc_error(layout));
let ptr = allocate(layout).unwrap_or_else(|_| handle_alloc_error(layout));

// Initialize the ArcInner
let inner = mem_to_arcinner(ptr.as_non_null_ptr().as_ptr());
Expand All @@ -901,9 +940,11 @@ impl<T: ?Sized> Arc<T> {
unsafe fn allocate_for_ptr(ptr: *const T) -> *mut ArcInner<T> {
// Allocate for the `ArcInner<T>` using the given value.
unsafe {
Self::allocate_for_layout(Layout::for_value(&*ptr), |mem| {
set_data_ptr(ptr as *mut T, mem) as *mut ArcInner<T>
})
Self::allocate_for_layout(
Layout::for_value(&*ptr),
|layout| Global.alloc(layout),
|mem| set_data_ptr(ptr as *mut T, mem) as *mut ArcInner<T>,
)
}
}

Expand Down Expand Up @@ -934,9 +975,11 @@ impl<T> Arc<[T]> {
/// Allocates an `ArcInner<[T]>` with the given length.
unsafe fn allocate_for_slice(len: usize) -> *mut ArcInner<[T]> {
unsafe {
Self::allocate_for_layout(Layout::array::<T>(len).unwrap(), |mem| {
ptr::slice_from_raw_parts_mut(mem as *mut T, len) as *mut ArcInner<[T]>
})
Self::allocate_for_layout(
Layout::array::<T>(len).unwrap(),
|layout| Global.alloc(layout),
|mem| ptr::slice_from_raw_parts_mut(mem as *mut T, len) as *mut ArcInner<[T]>,
)
}
}
}
Expand Down