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

Fix unnecessary zeroing for AsyncRead implementors #2525

Merged
merged 18 commits into from
May 21, 2020
6 changes: 6 additions & 0 deletions tokio/src/fs/file.rs
Original file line number Diff line number Diff line change
Expand Up @@ -537,6 +537,12 @@ impl File {
}

impl AsyncRead for File {
unsafe fn prepare_uninitialized_buffer(&self, _buf: &mut [std::mem::MaybeUninit<u8>]) -> bool {
// std::fs::File does not need zeroing
// https://github.com/rust-lang/rust/blob/09c817eeb29e764cfc12d0a8d94841e3ffe34023/src/libstd/fs.rs#L668
false
}

fn poll_read(
mut self: Pin<&mut Self>,
cx: &mut Context<'_>,
Expand Down
22 changes: 22 additions & 0 deletions tokio/src/io/async_read.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,28 @@ use std::ops::DerefMut;
use std::pin::Pin;
use std::task::{Context, Poll};

/// This utility function shoyld be used to override `AsyncRead::prepare_uninitialized_buffer`
/// for any AsyncRead impl which wraps an `std::io::Read` instance.
pub(crate) fn prepare_uninitialized_buffer_std_read<R: std::io::Read>(
buf: &mut [MaybeUninit<u8>],
) -> bool {
// TODO: when std::io::Initializer is stable, it should be used
// to override `prepare_uninitialized_buffer`
/*use std::io::Read;
if !T::initializer::should_initialize() {
return false;
}
*/
for x in buf {
// we could use safe method x.write(0) here, but it is unstable.
// Safety: as_mut_ptr() returns valid writeable pointer.
unsafe {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

*x = MaybeUninit::new(0);

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've updated both places.

x.as_mut_ptr().write(0);
}
}
true
}

/// Reads bytes from a source.
///
/// This trait is analogous to the [`std::io::Read`] trait, but integrates with
Expand Down
4 changes: 4 additions & 0 deletions tokio/src/io/blocking.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,10 @@ impl<T> AsyncRead for Blocking<T>
where
T: Read + Unpin + Send + 'static,
{
unsafe fn prepare_uninitialized_buffer(&self, buf: &mut [std::mem::MaybeUninit<u8>]) -> bool {
crate::io::prepare_uninitialized_buffer_std_read::<T>(buf)
}

fn poll_read(
mut self: Pin<&mut Self>,
cx: &mut Context<'_>,
Expand Down
1 change: 1 addition & 0 deletions tokio/src/io/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,7 @@ pub use self::async_buf_read::AsyncBufRead;

mod async_read;
pub use self::async_read::AsyncRead;
pub(crate) use self::async_read::prepare_uninitialized_buffer_std_read;

mod async_seek;
pub use self::async_seek::AsyncSeek;
Expand Down
4 changes: 4 additions & 0 deletions tokio/src/io/poll_evented.rs
Original file line number Diff line number Diff line change
Expand Up @@ -381,6 +381,10 @@ impl<E> AsyncRead for PollEvented<E>
where
E: Evented + Read + Unpin,
{
unsafe fn prepare_uninitialized_buffer(&self, buf: &mut [std::mem::MaybeUninit<u8>]) -> bool {
crate::io::prepare_uninitialized_buffer_std_read::<E>(buf)
}

fn poll_read(
mut self: Pin<&mut Self>,
cx: &mut Context<'_>,
Expand Down
5 changes: 5 additions & 0 deletions tokio/src/io/stdin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,11 @@ impl std::os::windows::io::AsRawHandle for Stdin {
}

impl AsyncRead for Stdin {
unsafe fn prepare_uninitialized_buffer(&self, _buf: &mut [std::mem::MaybeUninit<u8>]) -> bool {
// https://github.com/rust-lang/rust/blob/09c817eeb29e764cfc12d0a8d94841e3ffe34023/src/libstd/io/stdio.rs#L97
false
}

fn poll_read(
mut self: Pin<&mut Self>,
cx: &mut Context<'_>,
Expand Down
9 changes: 9 additions & 0 deletions tokio/src/io/util/chain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,15 @@ where
T: AsyncRead,
U: AsyncRead,
{
unsafe fn prepare_uninitialized_buffer(&self, buf: &mut [std::mem::MaybeUninit<u8>]) -> bool {
if self.first.prepare_uninitialized_buffer(buf) {
return true;
}
if self.second.prepare_uninitialized_buffer(buf) {
return true;
}
false
}
fn poll_read(
self: Pin<&mut Self>,
cx: &mut Context<'_>,
Expand Down
3 changes: 3 additions & 0 deletions tokio/src/io/util/empty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,9 @@ cfg_io_util! {
}

impl AsyncRead for Empty {
unsafe fn prepare_uninitialized_buffer(&self, _buf: &mut [std::mem::MaybeUninit<u8>]) -> bool {
false
}
#[inline]
fn poll_read(
self: Pin<&mut Self>,
Expand Down
3 changes: 3 additions & 0 deletions tokio/src/io/util/repeat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,9 @@ cfg_io_util! {
}

impl AsyncRead for Repeat {
unsafe fn prepare_uninitialized_buffer(&self, _buf: &mut [std::mem::MaybeUninit<u8>]) -> bool {
false
}
#[inline]
fn poll_read(
self: Pin<&mut Self>,
Expand Down
10 changes: 10 additions & 0 deletions tokio/src/process/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -872,6 +872,11 @@ impl AsyncWrite for ChildStdin {
}

impl AsyncRead for ChildStdout {
unsafe fn prepare_uninitialized_buffer(&self, _buf: &mut [std::mem::MaybeUninit<u8>]) -> bool {
// https://github.com/rust-lang/rust/blob/09c817eeb29e764cfc12d0a8d94841e3ffe34023/src/libstd/process.rs#L314
false
}

fn poll_read(
mut self: Pin<&mut Self>,
cx: &mut Context<'_>,
Expand All @@ -882,6 +887,11 @@ impl AsyncRead for ChildStdout {
}

impl AsyncRead for ChildStderr {
unsafe fn prepare_uninitialized_buffer(&self, _buf: &mut [std::mem::MaybeUninit<u8>]) -> bool {
// https://github.com/rust-lang/rust/blob/09c817eeb29e764cfc12d0a8d94841e3ffe34023/src/libstd/process.rs#L375
false
}

fn poll_read(
mut self: Pin<&mut Self>,
cx: &mut Context<'_>,
Expand Down