From 0ae585eb9e80378e48db43b77076d6ce1c9820c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Kub=C3=ADk?= Date: Sat, 5 Aug 2023 17:03:02 +0200 Subject: [PATCH 1/3] io: delegate WriteHalf poll_write_vectored to inner struct Fixes: #5913 --- tokio/src/io/split.rs | 9 +++++++++ tokio/tests/io_split.rs | 39 ++++++++++++++++++++++++++++++++++++++- 2 files changed, 47 insertions(+), 1 deletion(-) diff --git a/tokio/src/io/split.rs b/tokio/src/io/split.rs index f067b65a826..4ca3d97699c 100644 --- a/tokio/src/io/split.rs +++ b/tokio/src/io/split.rs @@ -131,6 +131,15 @@ impl AsyncWrite for WriteHalf { let mut inner = ready!(self.inner.poll_lock(cx)); inner.stream_pin().poll_shutdown(cx) } + + fn poll_write_vectored( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + bufs: &[io::IoSlice<'_>], + ) -> Poll> { + let mut inner = ready!(self.inner.poll_lock(cx)); + inner.stream_pin().poll_write_vectored(cx, bufs) + } } impl Inner { diff --git a/tokio/tests/io_split.rs b/tokio/tests/io_split.rs index 77b77a3a04c..2c90cb942ca 100644 --- a/tokio/tests/io_split.rs +++ b/tokio/tests/io_split.rs @@ -1,7 +1,9 @@ #![warn(rust_2018_idioms)] #![cfg(all(feature = "full", not(target_os = "wasi")))] // Wasi does not support panic recovery -use tokio::io::{split, AsyncRead, AsyncWrite, ReadBuf, ReadHalf, WriteHalf}; +use tokio::io::{ + split, AsyncRead, AsyncReadExt, AsyncWrite, AsyncWriteExt, ReadBuf, ReadHalf, WriteHalf, +}; use std::io; use std::pin::Pin; @@ -36,6 +38,18 @@ impl AsyncWrite for RW { fn poll_shutdown(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll> { Poll::Ready(Ok(())) } + + fn poll_write_vectored( + self: Pin<&mut Self>, + _cx: &mut Context<'_>, + _bufs: &[io::IoSlice<'_>], + ) -> Poll> { + Poll::Ready(Ok(2)) + } + + fn is_write_vectored(&self) -> bool { + true + } } #[test] @@ -77,3 +91,26 @@ fn unsplit_err2() { let (r, _) = split(RW); r.unsplit(w); } + +#[test] +fn method_delegation() { + let (mut r, mut w) = split(RW); + let mut buf = [0; 1]; + + tokio_test::block_on(async move { + assert_eq!(1, r.read(&mut buf).await.unwrap()); + assert_eq!(b'z', buf[0]); + + assert_eq!(1, w.write(&[b'x']).await.unwrap()); + assert_eq!( + 2, + w.write_vectored(&[io::IoSlice::new(&[b'x'])]) + .await + .unwrap() + ); + // assert!(w.is_write_vectored()); + + assert!(w.flush().await.is_ok()); + assert!(w.shutdown().await.is_ok()); + }); +} From 3cbd930eb53e0ff39ee78e884f0a3d0ea6e88a9a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Kub=C3=ADk?= Date: Sun, 6 Aug 2023 18:23:13 +0200 Subject: [PATCH 2/3] io: save is_write_vectored in WriteHalf --- tokio/src/io/split.rs | 9 ++++++++- tokio/tests/io_split.rs | 2 +- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/tokio/src/io/split.rs b/tokio/src/io/split.rs index 4ca3d97699c..34c216a05f4 100644 --- a/tokio/src/io/split.rs +++ b/tokio/src/io/split.rs @@ -24,6 +24,7 @@ cfg_io_util! { /// The writable half of a value returned from [`split`](split()). pub struct WriteHalf { inner: Arc>, + is_write_vectored: bool, } /// Splits a single value implementing `AsyncRead + AsyncWrite` into separate @@ -35,6 +36,8 @@ cfg_io_util! { where T: AsyncRead + AsyncWrite, { + let is_write_vectored = stream.is_write_vectored(); + let inner = Arc::new(Inner { locked: AtomicBool::new(false), stream: UnsafeCell::new(stream), @@ -44,7 +47,7 @@ cfg_io_util! { inner: inner.clone(), }; - let wr = WriteHalf { inner }; + let wr = WriteHalf { inner, is_write_vectored }; (rd, wr) } @@ -140,6 +143,10 @@ impl AsyncWrite for WriteHalf { let mut inner = ready!(self.inner.poll_lock(cx)); inner.stream_pin().poll_write_vectored(cx, bufs) } + + fn is_write_vectored(&self) -> bool { + self.is_write_vectored + } } impl Inner { diff --git a/tokio/tests/io_split.rs b/tokio/tests/io_split.rs index 2c90cb942ca..9f17c9eb14e 100644 --- a/tokio/tests/io_split.rs +++ b/tokio/tests/io_split.rs @@ -108,7 +108,7 @@ fn method_delegation() { .await .unwrap() ); - // assert!(w.is_write_vectored()); + assert!(w.is_write_vectored()); assert!(w.flush().await.is_ok()); assert!(w.shutdown().await.is_ok()); From e5ed37ea1d07440baf1b131c7d78767c86cdf762 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Kub=C3=ADk?= Date: Wed, 9 Aug 2023 22:28:09 +0200 Subject: [PATCH 3/3] io: move is_write_vectored to inner --- tokio/src/io/split.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/tokio/src/io/split.rs b/tokio/src/io/split.rs index 34c216a05f4..63f0960e4f3 100644 --- a/tokio/src/io/split.rs +++ b/tokio/src/io/split.rs @@ -24,7 +24,6 @@ cfg_io_util! { /// The writable half of a value returned from [`split`](split()). pub struct WriteHalf { inner: Arc>, - is_write_vectored: bool, } /// Splits a single value implementing `AsyncRead + AsyncWrite` into separate @@ -41,13 +40,14 @@ cfg_io_util! { let inner = Arc::new(Inner { locked: AtomicBool::new(false), stream: UnsafeCell::new(stream), + is_write_vectored, }); let rd = ReadHalf { inner: inner.clone(), }; - let wr = WriteHalf { inner, is_write_vectored }; + let wr = WriteHalf { inner }; (rd, wr) } @@ -56,6 +56,7 @@ cfg_io_util! { struct Inner { locked: AtomicBool, stream: UnsafeCell, + is_write_vectored: bool, } struct Guard<'a, T> { @@ -145,7 +146,7 @@ impl AsyncWrite for WriteHalf { } fn is_write_vectored(&self) -> bool { - self.is_write_vectored + self.inner.is_write_vectored } }