Replace (some) uninitialized with MaybeUninit (#1295)

This commit is contained in:
Yin Guanhao
2019-07-16 10:47:46 -07:00
committed by Sean McArthur
parent 0d99ddd4f4
commit 6d186fe40e
2 changed files with 64 additions and 30 deletions
+55 -25
View File
@@ -5,7 +5,7 @@ use crate::loom::{sync::atomic::AtomicUsize, sync::CausalCell};
use futures_core::ready; use futures_core::ready;
use std::fmt; use std::fmt;
use std::future::Future; use std::future::Future;
use std::mem::{self, ManuallyDrop}; use std::mem::MaybeUninit;
use std::pin::Pin; use std::pin::Pin;
use std::sync::atomic::Ordering::{self, AcqRel, Acquire}; use std::sync::atomic::Ordering::{self, AcqRel, Acquire};
use std::sync::Arc; use std::sync::Arc;
@@ -73,10 +73,10 @@ struct Inner<T> {
value: CausalCell<Option<T>>, value: CausalCell<Option<T>>,
/// The task to notify when the receiver drops without consuming the value. /// The task to notify when the receiver drops without consuming the value.
tx_task: CausalCell<ManuallyDrop<Waker>>, tx_task: CausalCell<MaybeUninit<Waker>>,
/// The task to notify when the value is sent. /// The task to notify when the value is sent.
rx_task: CausalCell<ManuallyDrop<Waker>>, rx_task: CausalCell<MaybeUninit<Waker>>,
} }
#[derive(Clone, Copy)] #[derive(Clone, Copy)]
@@ -117,8 +117,8 @@ pub fn channel<T>() -> (Sender<T>, Receiver<T>) {
let inner = Arc::new(Inner { let inner = Arc::new(Inner {
state: AtomicUsize::new(State::new().as_usize()), state: AtomicUsize::new(State::new().as_usize()),
value: CausalCell::new(None), value: CausalCell::new(None),
tx_task: CausalCell::new(ManuallyDrop::new(unsafe { mem::uninitialized() })), tx_task: CausalCell::new(MaybeUninit::uninit()),
rx_task: CausalCell::new(ManuallyDrop::new(unsafe { mem::uninitialized() })), rx_task: CausalCell::new(MaybeUninit::uninit()),
}); });
let tx = Sender { let tx = Sender {
@@ -177,9 +177,7 @@ impl<T> Sender<T> {
} }
if state.is_tx_task_set() { if state.is_tx_task_set() {
let will_notify = inner let will_notify = unsafe { inner.with_tx_task(|w| w.will_wake(cx.waker())) };
.tx_task
.with(|ptr| unsafe { (&*ptr).will_wake(cx.waker()) });
if !will_notify { if !will_notify {
state = State::unset_tx_task(&inner.state); state = State::unset_tx_task(&inner.state);
@@ -333,7 +331,9 @@ impl<T> Inner<T> {
if prev.is_rx_task_set() { if prev.is_rx_task_set() {
// TODO: Consume waker? // TODO: Consume waker?
self.rx_task.with(|ptr| unsafe { (&*ptr).wake_by_ref() }); unsafe {
self.with_rx_task(Waker::wake_by_ref);
}
} }
true true
@@ -352,9 +352,7 @@ impl<T> Inner<T> {
Ready(Err(RecvError(()))) Ready(Err(RecvError(())))
} else { } else {
if state.is_rx_task_set() { if state.is_rx_task_set() {
let will_notify = self let will_notify = unsafe { self.with_rx_task(|w| w.will_wake(cx.waker())) };
.rx_task
.with(|ptr| unsafe { (&*ptr).will_wake(cx.waker()) });
// Check if the task is still the same // Check if the task is still the same
if !will_notify { if !will_notify {
@@ -399,7 +397,9 @@ impl<T> Inner<T> {
let prev = State::set_closed(&self.state); let prev = State::set_closed(&self.state);
if prev.is_tx_task_set() && !prev.is_complete() { if prev.is_tx_task_set() && !prev.is_complete() {
self.tx_task.with(|ptr| unsafe { (&*ptr).wake_by_ref() }); unsafe {
self.with_tx_task(Waker::wake_by_ref);
}
} }
} }
@@ -408,22 +408,52 @@ impl<T> Inner<T> {
self.value.with_mut(|ptr| (*ptr).take()) self.value.with_mut(|ptr| (*ptr).take())
} }
unsafe fn with_rx_task<F, R>(&self, f: F) -> R
where
F: FnOnce(&Waker) -> R,
{
self.rx_task.with(|ptr| {
let waker: *const Waker = (&*ptr).as_ptr();
f(&*waker)
})
}
unsafe fn with_tx_task<F, R>(&self, f: F) -> R
where
F: FnOnce(&Waker) -> R,
{
self.tx_task.with(|ptr| {
let waker: *const Waker = (&*ptr).as_ptr();
f(&*waker)
})
}
unsafe fn drop_rx_task(&self) { unsafe fn drop_rx_task(&self) {
self.rx_task.with_mut(|ptr| ManuallyDrop::drop(&mut *ptr)) self.rx_task.with_mut(|ptr| {
let ptr: *mut Waker = (&mut *ptr).as_mut_ptr();
ptr.drop_in_place();
});
} }
unsafe fn drop_tx_task(&self) { unsafe fn drop_tx_task(&self) {
self.tx_task.with_mut(|ptr| ManuallyDrop::drop(&mut *ptr)) self.tx_task.with_mut(|ptr| {
let ptr: *mut Waker = (&mut *ptr).as_mut_ptr();
ptr.drop_in_place();
});
} }
unsafe fn set_rx_task(&self, cx: &mut Context<'_>) { unsafe fn set_rx_task(&self, cx: &mut Context<'_>) {
self.rx_task self.rx_task.with_mut(|ptr| {
.with_mut(|ptr| *ptr = ManuallyDrop::new(cx.waker().clone())); let ptr: *mut Waker = (&mut *ptr).as_mut_ptr();
ptr.write(cx.waker().clone());
});
} }
unsafe fn set_tx_task(&self, cx: &mut Context<'_>) { unsafe fn set_tx_task(&self, cx: &mut Context<'_>) {
self.tx_task self.tx_task.with_mut(|ptr| {
.with_mut(|ptr| *ptr = ManuallyDrop::new(cx.waker().clone())); let ptr: *mut Waker = (&mut *ptr).as_mut_ptr();
ptr.write(cx.waker().clone());
});
} }
} }
@@ -435,15 +465,15 @@ impl<T> Drop for Inner<T> {
let state = State(*self.state.get_mut()); let state = State(*self.state.get_mut());
if state.is_rx_task_set() { if state.is_rx_task_set() {
self.rx_task.with_mut(|ptr| unsafe { unsafe {
ManuallyDrop::drop(&mut *ptr); self.drop_rx_task();
}); }
} }
if state.is_tx_task_set() { if state.is_tx_task_set() {
self.tx_task.with_mut(|ptr| unsafe { unsafe {
ManuallyDrop::drop(&mut *ptr); self.drop_tx_task();
}); }
} }
} }
} }
+9 -5
View File
@@ -83,20 +83,24 @@ pub mod impl_linux {
pub mod impl_macos { pub mod impl_macos {
use crate::UnixStream; use crate::UnixStream;
use libc::getpeereid; use libc::getpeereid;
use std::io;
use std::mem::MaybeUninit;
use std::os::unix::io::AsRawFd; use std::os::unix::io::AsRawFd;
use std::{io, mem};
pub fn get_peer_cred(sock: &UnixStream) -> io::Result<super::UCred> { pub fn get_peer_cred(sock: &UnixStream) -> io::Result<super::UCred> {
unsafe { unsafe {
let raw_fd = sock.as_raw_fd(); let raw_fd = sock.as_raw_fd();
#[allow(deprecated)] let mut uid = MaybeUninit::uninit();
let mut cred: super::UCred = mem::uninitialized(); let mut gid = MaybeUninit::uninit();
let ret = getpeereid(raw_fd, &mut cred.uid, &mut cred.gid); let ret = getpeereid(raw_fd, uid.as_mut_ptr(), gid.as_mut_ptr());
if ret == 0 { if ret == 0 {
Ok(cred) Ok(super::UCred {
uid: uid.assume_init(),
gid: gid.assume_init(),
})
} else { } else {
Err(io::Error::last_os_error()) Err(io::Error::last_os_error())
} }