udp: remove poll_* fns in favor of async fns (#1393)

This removes the need for manual futures.
This commit is contained in:
Carl Lerche
2019-08-05 14:18:18 -07:00
committed by GitHub
parent 6d8cc4e475
commit 62733a6594
9 changed files with 28 additions and 278 deletions
+2 -1
View File
@@ -28,7 +28,8 @@ tokio-reactor = { version = "0.2.0", path = "../tokio-reactor" }
# bytes = "0.4"
mio = "0.6.14"
log = "0.4"
futures-core-preview = "0.3.0-alpha.17"
futures-core-preview = "= 0.3.0-alpha.17"
futures-util-preview = "= 0.3.0-alpha.17"
[dev-dependencies]
env_logger = { version = "0.5", default-features = false }
+1 -8
View File
@@ -2,6 +2,7 @@
#![deny(missing_docs, missing_debug_implementations, rust_2018_idioms)]
#![cfg_attr(test, deny(warnings))]
#![doc(test(no_crate_inject, attr(deny(rust_2018_idioms))))]
#![feature(async_await)]
//! UDP bindings for `tokio`.
//!
@@ -13,17 +14,9 @@
//! [`Recv`], [`Send`], [`RecvFrom`] and [`SendTo`] structs respectively.
// mod frame;
mod recv;
mod recv_from;
mod send;
mod send_to;
mod socket;
pub mod split;
// pub use self::frame::UdpFramed;
pub use self::recv::Recv;
pub use self::recv_from::RecvFrom;
pub use self::send::Send;
pub use self::send_to::SendTo;
pub use self::socket::UdpSocket;
-30
View File
@@ -1,30 +0,0 @@
use super::UdpSocket;
use std::future::Future;
use std::io;
use std::pin::Pin;
use std::task::{Context, Poll};
/// A future that receives a datagram from the connected address.
///
/// This `struct` is created by [`recv`](super::UdpSocket::recv).
#[must_use = "futures do nothing unless you `.await` or poll them"]
#[derive(Debug)]
pub struct Recv<'a, 'b> {
socket: &'a UdpSocket,
buf: &'b mut [u8],
}
impl<'a, 'b> Recv<'a, 'b> {
pub(super) fn new(socket: &'a UdpSocket, buf: &'b mut [u8]) -> Self {
Self { socket, buf }
}
}
impl<'a, 'b> Future for Recv<'a, 'b> {
type Output = io::Result<usize>;
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
let Recv { socket, buf } = self.get_mut();
socket.poll_recv_priv(cx, buf)
}
}
-31
View File
@@ -1,31 +0,0 @@
use super::UdpSocket;
use std::future::Future;
use std::io;
use std::net::SocketAddr;
use std::pin::Pin;
use std::task::{Context, Poll};
/// A future that receives a datagram.
///
/// This `struct` is created by [`recv_from`](super::UdpSocket::recv_from).
#[must_use = "futures do nothing unless you `.await` or poll them"]
#[derive(Debug)]
pub struct RecvFrom<'a, 'b> {
socket: &'a UdpSocket,
buf: &'b mut [u8],
}
impl<'a, 'b> RecvFrom<'a, 'b> {
pub(super) fn new(socket: &'a UdpSocket, buf: &'b mut [u8]) -> Self {
Self { socket, buf }
}
}
impl<'a, 'b> Future for RecvFrom<'a, 'b> {
type Output = io::Result<(usize, SocketAddr)>;
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
let RecvFrom { socket, buf } = self.get_mut();
socket.poll_recv_from_priv(cx, buf)
}
}
-30
View File
@@ -1,30 +0,0 @@
use super::UdpSocket;
use std::future::Future;
use std::io;
use std::pin::Pin;
use std::task::{Context, Poll};
/// A future that sends a datagram to the connected address.
///
/// This `struct` is created by [`send`](super::UdpSocket::send).
#[must_use = "futures do nothing unless you `.await` or poll them"]
#[derive(Debug)]
pub struct Send<'a, 'b> {
socket: &'a UdpSocket,
buf: &'b [u8],
}
impl<'a, 'b> Send<'a, 'b> {
pub(super) fn new(socket: &'a UdpSocket, buf: &'b [u8]) -> Self {
Self { socket, buf }
}
}
impl<'a, 'b> Future for Send<'a, 'b> {
type Output = io::Result<usize>;
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
let Send { socket, buf } = self.get_mut();
socket.poll_send_priv(cx, buf)
}
}
-40
View File
@@ -1,40 +0,0 @@
use super::UdpSocket;
use std::future::Future;
use std::io;
use std::net::SocketAddr;
use std::pin::Pin;
use std::task::{Context, Poll};
/// A future that sends a datagram to a given address.
///
/// This `struct` is created by [`send_to`](super::UdpSocket::send_to).
#[must_use = "futures do nothing unless you `.await` or poll them"]
#[derive(Debug)]
pub struct SendTo<'a, 'b> {
socket: &'a UdpSocket,
buf: &'b [u8],
target: &'b SocketAddr,
}
impl<'a, 'b> SendTo<'a, 'b> {
pub(super) fn new(socket: &'a UdpSocket, buf: &'b [u8], target: &'b SocketAddr) -> Self {
Self {
socket,
buf,
target,
}
}
}
impl<'a, 'b> Future for SendTo<'a, 'b> {
type Output = io::Result<usize>;
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
let SendTo {
socket,
buf,
target,
} = self.get_mut();
socket.poll_send_to_priv(cx, buf, target)
}
}
+12 -128
View File
@@ -1,14 +1,15 @@
use super::split::{split, UdpSocketRecvHalf, UdpSocketSendHalf};
use super::{Recv, RecvFrom, Send, SendTo};
use tokio_reactor::{Handle, PollEvented};
use futures_core::ready;
use futures_util::future::poll_fn;
use mio;
use std::convert::TryFrom;
use std::fmt;
use std::io;
use std::net::{self, Ipv4Addr, Ipv6Addr, SocketAddr};
use std::pin::Pin;
use std::task::{Context, Poll};
use tokio_reactor::{Handle, PollEvented};
/// An I/O object representing a UDP socket.
pub struct UdpSocket {
@@ -73,30 +74,8 @@ impl UdpSocket {
/// will resolve to an error if the socket is not connected.
///
/// [`connect`]: #method.connect
pub fn send<'a, 'b>(&'a mut self, buf: &'b [u8]) -> Send<'a, 'b> {
Send::new(self, buf)
}
/// Sends data on the socket to the remote address to which it is connected.
///
/// The [`connect`] method will connect this socket to a remote address. This
/// method will fail if the socket is not connected.
///
/// [`connect`]: #method.connect
///
/// # Return
///
/// On success, returns `Poll::Ready(Ok(num_bytes_written))`.
///
/// If the socket is not ready for writing, the method returns
/// `Poll::Pending` and arranges for the current task to receive a
/// notification when the socket becomes writable.
pub fn poll_send(
self: Pin<&mut Self>,
cx: &mut Context<'_>,
buf: &[u8],
) -> Poll<io::Result<usize>> {
self.poll_send_priv(cx, buf)
pub async fn send(&mut self, buf: &[u8]) -> io::Result<usize> {
poll_fn(|cx| self.poll_send_priv(cx, buf)).await
}
// Poll IO functions that takes `&self` are provided for the split API.
@@ -137,35 +116,8 @@ impl UdpSocket {
/// will fail if the socket is not connected.
///
/// [`connect`]: #method.connect
pub fn recv<'a, 'b>(&'a mut self, buf: &'b mut [u8]) -> Recv<'a, 'b> {
Recv::new(self, buf)
}
/// Receives a single datagram message on the socket from the remote address to
/// which it is connected. On success, returns the number of bytes read.
///
/// The function must be called with valid byte array `buf` of sufficient size to
/// hold the message bytes. If a message is too long to fit in the supplied buffer,
/// excess bytes may be discarded.
///
/// The [`connect`] method will connect this socket to a remote address. This
/// method will fail if the socket is not connected.
///
/// [`connect`]: #method.connect
///
/// # Return
///
/// On success, returns `Poll::Ready(Ok(num_bytes_read))`.
///
/// If no data is available for reading, the method returns
/// `Poll::Pending` and arranges for the current task to receive a
/// notification when the socket becomes receivable or is closed.
pub fn poll_recv(
self: Pin<&mut Self>,
cx: &mut Context<'_>,
buf: &mut [u8],
) -> Poll<io::Result<usize>> {
self.poll_recv_priv(cx, buf)
pub async fn recv(&mut self, buf: &mut [u8]) -> io::Result<usize> {
poll_fn(|cx| self.poll_recv_priv(cx, buf)).await
}
pub(crate) fn poll_recv_priv(
@@ -189,30 +141,8 @@ impl UdpSocket {
///
/// The future will resolve to an error if the IP version of the socket does
/// not match that of `target`.
pub fn send_to<'a, 'b>(&'a mut self, buf: &'b [u8], target: &'b SocketAddr) -> SendTo<'a, 'b> {
SendTo::new(self, buf, target)
}
/// Sends data on the socket to the given address. On success, returns the
/// number of bytes written.
///
/// This will return an error when the IP version of the local socket
/// does not match that of `target`.
///
/// # Return
///
/// On success, returns `Poll::Ready(Ok(num_bytes_written))`.
///
/// If the socket is not ready for writing, the method returns
/// `Poll::Pending` and arranges for the current task to receive a
/// notification when the socket becomes writable.
pub fn poll_send_to(
self: Pin<&mut Self>,
cx: &mut Context<'_>,
buf: &[u8],
target: &SocketAddr,
) -> Poll<io::Result<usize>> {
self.poll_send_to_priv(cx, buf, target)
pub async fn send_to(&mut self, buf: &[u8], target: &SocketAddr) -> io::Result<usize> {
poll_fn(|cx| self.poll_send_to_priv(cx, buf, target)).await
}
pub(crate) fn poll_send_to_priv(
@@ -238,18 +168,8 @@ impl UdpSocket {
/// The function must be called with valid byte array `buf` of sufficient size
/// to hold the message bytes. If a message is too long to fit in the supplied
/// buffer, excess bytes may be discarded.
pub fn recv_from<'a, 'b>(&'a mut self, buf: &'b mut [u8]) -> RecvFrom<'a, 'b> {
RecvFrom::new(self, buf)
}
/// Receives data from the socket. On success, returns the number of bytes
/// read and the address from whence the data came.
pub fn poll_recv_from(
self: Pin<&mut Self>,
cx: &mut Context<'_>,
buf: &mut [u8],
) -> Poll<Result<(usize, SocketAddr), io::Error>> {
self.poll_recv_from_priv(cx, buf)
pub async fn recv_from(&mut self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
poll_fn(|cx| self.poll_recv_from_priv(cx, buf)).await
}
pub(crate) fn poll_recv_from_priv(
@@ -268,42 +188,6 @@ impl UdpSocket {
}
}
/// Check the UDP socket'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`.
///
/// If the socket is not ready for receiving then `Poll::Pending` is
/// returned and the current task is notified once a new event is received.
///
/// The socket will remain in a read-ready state until calls to `poll_recv`
/// return `Poll::Pending`.
///
/// # Panics
///
/// This function panics if:
///
/// * `ready` includes writable.
pub fn poll_read_ready(
&self,
cx: &mut Context<'_>,
mask: mio::Ready,
) -> Poll<Result<mio::Ready, io::Error>> {
self.io.poll_read_ready(cx, mask)
}
/// Check the UDP socket's write readiness state.
///
/// If the socket is not ready for sending then `Poll::Pending` 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_send` return `Poll::Pending`.
pub fn poll_write_ready(&self, cx: &mut Context<'_>) -> Poll<Result<mio::Ready, io::Error>> {
self.io.poll_write_ready(cx)
}
/// Gets the value of the `SO_BROADCAST` option for this socket.
///
/// For more information about this option, see [`set_broadcast`].
+12 -9
View File
@@ -12,9 +12,12 @@
//! The halves can be reunited to the original socket with their `reunite`
//! methods.
use super::{Recv, RecvFrom, Send, SendTo, UdpSocket};
use super::UdpSocket;
use futures_util::future::poll_fn;
use std::error::Error;
use std::fmt;
use std::io;
use std::net::SocketAddr;
use std::sync::Arc;
@@ -82,8 +85,8 @@ impl UdpSocketRecvHalf {
/// The function must be called with valid byte array `buf` of sufficient size
/// to hold the message bytes. If a message is too long to fit in the supplied
/// buffer, excess bytes may be discarded.
pub fn recv_from<'a, 'b>(&'a mut self, buf: &'b mut [u8]) -> RecvFrom<'a, 'b> {
RecvFrom::new(&self.0, buf)
pub async fn recv_from(&mut self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
poll_fn(|cx| self.0.poll_recv_from_priv(cx, buf)).await
}
/// Returns a future that receives a single datagram message on the socket from
@@ -98,8 +101,8 @@ impl UdpSocketRecvHalf {
/// will fail if the socket is not connected.
///
/// [`connect`]: super::UdpSocket::connect
pub fn recv<'a, 'b>(&'a mut self, buf: &'b mut [u8]) -> Recv<'a, 'b> {
Recv::new(&self.0, buf)
pub async fn recv<'a, 'b>(&'a mut self, buf: &'b mut [u8]) -> io::Result<usize> {
poll_fn(|cx| self.0.poll_recv_priv(cx, buf)).await
}
}
@@ -116,8 +119,8 @@ impl UdpSocketSendHalf {
///
/// The future will resolve to an error if the IP version of the socket does
/// not match that of `target`.
pub fn send_to<'a, 'b>(&'a mut self, buf: &'b [u8], target: &'b SocketAddr) -> SendTo<'a, 'b> {
SendTo::new(&self.0, buf, target)
pub async fn send_to(&mut self, buf: &[u8], target: &SocketAddr) -> io::Result<usize> {
poll_fn(|cx| self.0.poll_send_to_priv(cx, buf, target)).await
}
/// Returns a future that sends data on the socket to the remote address to which it is connected.
@@ -127,8 +130,8 @@ impl UdpSocketSendHalf {
/// will resolve to an error if the socket is not connected.
///
/// [`connect`]: super::UdpSocket::connect
pub fn send<'a, 'b>(&'a mut self, buf: &'b [u8]) -> Send<'a, 'b> {
Send::new(&self.0, buf)
pub async fn send(&mut self, buf: &[u8]) -> io::Result<usize> {
poll_fn(|cx| self.0.poll_send_priv(cx, buf)).await
}
}
+1 -1
View File
@@ -58,7 +58,7 @@ pub mod udp {
//! [`Send`]: struct.Send.html
//! [`RecvFrom`]: struct.RecvFrom.html
//! [`SendTo`]: struct.SendTo.html
pub use tokio_udp::{split, Recv, RecvFrom, Send, SendTo, UdpSocket};
pub use tokio_udp::{split, UdpSocket};
}
#[cfg(feature = "udp")]
pub use self::udp::UdpSocket;