mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-01 15:01:51 +00:00
Auto merge of #75171 - amosonn:new_zeroed_slice, r=Amanieu
New zeroed slice Add to #63291 the methods ```rust impl<T> Box<[T]> { pub fn new_zeroed_slice(len: usize) -> Box<[MaybeUninit<T>]> {…} } impl<T> Rc<[T]> { pub fn new_zeroed_slice(len: usize) -> Rc<[MaybeUninit<T>]> {…} } impl<T> Arc<[T]> { pub fn new_zeroed_slice(len: usize) -> Arc<[MaybeUninit<T>]> {…} } ``` as suggested in https://github.com/rust-lang/rust/issues/63291#issuecomment-605511675 . Also optimize `{Rc, Arc}::new_zeroed` to use `alloc_zeroed`, otherwise they are no more efficient than using `new_uninit` and zeroing the memory manually (which was the original implementation).
This commit is contained in:
commit
663d2f5cd3
@ -271,6 +271,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>> {
|
||||
|
@ -247,7 +247,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;
|
||||
@ -349,9 +349,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>>,
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
@ -378,9 +380,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>>,
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
@ -460,6 +464,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>> {
|
||||
@ -905,6 +943,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.
|
||||
@ -914,7 +953,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());
|
||||
@ -932,9 +971,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>,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@ -965,9 +1006,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]>,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2061,7 +2104,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
|
||||
|
@ -21,7 +21,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;
|
||||
@ -343,9 +343,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>>,
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
@ -372,9 +374,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>>,
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
@ -426,7 +430,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
|
||||
///
|
||||
@ -453,6 +457,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>> {
|
||||
@ -858,6 +896,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.
|
||||
@ -866,7 +905,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());
|
||||
@ -884,9 +923,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>,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@ -917,9 +958,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]>,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user