Improve poll_read_ready implementation (#193)

This patch updates `poll_read_ready` to take a `mask` argument, enabling
the caller to specify the desired readiness. `need_read` is renamed to
`clear_read_ready` and also takes a mask.

This enables a caller to listen for HUP events without requiring reading
from the I/O resource.
This commit is contained in:
Carl Lerche
2018-03-07 16:24:51 -08:00
committed by GitHub
parent 5555cbc85e
commit 25dd54d263
8 changed files with 262 additions and 265 deletions
+2 -2
View File
@@ -93,12 +93,12 @@ impl TcpListener {
///
/// This function will panic if called from outside of a task context.
pub fn poll_accept_std(&mut self) -> Poll<(net::TcpStream, SocketAddr), io::Error> {
try_ready!(self.io.poll_read_ready());
try_ready!(self.io.poll_read_ready(mio::Ready::readable()));
match self.io.get_ref().accept_std() {
Ok(pair) => Ok(pair.into()),
Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => {
self.io.need_read()?;
self.io.clear_read_ready(mio::Ready::readable())?;
Ok(Async::NotReady)
}
Err(e) => Err(e),
+49 -5
View File
@@ -114,6 +114,50 @@ impl TcpStream {
ConnectFuture { inner: inner }
}
/// Check the TCP stream's read readiness state.
///
/// The mask argument allows specifying what readiness to notify on. This
/// can be any value, including platform specific readiness, **except**
/// `writable`. HUP is always implicitly included on platforms that support
/// it.
///
/// If the resource is not ready for a read then `Async::NotReady` is
/// returned and the current task is notified once a new event is received.
///
/// The stream will remain in a read-ready state until calls to `poll_read`
/// return `NotReady`.
///
/// # Panics
///
/// This function panics if:
///
/// * `ready` includes writable.
/// * called from outside of a task context.
pub fn poll_read_ready(&self, mask: mio::Ready) -> Poll<mio::Ready, io::Error> {
self.io.poll_read_ready(mask)
}
/// Check the TCP stream's write readiness state.
///
/// This always checks for writable readiness and also checks for HUP
/// readiness on platforms that support it.
///
/// If the resource is not ready for a write then `Async::NotReady` is
/// returned and the current task is notified once a new event is received.
///
/// The I/O resource will remain in a write-ready state until calls to
/// `poll_write` return `NotReady`.
///
/// # Panics
///
/// This function panics if:
///
/// * `ready` contains bits besides `writable` and `hup`.
/// * called from outside of a task context.
pub fn poll_write_ready(&self) -> Poll<mio::Ready, io::Error> {
self.io.poll_write_ready()
}
/// Returns the local address that this stream is bound to.
pub fn local_addr(&self) -> io::Result<SocketAddr> {
self.io.get_ref().local_addr()
@@ -152,12 +196,12 @@ impl TcpStream {
///
/// This function will panic if called from outside of a task context.
pub fn poll_peek(&mut self, buf: &mut [u8]) -> Poll<usize, io::Error> {
try_ready!(self.io.poll_read_ready());
try_ready!(self.io.poll_read_ready(mio::Ready::readable()));
match self.io.get_ref().peek(buf) {
Ok(ret) => Ok(ret.into()),
Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => {
self.io.need_read()?;
self.io.clear_read_ready(mio::Ready::readable())?;
Ok(Async::NotReady)
}
Err(e) => Err(e),
@@ -357,7 +401,7 @@ impl<'a> AsyncRead for &'a TcpStream {
}
fn read_buf<B: BufMut>(&mut self, buf: &mut B) -> Poll<usize, io::Error> {
if let Async::NotReady = self.io.poll_read_ready()? {
if let Async::NotReady = self.io.poll_read_ready(mio::Ready::readable())? {
return Ok(Async::NotReady)
}
@@ -397,7 +441,7 @@ impl<'a> AsyncRead for &'a TcpStream {
Ok(Async::Ready(n))
}
Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => {
self.io.need_read()?;
self.io.clear_read_ready(mio::Ready::readable())?;
Ok(Async::NotReady)
}
Err(e) => Err(e),
@@ -431,7 +475,7 @@ impl<'a> AsyncWrite for &'a TcpStream {
Ok(Async::Ready(n))
}
Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => {
self.io.need_write()?;
self.io.clear_write_ready()?;
Ok(Async::NotReady)
}
Err(e) => Err(e),
+6 -6
View File
@@ -88,7 +88,7 @@ impl UdpSocket {
match self.io.get_ref().send(buf) {
Ok(n) => Ok(n.into()),
Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => {
self.io.need_write()?;
self.io.clear_write_ready()?;
Ok(Async::NotReady)
}
Err(e) => Err(e),
@@ -128,12 +128,12 @@ impl UdpSocket {
///
/// This function will panic if called from outside of a task context.
pub fn poll_recv(&mut self, buf: &mut [u8]) -> Poll<usize, io::Error> {
try_ready!(self.io.poll_read_ready());
try_ready!(self.io.poll_read_ready(mio::Ready::readable()));
match self.io.get_ref().recv(buf) {
Ok(n) => Ok(n.into()),
Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => {
self.io.need_read()?;
self.io.clear_read_ready(mio::Ready::readable())?;
Ok(Async::NotReady)
}
Err(e) => Err(e),
@@ -172,7 +172,7 @@ impl UdpSocket {
match self.io.get_ref().send_to(buf, target) {
Ok(n) => Ok(n.into()),
Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => {
self.io.need_write()?;
self.io.clear_write_ready()?;
Ok(Async::NotReady)
}
Err(e) => Err(e),
@@ -216,12 +216,12 @@ impl UdpSocket {
/// This function will panic if called outside the context of a future's
/// task.
pub fn poll_recv_from(&mut self, buf: &mut [u8]) -> Poll<(usize, SocketAddr), io::Error> {
try_ready!(self.io.poll_read_ready());
try_ready!(self.io.poll_read_ready(mio::Ready::readable()));
match self.io.get_ref().recv_from(buf) {
Ok(n) => Ok(n.into()),
Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => {
self.io.need_read()?;
self.io.clear_read_ready(mio::Ready::readable())?;
Ok(Async::NotReady)
}
Err(e) => Err(e),