summaryrefslogtreecommitdiffstats
path: root/tokio/src/io/async_write.rs
diff options
context:
space:
mode:
Diffstat (limited to 'tokio/src/io/async_write.rs')
-rw-r--r--tokio/src/io/async_write.rs135
1 files changed, 134 insertions, 1 deletions
diff --git a/tokio/src/io/async_write.rs b/tokio/src/io/async_write.rs
index 66ba4bf3..569fb9c9 100644
--- a/tokio/src/io/async_write.rs
+++ b/tokio/src/io/async_write.rs
@@ -1,4 +1,4 @@
-use std::io;
+use std::io::{self, IoSlice};
use std::ops::DerefMut;
use std::pin::Pin;
use std::task::{Context, Poll};
@@ -127,6 +127,55 @@ pub trait AsyncWrite {
/// This function will panic if not called within the context of a future's
/// task.
fn poll_shutdown(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), io::Error>>;
+
+ /// Like [`poll_write`], except that it writes from a slice of buffers.
+ ///
+ /// Data is copied from each buffer in order, with the final buffer
+ /// read from possibly being only partially consumed. This method must
+ /// behave as a call to [`write`] with the buffers concatenated would.
+ ///
+ /// The default implementation calls [`poll_write`] with either the first nonempty
+ /// buffer provided, or an empty one if none exists.
+ ///
+ /// On success, returns `Poll::Ready(Ok(num_bytes_written))`.
+ ///
+ /// If the object is not ready for writing, the method returns
+ /// `Poll::Pending` and arranges for the current task (via
+ /// `cx.waker()`) to receive a notification when the object becomes
+ /// writable or is closed.
+ ///
+ /// # Note
+ ///
+ /// This should be implemented as a single "atomic" write action. If any
+ /// data has been partially written, it is wrong to return an error or
+ /// pending.
+ ///
+ /// [`poll_write`]: AsyncWrite::poll_write
+ fn poll_write_vectored(
+ self: Pin<&mut Self>,
+ cx: &mut Context<'_>,
+ bufs: &[IoSlice<'_>],
+ ) -> Poll<Result<usize, io::Error>> {
+ let buf = bufs
+ .iter()
+ .find(|b| !b.is_empty())
+ .map_or(&[][..], |b| &**b);
+ self.poll_write(cx, buf)
+ }
+
+ /// Determines if this writer has an efficient [`poll_write_vectored`]
+ /// implementation.
+ ///
+ /// If a writer does not override the default [`poll_write_vectored`]
+ /// implementation, code using it may want to avoid the method all together
+ /// and coalesce writes into a single buffer for higher performance.
+ ///
+ /// The default implementation returns `false`.
+ ///
+ /// [`poll_write_vectored`]: AsyncWrite::poll_write_vectored
+ fn is_write_vectored(&self) -> bool {
+ false
+ }
}
macro_rules! deref_async_write {
@@ -139,6 +188,18 @@ macro_rules! deref_async_write {
Pin::new(&mut **self).poll_write(cx, buf)
}
+ fn poll_write_vectored(
+ mut self: Pin<&mut Self>,
+ cx: &mut Context<'_>,
+ bufs: &[IoSlice<'_>],
+ ) -> Poll<io::Result<usize>> {
+ Pin::new(&mut **self).poll_write_vectored(cx, bufs)
+ }
+
+ fn is_write_vectored(&self) -> bool {
+ (**self).is_write_vectored()
+ }
+
fn poll_flush(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
Pin::new(&mut **self).poll_flush(cx)
}
@@ -170,6 +231,18 @@ where
self.get_mut().as_mut().poll_write(cx, buf)
}
+ fn poll_write_vectored(
+ self: Pin<&mut Self>,
+ cx: &mut Context<'_>,
+ bufs: &[IoSlice<'_>],
+ ) -> Poll<io::Result<usize>> {
+ self.get_mut().as_mut().poll_write_vectored(cx, bufs)
+ }
+
+ fn is_write_vectored(&self) -> bool {
+ (**self).is_write_vectored()
+ }
+
fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
self.get_mut().as_mut().poll_flush(cx)
}
@@ -189,6 +262,18 @@ impl AsyncWrite for Vec<u8> {
Poll::Ready(Ok(buf.len()))
}
+ fn poll_write_vectored(
+ mut self: Pin<&mut Self>,
+ _: &mut Context<'_>,
+ bufs: &[IoSlice<'_>],
+ ) -> Poll<io::Result<usize>> {
+ Poll::Ready(io::Write::write_vectored(&mut *self, bufs))
+ }
+
+ fn is_write_vectored(&self) -> bool {
+ true
+ }
+
fn poll_flush(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<io::Result<()>> {
Poll::Ready(Ok(()))
}
@@ -207,6 +292,18 @@ impl AsyncWrite for io::Cursor<&mut [u8]> {
Poll::Ready(io::Write::write(&mut *self, buf))
}
+ fn poll_write_vectored(
+ mut self: Pin<&mut Self>,
+ _: &mut Context<'_>,
+ bufs: &[IoSlice<'_>],
+ ) -> Poll<io::Result<usize>> {
+ Poll::Ready(io::Write::write_vectored(&mut *self, bufs))
+ }
+
+ fn is_write_vectored(&self) -> bool {
+ true
+ }
+
fn poll_flush(mut self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll<io::Result<()>> {
Poll::Ready(io::Write::flush(&mut *self))
}
@@ -225,6 +322,18 @@ impl AsyncWrite for io::Cursor<&mut Vec<u8>> {
Poll::Ready(io::Write::write(&mut *self, buf))
}
+ fn poll_write_vectored(
+ mut self: Pin<&mut Self>,
+ _: &mut Context<'_>,
+ bufs: &[IoSlice<'_>],
+ ) -> Poll<io::Result<usize>> {
+ Poll::Ready(io::Write::write_vectored(&mut *self, bufs))
+ }
+
+ fn is_write_vectored(&self) -> bool {
+ true
+ }
+
fn poll_flush(mut self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll<io::Result<()>> {
Poll::Ready(io::Write::flush(&mut *self))
}
@@ -243,6 +352,18 @@ impl AsyncWrite for io::Cursor<Vec<u8>> {
Poll::Ready(io::Write::write(&mut *self, buf))
}
+ fn poll_write_vectored(
+ mut self: Pin<&mut Self>,
+ _: &mut Context<'_>,
+ bufs: &[IoSlice<'_>],
+ ) -> Poll<io::Result<usize>> {
+ Poll::Ready(io::Write::write_vectored(&mut *self, bufs))
+ }
+
+ fn is_write_vectored(&self) -> bool {
+ true
+ }
+
fn poll_flush(mut self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll<io::Result<()>> {
Poll::Ready(io::Write::flush(&mut *self))
}
@@ -261,6 +382,18 @@ impl AsyncWrite for io::Cursor<Box<[u8]>> {
Poll::Ready(io::Write::write(&mut *self, buf))
}
+ fn poll_write_vectored(
+ mut self: Pin<&mut Self>,
+ _: &mut Context<'_>,
+ bufs: &[IoSlice<'_>],
+ ) -> Poll<io::Result<usize>> {
+ Poll::Ready(io::Write::write_vectored(&mut *self, bufs))
+ }
+
+ fn is_write_vectored(&self) -> bool {
+ true
+ }
+
fn poll_flush(mut self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll<io::Result<()>> {
Poll::Ready(io::Write::flush(&mut *self))
}