55: internally use MaybeUninit r=japaric a=japaric

which has been proposed in rust-lang/rfcs#1892

Co-authored-by: Jorge Aparicio <jorge@japaric.io>
This commit is contained in:
bors[bot] 2018-08-19 09:22:56 +00:00
commit 9037d97263
4 changed files with 69 additions and 72 deletions

View File

@ -2,46 +2,51 @@
pub mod mem {
#[cfg(not(feature = "const-fn"))]
pub use core::mem::uninitialized;
pub use core::mem;
pub use core::mem::{replace, zeroed, ManuallyDrop};
// See RFC 1892
#[cfg(feature = "const-fn")]
pub const unsafe fn uninitialized<T>() -> T {
#[allow(unions_with_drop_fields)]
union U<T> {
none: (),
some: T,
pub union MaybeUninit<T> {
uninit: (),
value: ManuallyDrop<T>,
}
// workaround to get this to compile on stable ("unions with non-`Copy` fields are unstable")
#[cfg(not(feature = "const-fn"))]
pub struct MaybeUninit<T> {
value: ManuallyDrop<T>
}
impl<T> MaybeUninit<T> {
#[cfg(feature = "const-fn")]
pub const unsafe fn uninitialized() -> Self {
MaybeUninit { uninit: () }
}
U { none: () }.some
}
}
#[cfg(feature = "const-fn")] // Remove this if there are more tests
#[cfg(test)]
mod test {
use __core;
use __core::mem::ManuallyDrop;
use core;
#[cfg(feature = "const-fn")]
#[test]
fn static_uninitzialized() {
static mut I: i32 = unsafe { __core::mem::uninitialized() };
// Initialize before drop
unsafe { core::ptr::write(&mut I as *mut i32, 42) };
unsafe { assert_eq!(I, 42) };
}
#[cfg(feature = "const-fn")]
#[test]
fn static_new_manually_drop() {
static mut M: ManuallyDrop<i32> = ManuallyDrop::new(42);
unsafe {
assert_eq!(*M, 42);
#[cfg(not(feature = "const-fn"))]
pub unsafe fn uninitialized() -> Self {
mem::uninitialized()
}
// Drop before deinitialization
unsafe { core::ptr::drop_in_place(&mut M as &mut i32 as *mut i32) };
}
/// Get a reference to the contained value.
///
/// # Unsafety
///
/// It is up to the caller to guarantee that the the `MaybeUninit` really is in an
/// initialized state, otherwise this will immediately cause undefined behavior.
pub unsafe fn get_ref(&self) -> &T {
&*self.value
}
/// Get a mutable reference to the contained value.
///
/// # Unsafety
///
/// It is up to the caller to guarantee that the the `MaybeUninit` really is in an
/// initialized state, otherwise this will immediately cause undefined behavior.
pub unsafe fn get_mut(&mut self) -> &mut T {
&mut *self.value
}
}
}

View File

@ -8,11 +8,11 @@ use core::ptr;
#[cfg(not(feature = "smaller-atomics"))]
use core::sync::atomic::{AtomicUsize, Ordering};
use generic_array::typenum::{Sum, U1, Unsigned};
use generic_array::typenum::{Sum, Unsigned, U1};
use generic_array::{ArrayLength, GenericArray};
pub use self::spsc::{Consumer, Producer};
use __core::mem::{self, ManuallyDrop};
use __core::mem::MaybeUninit;
mod spsc;
@ -230,7 +230,7 @@ where
// this is where we enqueue new items
tail: Atomic<U>,
buffer: ManuallyDrop<GenericArray<T, Sum<N, U1>>>,
buffer: MaybeUninit<GenericArray<T, Sum<N, U1>>>,
}
impl<T, N, U> RingBuffer<T, N, U>
@ -334,7 +334,7 @@ macro_rules! impl_ {
/// Creates an empty ring buffer with a fixed capacity of `N`
pub const fn $uxx() -> Self {
RingBuffer {
buffer: ManuallyDrop::new(unsafe { mem::uninitialized() }),
buffer: unsafe { MaybeUninit::uninitialized() },
head: Atomic::new(0),
tail: Atomic::new(0),
}
@ -348,7 +348,7 @@ macro_rules! impl_ {
let head = self.head.get_mut();
let tail = self.tail.get_mut();
let buffer = self.buffer.as_slice();
let buffer = unsafe { self.buffer.get_ref() };
if *head != *tail {
let item = unsafe { ptr::read(buffer.get_unchecked(usize::from(*head))) };
@ -387,7 +387,7 @@ macro_rules! impl_ {
let tail = self.tail.get_mut();
let buffer = self.buffer.as_mut_slice();
let buffer = unsafe { self.buffer.get_mut() };
let next_tail = (*tail + 1) % n;
// NOTE(ptr::write) the memory slot that we are about to write to is
@ -473,7 +473,7 @@ macro_rules! iterator {
let head = self.rb.head.load_relaxed().into();
let capacity = self.rb.capacity().into() + 1;
let buffer = self.rb.buffer.$asref();
let buffer = unsafe { self.rb.buffer.$asref() };
let ptr: $ptr = buffer.$asptr();
let i = (head + self.index) % capacity;
self.index += 1;
@ -498,8 +498,8 @@ macro_rules! make_ref_mut {
};
}
iterator!(struct Iter -> &'a T, *const T, as_slice, as_ptr, make_ref);
iterator!(struct IterMut -> &'a mut T, *mut T, as_mut_slice, as_mut_ptr, make_ref_mut);
iterator!(struct Iter -> &'a T, *const T, get_ref, as_ptr, make_ref);
iterator!(struct IterMut -> &'a mut T, *mut T, get_mut, as_mut_ptr, make_ref_mut);
#[cfg(test)]
mod tests {

View File

@ -2,7 +2,7 @@ use core::marker::PhantomData;
use core::ops::Add;
use core::ptr::{self, NonNull};
use generic_array::typenum::{Sum, U1, Unsigned};
use generic_array::typenum::{Sum, Unsigned, U1};
use generic_array::ArrayLength;
use ring_buffer::{RingBuffer, Uxx};
@ -47,8 +47,7 @@ where
Sum<N, U1>: ArrayLength<T>,
T: Send,
U: Uxx,
{
}
{}
/// A ring buffer "producer"; it can enqueue items into the ring buffer
// NOTE the producer semantically owns the `tail` pointer of the ring buffer
@ -69,8 +68,7 @@ where
Sum<N, U1>: ArrayLength<T>,
T: Send,
U: Uxx,
{
}
{}
macro_rules! impl_ {
($uxx:ident) => {
@ -114,7 +112,7 @@ macro_rules! impl_ {
let rb = self.rb.as_ref();
let n = rb.capacity() + 1;
let buffer: &[T] = rb.buffer.as_ref();
let buffer = rb.buffer.get_ref();
let item = ptr::read(buffer.get_unchecked(usize::from(head)));
rb.head.store_release((head + 1) % n);
@ -183,7 +181,7 @@ macro_rules! impl_ {
let rb = self.rb.as_mut();
let n = rb.capacity() + 1;
let buffer: &mut [T] = rb.buffer.as_mut();
let buffer = rb.buffer.get_mut();
let next_tail = (tail + 1) % n;
// NOTE(ptr::write) the memory slot that we are about to write to is

View File

@ -2,7 +2,7 @@ use core::{fmt, ops, ptr, slice};
use generic_array::{ArrayLength, GenericArray};
use __core::mem::{self, ManuallyDrop};
use __core::mem::MaybeUninit;
use core::iter::FromIterator;
@ -39,7 +39,7 @@ pub struct Vec<T, N>
where
N: ArrayLength<T>,
{
buffer: ManuallyDrop<GenericArray<T, N>>,
buffer: MaybeUninit<GenericArray<T, N>>,
len: usize,
}
@ -52,7 +52,7 @@ where
/// Constructs a new, empty vector with a fixed capacity of `N`
pub const fn new() -> Self {
Vec {
buffer: ManuallyDrop::new(unsafe { mem::uninitialized() }),
buffer: unsafe { MaybeUninit::uninitialized() },
len: 0,
}
}
@ -112,7 +112,7 @@ where
pub(crate) unsafe fn pop_unchecked(&mut self) -> T {
debug_assert!(!self.is_empty());
let buffer = self.buffer.as_slice();
let buffer = self.buffer.get_ref();
self.len -= 1;
let item = ptr::read(buffer.get_unchecked(self.len));
@ -132,7 +132,7 @@ where
}
pub(crate) unsafe fn push_unchecked(&mut self, item: T) {
let buffer = self.buffer.as_mut_slice();
let buffer = self.buffer.get_mut();
// NOTE(ptr::write) the memory slot that we are about to write to is uninitialized. We
// use `ptr::write` to avoid running `T`'s destructor on the uninitialized memory
@ -314,7 +314,6 @@ where
}
}
impl<T, N> FromIterator<T> for Vec<T, N>
where
N: ArrayLength<T>,
@ -345,15 +344,15 @@ where
next: usize,
}
impl <T, N> Iterator for IntoIter<T, N>
impl<T, N> Iterator for IntoIter<T, N>
where
N: ArrayLength<T>,
{
type Item = T;
fn next(&mut self) -> Option<Self::Item> {
if self.next < self.vec.len() {
let buffer = self.vec.buffer.as_slice();
let item = unsafe {ptr::read(buffer.get_unchecked(self.next))};
let buffer = unsafe { self.vec.buffer.get_ref() };
let item = unsafe { ptr::read(buffer.get_unchecked(self.next)) };
self.next += 1;
Some(item)
} else {
@ -362,7 +361,7 @@ where
}
}
impl <T, N> Drop for IntoIter<T, N>
impl<T, N> Drop for IntoIter<T, N>
where
N: ArrayLength<T>,
{
@ -376,7 +375,7 @@ where
}
}
impl <T, N> IntoIterator for Vec<T, N>
impl<T, N> IntoIterator for Vec<T, N>
where
N: ArrayLength<T>,
{
@ -384,10 +383,7 @@ where
type IntoIter = IntoIter<T, N>;
fn into_iter(self) -> Self::IntoIter {
IntoIter {
vec: self,
next: 0,
}
IntoIter { vec: self, next: 0 }
}
}
@ -448,7 +444,7 @@ where
type Target = [T];
fn deref(&self) -> &[T] {
let buffer = self.buffer.as_slice();
let buffer = unsafe { self.buffer.get_ref() };
// NOTE(unsafe) avoid bound checks in the slicing operation
// &buffer[..self.len]
unsafe { slice::from_raw_parts(buffer.as_ptr(), self.len) }
@ -461,7 +457,7 @@ where
{
fn deref_mut(&mut self) -> &mut [T] {
let len = self.len();
let buffer = self.buffer.as_mut_slice();
let buffer = unsafe { self.buffer.get_mut() };
// NOTE(unsafe) avoid bound checks in the slicing operation
// &mut buffer[..len]
@ -521,7 +517,7 @@ mod tests {
}
macro_rules! droppable {
() => (
() => {
struct Droppable;
impl Droppable {
fn new() -> Self {
@ -540,12 +536,11 @@ mod tests {
}
static mut COUNT: i32 = 0;
)
};
}
#[test]
fn drop() {
droppable!();
{
@ -660,7 +655,6 @@ mod tests {
#[test]
fn iter_move_drop() {
droppable!();
{