feat(lib): update to std::future::Future
BREAKING CHANGE: All usage of async traits (`Future`, `Stream`, `AsyncRead`, `AsyncWrite`, etc) are updated to newer versions.
This commit is contained in:
@@ -1,14 +1,19 @@
|
||||
use std::mem;
|
||||
|
||||
use futures::{Async, Future, Poll, Stream};
|
||||
use futures::future::Shared;
|
||||
use futures::sync::{mpsc, oneshot};
|
||||
use tokio_sync::{mpsc, watch};
|
||||
|
||||
use super::Never;
|
||||
use super::{Future, Never, Poll, Pin, task};
|
||||
|
||||
// Sentinel value signaling that the watch is still open
|
||||
enum Action {
|
||||
Open,
|
||||
// Closed isn't sent via the `Action` type, but rather once
|
||||
// the watch::Sender is dropped.
|
||||
}
|
||||
|
||||
pub fn channel() -> (Signal, Watch) {
|
||||
let (tx, rx) = oneshot::channel();
|
||||
let (drained_tx, drained_rx) = mpsc::channel(0);
|
||||
let (tx, rx) = watch::channel(Action::Open);
|
||||
let (drained_tx, drained_rx) = mpsc::channel(1);
|
||||
(
|
||||
Signal {
|
||||
drained_rx,
|
||||
@@ -16,14 +21,14 @@ pub fn channel() -> (Signal, Watch) {
|
||||
},
|
||||
Watch {
|
||||
drained_tx,
|
||||
rx: rx.shared(),
|
||||
rx,
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
pub struct Signal {
|
||||
drained_rx: mpsc::Receiver<Never>,
|
||||
tx: oneshot::Sender<()>,
|
||||
tx: watch::Sender<Action>,
|
||||
}
|
||||
|
||||
pub struct Draining {
|
||||
@@ -33,7 +38,7 @@ pub struct Draining {
|
||||
#[derive(Clone)]
|
||||
pub struct Watch {
|
||||
drained_tx: mpsc::Sender<Never>,
|
||||
rx: Shared<oneshot::Receiver<()>>,
|
||||
rx: watch::Receiver<Action>,
|
||||
}
|
||||
|
||||
#[allow(missing_debug_implementations)]
|
||||
@@ -50,7 +55,7 @@ enum State<F> {
|
||||
|
||||
impl Signal {
|
||||
pub fn drain(self) -> Draining {
|
||||
let _ = self.tx.send(());
|
||||
// Simply dropping `self.tx` will signal the watchers
|
||||
Draining {
|
||||
drained_rx: self.drained_rx,
|
||||
}
|
||||
@@ -58,13 +63,12 @@ impl Signal {
|
||||
}
|
||||
|
||||
impl Future for Draining {
|
||||
type Item = ();
|
||||
type Error = ();
|
||||
type Output = ();
|
||||
|
||||
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
|
||||
match try_ready!(self.drained_rx.poll()) {
|
||||
fn poll(mut self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll<Self::Output> {
|
||||
match ready!(self.drained_rx.poll_recv(cx)) {
|
||||
Some(never) => match never {},
|
||||
None => Ok(Async::Ready(())),
|
||||
None => Poll::Ready(()),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -73,7 +77,7 @@ impl Watch {
|
||||
pub fn watch<F, FN>(self, future: F, on_drain: FN) -> Watching<F, FN>
|
||||
where
|
||||
F: Future,
|
||||
FN: FnOnce(&mut F),
|
||||
FN: FnOnce(Pin<&mut F>),
|
||||
{
|
||||
Watching {
|
||||
future,
|
||||
@@ -86,28 +90,29 @@ impl Watch {
|
||||
impl<F, FN> Future for Watching<F, FN>
|
||||
where
|
||||
F: Future,
|
||||
FN: FnOnce(&mut F),
|
||||
FN: FnOnce(Pin<&mut F>),
|
||||
{
|
||||
type Item = F::Item;
|
||||
type Error = F::Error;
|
||||
type Output = F::Output;
|
||||
|
||||
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
|
||||
fn poll(mut self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll<Self::Output> {
|
||||
let me = unsafe { self.get_unchecked_mut() };
|
||||
loop {
|
||||
match mem::replace(&mut self.state, State::Draining) {
|
||||
match mem::replace(&mut me.state, State::Draining) {
|
||||
State::Watch(on_drain) => {
|
||||
match self.watch.rx.poll() {
|
||||
Ok(Async::Ready(_)) | Err(_) => {
|
||||
match me.watch.rx.poll_ref(cx) {
|
||||
Poll::Ready(None) => {
|
||||
// Drain has been triggered!
|
||||
on_drain(&mut self.future);
|
||||
on_drain(unsafe { Pin::new_unchecked(&mut me.future) });
|
||||
},
|
||||
Ok(Async::NotReady) => {
|
||||
self.state = State::Watch(on_drain);
|
||||
return self.future.poll();
|
||||
Poll::Ready(Some(_/*State::Open*/)) |
|
||||
Poll::Pending => {
|
||||
me.state = State::Watch(on_drain);
|
||||
return unsafe { Pin::new_unchecked(&mut me.future) }.poll(cx);
|
||||
},
|
||||
}
|
||||
},
|
||||
State::Draining => {
|
||||
return self.future.poll();
|
||||
return unsafe { Pin::new_unchecked(&mut me.future) }.poll(cx);
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
use std::fmt;
|
||||
use std::future::Future;
|
||||
use std::pin::Pin;
|
||||
use std::sync::Arc;
|
||||
|
||||
use futures::future::{Executor, Future};
|
||||
use tokio_executor::TypedExecutor;
|
||||
|
||||
use crate::body::Payload;
|
||||
use crate::proto::h2::server::H2Stream;
|
||||
@@ -9,11 +11,11 @@ use crate::server::conn::spawn_all::{NewSvcTask, Watcher};
|
||||
use crate::service::Service;
|
||||
|
||||
pub trait H2Exec<F, B: Payload>: Clone {
|
||||
fn execute_h2stream(&self, fut: H2Stream<F, B>) -> crate::Result<()>;
|
||||
fn execute_h2stream(&mut self, fut: H2Stream<F, B>) -> crate::Result<()>;
|
||||
}
|
||||
|
||||
pub trait NewSvcExec<I, N, S: Service, E, W: Watcher<I, S, E>>: Clone {
|
||||
fn execute_new_svc(&self, fut: NewSvcTask<I, N, S, E, W>) -> crate::Result<()>;
|
||||
fn execute_new_svc(&mut self, fut: NewSvcTask<I, N, S, E, W>) -> crate::Result<()>;
|
||||
}
|
||||
|
||||
// Either the user provides an executor for background tasks, or we use
|
||||
@@ -21,7 +23,7 @@ pub trait NewSvcExec<I, N, S: Service, E, W: Watcher<I, S, E>>: Clone {
|
||||
#[derive(Clone)]
|
||||
pub enum Exec {
|
||||
Default,
|
||||
Executor(Arc<dyn Executor<Box<dyn Future<Item=(), Error=()> + Send>> + Send + Sync>),
|
||||
Executor(Arc<dyn TypedExecutor<Pin<Box<dyn Future<Output=()> + Send>>> + Send + Sync>),
|
||||
}
|
||||
|
||||
// ===== impl Exec =====
|
||||
@@ -29,14 +31,13 @@ pub enum Exec {
|
||||
impl Exec {
|
||||
pub(crate) fn execute<F>(&self, fut: F) -> crate::Result<()>
|
||||
where
|
||||
F: Future<Item=(), Error=()> + Send + 'static,
|
||||
F: Future<Output=()> + Send + 'static,
|
||||
{
|
||||
match *self {
|
||||
Exec::Default => {
|
||||
#[cfg(feature = "runtime")]
|
||||
{
|
||||
use std::error::Error as StdError;
|
||||
use ::tokio_executor::Executor;
|
||||
|
||||
struct TokioSpawnError;
|
||||
|
||||
@@ -59,7 +60,7 @@ impl Exec {
|
||||
}
|
||||
|
||||
::tokio_executor::DefaultExecutor::current()
|
||||
.spawn(Box::new(fut))
|
||||
.spawn(Box::pin(fut))
|
||||
.map_err(|err| {
|
||||
warn!("executor error: {:?}", err);
|
||||
crate::Error::new_execute(TokioSpawnError)
|
||||
@@ -72,11 +73,14 @@ impl Exec {
|
||||
}
|
||||
},
|
||||
Exec::Executor(ref e) => {
|
||||
e.execute(Box::new(fut))
|
||||
unimplemented!("custom executor exec");
|
||||
/* XXX: needs mut
|
||||
e.spawn(Box::pin(fut))
|
||||
.map_err(|err| {
|
||||
warn!("executor error: {:?}", err.kind());
|
||||
warn!("executor error: {:?}", err);
|
||||
crate::Error::new_execute("custom executor failed")
|
||||
})
|
||||
*/
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -92,21 +96,21 @@ impl fmt::Debug for Exec {
|
||||
|
||||
impl<F, B> H2Exec<F, B> for Exec
|
||||
where
|
||||
H2Stream<F, B>: Future<Item=(), Error=()> + Send + 'static,
|
||||
H2Stream<F, B>: Future<Output = ()> + Send + 'static,
|
||||
B: Payload,
|
||||
{
|
||||
fn execute_h2stream(&self, fut: H2Stream<F, B>) -> crate::Result<()> {
|
||||
fn execute_h2stream(&mut self, fut: H2Stream<F, B>) -> crate::Result<()> {
|
||||
self.execute(fut)
|
||||
}
|
||||
}
|
||||
|
||||
impl<I, N, S, E, W> NewSvcExec<I, N, S, E, W> for Exec
|
||||
where
|
||||
NewSvcTask<I, N, S, E, W>: Future<Item=(), Error=()> + Send + 'static,
|
||||
NewSvcTask<I, N, S, E, W>: Future<Output=()> + Send + 'static,
|
||||
S: Service,
|
||||
W: Watcher<I, S, E>,
|
||||
{
|
||||
fn execute_new_svc(&self, fut: NewSvcTask<I, N, S, E, W>) -> crate::Result<()> {
|
||||
fn execute_new_svc(&mut self, fut: NewSvcTask<I, N, S, E, W>) -> crate::Result<()> {
|
||||
self.execute(fut)
|
||||
}
|
||||
}
|
||||
@@ -115,14 +119,14 @@ where
|
||||
|
||||
impl<E, F, B> H2Exec<F, B> for E
|
||||
where
|
||||
E: Executor<H2Stream<F, B>> + Clone,
|
||||
H2Stream<F, B>: Future<Item=(), Error=()>,
|
||||
E: TypedExecutor<H2Stream<F, B>> + Clone,
|
||||
H2Stream<F, B>: Future<Output=()>,
|
||||
B: Payload,
|
||||
{
|
||||
fn execute_h2stream(&self, fut: H2Stream<F, B>) -> crate::Result<()> {
|
||||
self.execute(fut)
|
||||
fn execute_h2stream(&mut self, fut: H2Stream<F, B>) -> crate::Result<()> {
|
||||
self.spawn(fut)
|
||||
.map_err(|err| {
|
||||
warn!("executor error: {:?}", err.kind());
|
||||
warn!("executor error: {:?}", err);
|
||||
crate::Error::new_execute("custom executor failed")
|
||||
})
|
||||
}
|
||||
@@ -130,15 +134,15 @@ where
|
||||
|
||||
impl<I, N, S, E, W> NewSvcExec<I, N, S, E, W> for E
|
||||
where
|
||||
E: Executor<NewSvcTask<I, N, S, E, W>> + Clone,
|
||||
NewSvcTask<I, N, S, E, W>: Future<Item=(), Error=()>,
|
||||
E: TypedExecutor<NewSvcTask<I, N, S, E, W>> + Clone,
|
||||
NewSvcTask<I, N, S, E, W>: Future<Output=()>,
|
||||
S: Service,
|
||||
W: Watcher<I, S, E>,
|
||||
{
|
||||
fn execute_new_svc(&self, fut: NewSvcTask<I, N, S, E, W>) -> crate::Result<()> {
|
||||
self.execute(fut)
|
||||
fn execute_new_svc(&mut self, fut: NewSvcTask<I, N, S, E, W>) -> crate::Result<()> {
|
||||
self.spawn(fut)
|
||||
.map_err(|err| {
|
||||
warn!("executor error: {:?}", err.kind());
|
||||
warn!("executor error: {:?}", err);
|
||||
crate::Error::new_execute("custom executor failed")
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
use std::cmp;
|
||||
use std::io::{self, Read, Write};
|
||||
use std::io::{self, Read};
|
||||
use std::marker::Unpin;
|
||||
|
||||
use bytes::{Buf, BufMut, Bytes, IntoBuf};
|
||||
use futures::{Async, Poll};
|
||||
use tokio_io::{AsyncRead, AsyncWrite};
|
||||
|
||||
use crate::common::{Pin, Poll, task};
|
||||
|
||||
/// Combine a buffer with an IO, rewinding reads to use the buffer.
|
||||
#[derive(Debug)]
|
||||
pub(crate) struct Rewind<T> {
|
||||
@@ -37,12 +38,16 @@ impl<T> Rewind<T> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Read for Rewind<T>
|
||||
impl<T> AsyncRead for Rewind<T>
|
||||
where
|
||||
T: Read,
|
||||
T: AsyncRead + Unpin,
|
||||
{
|
||||
#[inline]
|
||||
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
|
||||
unsafe fn prepare_uninitialized_buffer(&self, buf: &mut [u8]) -> bool {
|
||||
self.inner.prepare_uninitialized_buffer(buf)
|
||||
}
|
||||
|
||||
fn poll_read(mut self: Pin<&mut Self>, cx: &mut task::Context<'_>, buf: &mut [u8]) -> Poll<io::Result<usize>> {
|
||||
if let Some(pre_bs) = self.pre.take() {
|
||||
// If there are no remaining bytes, let the bytes get dropped.
|
||||
if pre_bs.len() > 0 {
|
||||
@@ -57,39 +62,17 @@ where
|
||||
self.pre = Some(new_pre);
|
||||
}
|
||||
|
||||
return Ok(read_cnt);
|
||||
return Poll::Ready(Ok(read_cnt));
|
||||
}
|
||||
}
|
||||
self.inner.read(buf)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Write for Rewind<T>
|
||||
where
|
||||
T: Write,
|
||||
{
|
||||
#[inline]
|
||||
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
||||
self.inner.write(buf)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn flush(&mut self) -> io::Result<()> {
|
||||
self.inner.flush()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> AsyncRead for Rewind<T>
|
||||
where
|
||||
T: AsyncRead,
|
||||
{
|
||||
#[inline]
|
||||
unsafe fn prepare_uninitialized_buffer(&self, buf: &mut [u8]) -> bool {
|
||||
self.inner.prepare_uninitialized_buffer(buf)
|
||||
Pin::new(&mut self.inner).poll_read(cx, buf)
|
||||
}
|
||||
|
||||
/*
|
||||
#[inline]
|
||||
fn read_buf<B: BufMut>(&mut self, buf: &mut B) -> Poll<usize, io::Error> {
|
||||
use std::cmp;
|
||||
|
||||
if let Some(bs) = self.pre.take() {
|
||||
let pre_len = bs.len();
|
||||
// If there are no remaining bytes, let the bytes get dropped.
|
||||
@@ -112,21 +95,31 @@ where
|
||||
}
|
||||
self.inner.read_buf(buf)
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
impl<T> AsyncWrite for Rewind<T>
|
||||
where
|
||||
T: AsyncWrite,
|
||||
T: AsyncWrite + Unpin,
|
||||
{
|
||||
#[inline]
|
||||
fn shutdown(&mut self) -> Poll<(), io::Error> {
|
||||
AsyncWrite::shutdown(&mut self.inner)
|
||||
fn poll_write(mut self: Pin<&mut Self>, cx: &mut task::Context<'_>, buf: &[u8]) -> Poll<io::Result<usize>> {
|
||||
Pin::new(&mut self.inner).poll_write(cx, buf)
|
||||
}
|
||||
|
||||
fn poll_flush(mut self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll<io::Result<()>> {
|
||||
Pin::new(&mut self.inner).poll_flush(cx)
|
||||
}
|
||||
|
||||
fn poll_shutdown(mut self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll<io::Result<()>> {
|
||||
Pin::new(&mut self.inner).poll_shutdown(cx)
|
||||
}
|
||||
|
||||
/*
|
||||
#[inline]
|
||||
fn write_buf<B: Buf>(&mut self, buf: &mut B) -> Poll<usize, io::Error> {
|
||||
self.inner.write_buf(buf)
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use std::mem;
|
||||
|
||||
use futures::{Future, IntoFuture, Poll};
|
||||
use super::{Future, Pin, Poll, task};
|
||||
|
||||
pub(crate) trait Started: Future {
|
||||
fn started(&self) -> bool;
|
||||
@@ -9,7 +9,7 @@ pub(crate) trait Started: Future {
|
||||
pub(crate) fn lazy<F, R>(func: F) -> Lazy<F, R>
|
||||
where
|
||||
F: FnOnce() -> R,
|
||||
R: IntoFuture,
|
||||
R: Future + Unpin,
|
||||
{
|
||||
Lazy {
|
||||
inner: Inner::Init(func),
|
||||
@@ -18,8 +18,8 @@ where
|
||||
|
||||
// FIXME: allow() required due to `impl Trait` leaking types to this lint
|
||||
#[allow(missing_debug_implementations)]
|
||||
pub(crate) struct Lazy<F, R: IntoFuture> {
|
||||
inner: Inner<F, R::Future>
|
||||
pub(crate) struct Lazy<F, R> {
|
||||
inner: Inner<F, R>
|
||||
}
|
||||
|
||||
enum Inner<F, R> {
|
||||
@@ -31,7 +31,7 @@ enum Inner<F, R> {
|
||||
impl<F, R> Started for Lazy<F, R>
|
||||
where
|
||||
F: FnOnce() -> R,
|
||||
R: IntoFuture,
|
||||
R: Future + Unpin,
|
||||
{
|
||||
fn started(&self) -> bool {
|
||||
match self.inner {
|
||||
@@ -45,21 +45,20 @@ where
|
||||
impl<F, R> Future for Lazy<F, R>
|
||||
where
|
||||
F: FnOnce() -> R,
|
||||
R: IntoFuture,
|
||||
R: Future + Unpin,
|
||||
{
|
||||
type Item = R::Item;
|
||||
type Error = R::Error;
|
||||
type Output = R::Output;
|
||||
|
||||
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
|
||||
fn poll(mut self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll<Self::Output> {
|
||||
match self.inner {
|
||||
Inner::Fut(ref mut f) => return f.poll(),
|
||||
Inner::Fut(ref mut f) => return Pin::new(f).poll(cx),
|
||||
_ => (),
|
||||
}
|
||||
|
||||
match mem::replace(&mut self.inner, Inner::Empty) {
|
||||
Inner::Init(func) => {
|
||||
let mut fut = func().into_future();
|
||||
let ret = fut.poll();
|
||||
let mut fut = func();
|
||||
let ret = Pin::new(&mut fut).poll(cx);
|
||||
self.inner = Inner::Fut(fut);
|
||||
ret
|
||||
},
|
||||
@@ -68,3 +67,6 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
// The closure `F` is never pinned
|
||||
impl<F, R: Unpin> Unpin for Lazy<F, R> {}
|
||||
|
||||
|
||||
@@ -1,3 +1,12 @@
|
||||
macro_rules! ready {
|
||||
($e:expr) => (
|
||||
match $e {
|
||||
::std::task::Poll::Ready(v) => v,
|
||||
::std::task::Poll::Pending => return ::std::task::Poll::Pending,
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
mod buf;
|
||||
pub(crate) mod drain;
|
||||
pub(crate) mod exec;
|
||||
@@ -10,4 +19,12 @@ pub(crate) use self::buf::StaticBuf;
|
||||
pub(crate) use self::exec::Exec;
|
||||
pub(crate) use self::lazy::{lazy, Started as Lazy};
|
||||
pub use self::never::Never;
|
||||
pub(crate) use self::task::YieldNow;
|
||||
pub(crate) use self::task::Poll;
|
||||
|
||||
// group up types normally needed for `Future`
|
||||
pub(crate) use std::{
|
||||
future::Future,
|
||||
marker::Unpin,
|
||||
pin::Pin,
|
||||
};
|
||||
|
||||
|
||||
@@ -1,40 +1,10 @@
|
||||
use futures::{Async, Poll, task::Task};
|
||||
|
||||
pub(crate) use std::task::{Context, Poll};
|
||||
use super::Never;
|
||||
|
||||
/// A type to help "yield" a future, such that it is re-scheduled immediately.
|
||||
/// A function to help "yield" a future, such that it is re-scheduled immediately.
|
||||
///
|
||||
/// Useful for spin counts, so a future doesn't hog too much time.
|
||||
#[derive(Debug)]
|
||||
pub(crate) struct YieldNow {
|
||||
cached_task: Option<Task>,
|
||||
}
|
||||
|
||||
impl YieldNow {
|
||||
pub(crate) fn new() -> YieldNow {
|
||||
YieldNow {
|
||||
cached_task: None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns `Ok(Async::NotReady)` always, while also notifying the
|
||||
/// current task so that it is rescheduled immediately.
|
||||
///
|
||||
/// Since it never returns `Async::Ready` or `Err`, those types are
|
||||
/// set to `Never`.
|
||||
pub(crate) fn poll_yield(&mut self) -> Poll<Never, Never> {
|
||||
// Check for a cached `Task` first...
|
||||
if let Some(ref t) = self.cached_task {
|
||||
if t.will_notify_current() {
|
||||
t.notify();
|
||||
return Ok(Async::NotReady);
|
||||
}
|
||||
}
|
||||
|
||||
// No cached task, or not current, so get a new one...
|
||||
let t = ::futures::task::current();
|
||||
t.notify();
|
||||
self.cached_task = Some(t);
|
||||
Ok(Async::NotReady)
|
||||
}
|
||||
pub(crate) fn yield_now(cx: &mut Context) -> Poll<Never> {
|
||||
cx.waker().wake_by_ref();
|
||||
Poll::Pending
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user