Revert "refactor(lib): convert to futures 0.2.0-beta (#1470)"
This reverts commit a12f7beed9.
Much sadness 😢.
This commit is contained in:
@@ -12,8 +12,7 @@ use std::fmt;
|
||||
|
||||
use bytes::Bytes;
|
||||
use futures::{Future, Poll};
|
||||
use futures::task;
|
||||
use futures::io::{AsyncRead, AsyncWrite};
|
||||
use tokio_io::{AsyncRead, AsyncWrite};
|
||||
|
||||
use proto;
|
||||
use proto::body::{Body, Entity};
|
||||
@@ -90,8 +89,8 @@ where S: Service<Request = Request<Body>, Response = Response<B>, Error = ::Erro
|
||||
/// upgrade. Once the upgrade is completed, the connection would be "done",
|
||||
/// but it is not desired to actally shutdown the IO object. Instead you
|
||||
/// would take it back using `into_parts`.
|
||||
pub fn poll_without_shutdown(&mut self, cx: &mut task::Context) -> Poll<(), ::Error> {
|
||||
try_ready!(self.conn.poll_without_shutdown(cx));
|
||||
pub fn poll_without_shutdown(&mut self) -> Poll<(), ::Error> {
|
||||
try_ready!(self.conn.poll_without_shutdown());
|
||||
Ok(().into())
|
||||
}
|
||||
}
|
||||
@@ -104,8 +103,8 @@ where S: Service<Request = Request<Body>, Response = Response<B>, Error = ::Erro
|
||||
type Item = ();
|
||||
type Error = ::Error;
|
||||
|
||||
fn poll(&mut self, cx: &mut task::Context) -> Poll<Self::Item, Self::Error> {
|
||||
self.conn.poll(cx)
|
||||
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
|
||||
self.conn.poll()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
//! them off to a `Service`.
|
||||
|
||||
pub mod conn;
|
||||
mod service;
|
||||
|
||||
use std::fmt;
|
||||
use std::io;
|
||||
@@ -12,15 +13,16 @@ use std::net::{SocketAddr, TcpListener as StdTcpListener};
|
||||
use std::sync::{Arc, Mutex, Weak};
|
||||
use std::time::Duration;
|
||||
|
||||
use futures::task::{self, Waker};
|
||||
use futures::task::{self, Task};
|
||||
use futures::future::{self};
|
||||
use futures::{Future, FutureExt, Stream, StreamExt, Poll, Async};
|
||||
use futures::io::{AsyncRead, AsyncWrite};
|
||||
use futures::executor::spawn;
|
||||
use futures::{Future, Stream, Poll, Async};
|
||||
use futures_timer::Delay;
|
||||
use http::{Request, Response};
|
||||
use tokio_io::{AsyncRead, AsyncWrite};
|
||||
use tokio::spawn;
|
||||
use tokio::reactor::Handle;
|
||||
use tokio::net::TcpListener;
|
||||
pub use tokio_service::{NewService, Service};
|
||||
|
||||
use proto::body::{Body, Entity};
|
||||
use proto;
|
||||
@@ -28,8 +30,7 @@ use self::addr_stream::AddrStream;
|
||||
use self::hyper_service::HyperService;
|
||||
|
||||
pub use self::conn::Connection;
|
||||
pub use super::service::{NewService, Service};
|
||||
pub use super::service::{const_service, service_fn};
|
||||
pub use self::service::{const_service, service_fn};
|
||||
|
||||
/// A configuration of the HTTP protocol.
|
||||
///
|
||||
@@ -254,10 +255,11 @@ impl<B: AsRef<[u8]> + 'static> Http<B> {
|
||||
/// # extern crate futures;
|
||||
/// # extern crate hyper;
|
||||
/// # extern crate tokio;
|
||||
/// # use futures::FutureExt;
|
||||
/// # use futures::io::{AsyncRead, AsyncWrite};
|
||||
/// # extern crate tokio_io;
|
||||
/// # use futures::Future;
|
||||
/// # use hyper::{Body, Request, Response};
|
||||
/// # use hyper::server::{Http, Service};
|
||||
/// # use tokio_io::{AsyncRead, AsyncWrite};
|
||||
/// # use tokio::reactor::Handle;
|
||||
/// # fn run<I, S>(some_io: I, some_service: S)
|
||||
/// # where
|
||||
@@ -270,9 +272,9 @@ impl<B: AsRef<[u8]> + 'static> Http<B> {
|
||||
///
|
||||
/// let fut = conn
|
||||
/// .map(|_| ())
|
||||
/// .map_err(|e| panic!("server connection error: {}", e));
|
||||
/// .map_err(|e| eprintln!("server connection error: {}", e));
|
||||
///
|
||||
/// tokio::spawn2(fut);
|
||||
/// tokio::spawn(fut);
|
||||
/// # }
|
||||
/// # fn main() {}
|
||||
/// ```
|
||||
@@ -332,8 +334,8 @@ impl Future for Run {
|
||||
type Item = ();
|
||||
type Error = ::Error;
|
||||
|
||||
fn poll(&mut self, cx: &mut task::Context) -> Poll<(), ::Error> {
|
||||
self.0.poll(cx)
|
||||
fn poll(&mut self) -> Poll<(), ::Error> {
|
||||
self.0.poll()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -410,21 +412,17 @@ impl<S, B> Server<S, B>
|
||||
let addr = socket.remote_addr;
|
||||
debug!("accepted new connection ({})", addr);
|
||||
|
||||
let service = match new_service.new_service() {
|
||||
Ok(service) => service,
|
||||
Err(err) => return future::err(err).left()
|
||||
};
|
||||
|
||||
let service = new_service.new_service()?;
|
||||
let s = NotifyService {
|
||||
inner: service,
|
||||
info: Arc::downgrade(&info_cloned),
|
||||
};
|
||||
info_cloned.lock().unwrap().active += 1;
|
||||
let fut = protocol.serve_connection(socket, s).recover(move |err| {
|
||||
error!("server connection error: ({}) {}", addr, err);
|
||||
});
|
||||
|
||||
spawn(fut).map_err(|err| err.never_into()).right()
|
||||
let fut = protocol.serve_connection(socket, s)
|
||||
.map(|_| ())
|
||||
.map_err(move |err| error!("server connection error: ({}) {}", addr, err));
|
||||
spawn(fut);
|
||||
Ok(())
|
||||
});
|
||||
|
||||
// for now, we don't care if the shutdown signal succeeds or errors
|
||||
@@ -440,11 +438,8 @@ impl<S, B> Server<S, B>
|
||||
// stop accepting incoming connections.
|
||||
let main_execution = shutdown_signal.select(srv).then(move |result| {
|
||||
match result {
|
||||
Ok(_) => {},
|
||||
Err(future::Either::Left((e, _other))) =>
|
||||
return future::Either::Left(future::err(e)),
|
||||
Err(future::Either::Right((e, _other))) =>
|
||||
return future::Either::Left(future::err(e.into())),
|
||||
Ok(((), _incoming)) => {},
|
||||
Err((e, _other)) => return future::Either::A(future::err(e.into()))
|
||||
}
|
||||
|
||||
// Ok we've stopped accepting new connections at this point, but we want
|
||||
@@ -456,11 +451,10 @@ impl<S, B> Server<S, B>
|
||||
// here have been destroyed.
|
||||
let timeout = Delay::new(shutdown_timeout);
|
||||
let wait = WaitUntilZero { info: info.clone() };
|
||||
future::Either::Right(wait.select(timeout).then(|result| {
|
||||
future::Either::B(wait.select(timeout).then(|result| {
|
||||
match result {
|
||||
Ok(_) => Ok(()),
|
||||
Err(future::Either::Left((e, _))) => Err(e.into()),
|
||||
Err(future::Either::Right((e, _))) => Err(e.into())
|
||||
Err((e, _)) => Err(e.into())
|
||||
}
|
||||
}))
|
||||
});
|
||||
@@ -511,8 +505,8 @@ where
|
||||
type Item = Connection<I::Item, S::Instance>;
|
||||
type Error = ::Error;
|
||||
|
||||
fn poll_next(&mut self, cx: &mut task::Context) -> Poll<Option<Self::Item>, Self::Error> {
|
||||
if let Some(io) = try_ready!(self.incoming.poll_next(cx)) {
|
||||
fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> {
|
||||
if let Some(io) = try_ready!(self.incoming.poll()) {
|
||||
let service = self.new_service.new_service()?;
|
||||
Ok(Async::Ready(Some(self.protocol.serve_connection(io, service))))
|
||||
} else {
|
||||
@@ -592,17 +586,17 @@ impl Stream for AddrIncoming {
|
||||
type Item = AddrStream;
|
||||
type Error = ::std::io::Error;
|
||||
|
||||
fn poll_next(&mut self, cx: &mut task::Context) -> Poll<Option<Self::Item>, Self::Error> {
|
||||
fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> {
|
||||
// Check if a previous timeout is active that was set by IO errors.
|
||||
if let Some(ref mut to) = self.timeout {
|
||||
match to.poll(cx).expect("timeout never fails") {
|
||||
match to.poll().expect("timeout never fails") {
|
||||
Async::Ready(_) => {}
|
||||
Async::Pending => return Ok(Async::Pending),
|
||||
Async::NotReady => return Ok(Async::NotReady),
|
||||
}
|
||||
}
|
||||
self.timeout = None;
|
||||
loop {
|
||||
match self.listener.poll_accept2(cx) {
|
||||
match self.listener.poll_accept() {
|
||||
Ok(Async::Ready((socket, addr))) => {
|
||||
if let Some(dur) = self.keep_alive_timeout {
|
||||
if let Err(e) = socket.set_keepalive(Some(dur)) {
|
||||
@@ -611,7 +605,7 @@ impl Stream for AddrIncoming {
|
||||
}
|
||||
return Ok(Async::Ready(Some(AddrStream::new(socket, addr))));
|
||||
},
|
||||
Ok(Async::Pending) => return Ok(Async::Pending),
|
||||
Ok(Async::NotReady) => return Ok(Async::NotReady),
|
||||
Err(ref e) if self.sleep_on_errors => {
|
||||
// Connection errors can be ignored directly, continue by
|
||||
// accepting the next request.
|
||||
@@ -623,13 +617,13 @@ impl Stream for AddrIncoming {
|
||||
debug!("accept error: {}; sleeping {:?}",
|
||||
e, delay);
|
||||
let mut timeout = Delay::new(delay);
|
||||
let result = timeout.poll(cx)
|
||||
let result = timeout.poll()
|
||||
.expect("timeout never fails");
|
||||
match result {
|
||||
Async::Ready(()) => continue,
|
||||
Async::Pending => {
|
||||
Async::NotReady => {
|
||||
self.timeout = Some(timeout);
|
||||
return Ok(Async::Pending);
|
||||
return Ok(Async::NotReady);
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -653,13 +647,12 @@ fn connection_error(e: &io::Error) -> bool {
|
||||
}
|
||||
|
||||
mod addr_stream {
|
||||
use std::io;
|
||||
use std::io::{self, Read, Write};
|
||||
use std::net::SocketAddr;
|
||||
use bytes::{Buf, BufMut};
|
||||
use futures::Poll;
|
||||
use futures::task;
|
||||
use futures::io::{AsyncRead, AsyncWrite, Initializer};
|
||||
use iovec::IoVec;
|
||||
use tokio::net::TcpStream;
|
||||
use tokio_io::{AsyncRead, AsyncWrite};
|
||||
|
||||
|
||||
#[derive(Debug)]
|
||||
@@ -677,42 +670,46 @@ mod addr_stream {
|
||||
}
|
||||
}
|
||||
|
||||
impl Read for AddrStream {
|
||||
#[inline]
|
||||
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
|
||||
self.inner.read(buf)
|
||||
}
|
||||
}
|
||||
|
||||
impl Write for AddrStream {
|
||||
#[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 AsyncRead for AddrStream {
|
||||
#[inline]
|
||||
fn poll_read(&mut self, cx: &mut task::Context, buf: &mut [u8]) -> Poll<usize, io::Error> {
|
||||
self.inner.poll_read(cx, buf)
|
||||
unsafe fn prepare_uninitialized_buffer(&self, buf: &mut [u8]) -> bool {
|
||||
self.inner.prepare_uninitialized_buffer(buf)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn initializer(&self) -> Initializer {
|
||||
AsyncRead::initializer(&self.inner)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn poll_vectored_read(&mut self, cx: &mut task::Context, vec: &mut [&mut IoVec]) -> Poll<usize, io::Error> {
|
||||
self.inner.poll_vectored_read(cx, vec)
|
||||
fn read_buf<B: BufMut>(&mut self, buf: &mut B) -> Poll<usize, io::Error> {
|
||||
self.inner.read_buf(buf)
|
||||
}
|
||||
}
|
||||
|
||||
impl AsyncWrite for AddrStream {
|
||||
#[inline]
|
||||
fn poll_write(&mut self, cx: &mut task::Context, buf: &[u8]) -> Poll<usize, io::Error> {
|
||||
self.inner.poll_write(cx, buf)
|
||||
fn shutdown(&mut self) -> Poll<(), io::Error> {
|
||||
AsyncWrite::shutdown(&mut self.inner)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn poll_flush(&mut self, cx: &mut task::Context) -> Poll<(), io::Error> {
|
||||
self.inner.poll_flush(cx)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn poll_close(&mut self, cx: &mut task::Context) -> Poll<(), io::Error> {
|
||||
self.inner.poll_close(cx)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn poll_vectored_write(&mut self, cx: &mut task::Context, vec: &[&IoVec]) -> Poll<usize, io::Error> {
|
||||
self.inner.poll_vectored_write(cx, vec)
|
||||
fn write_buf<B: Buf>(&mut self, buf: &mut B) -> Poll<usize, io::Error> {
|
||||
self.inner.write_buf(buf)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -730,7 +727,7 @@ struct WaitUntilZero {
|
||||
|
||||
struct Info {
|
||||
active: usize,
|
||||
blocker: Option<Waker>,
|
||||
blocker: Option<Task>,
|
||||
}
|
||||
|
||||
impl<S: Service> Service for NotifyService<S> {
|
||||
@@ -753,8 +750,8 @@ impl<S> Drop for NotifyService<S> {
|
||||
let mut info = info.lock().unwrap();
|
||||
info.active -= 1;
|
||||
if info.active == 0 {
|
||||
if let Some(waker) = info.blocker.take() {
|
||||
waker.wake();
|
||||
if let Some(task) = info.blocker.take() {
|
||||
task.notify();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -764,13 +761,13 @@ impl Future for WaitUntilZero {
|
||||
type Item = ();
|
||||
type Error = io::Error;
|
||||
|
||||
fn poll(&mut self, cx: &mut task::Context) -> Poll<(), io::Error> {
|
||||
fn poll(&mut self) -> Poll<(), io::Error> {
|
||||
let mut info = self.info.lock().unwrap();
|
||||
if info.active == 0 {
|
||||
Ok(().into())
|
||||
} else {
|
||||
info.blocker = Some(cx.waker().clone());
|
||||
Ok(Async::Pending)
|
||||
info.blocker = Some(task::current());
|
||||
Ok(Async::NotReady)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
64
src/server/service.rs
Normal file
64
src/server/service.rs
Normal file
@@ -0,0 +1,64 @@
|
||||
use std::marker::PhantomData;
|
||||
use std::sync::Arc;
|
||||
|
||||
use futures::IntoFuture;
|
||||
use tokio_service::{NewService, Service};
|
||||
|
||||
/// Create a `Service` from a function.
|
||||
pub fn service_fn<F, R, S>(f: F) -> ServiceFn<F, R>
|
||||
where
|
||||
F: Fn(R) -> S,
|
||||
S: IntoFuture,
|
||||
{
|
||||
ServiceFn {
|
||||
f: f,
|
||||
_req: PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
/// Create a `NewService` by sharing references of `service.
|
||||
pub fn const_service<S>(service: S) -> ConstService<S> {
|
||||
ConstService {
|
||||
svc: Arc::new(service),
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ServiceFn<F, R> {
|
||||
f: F,
|
||||
_req: PhantomData<fn() -> R>,
|
||||
}
|
||||
|
||||
impl<F, R, S> Service for ServiceFn<F, R>
|
||||
where
|
||||
F: Fn(R) -> S,
|
||||
S: IntoFuture,
|
||||
{
|
||||
type Request = R;
|
||||
type Response = S::Item;
|
||||
type Error = S::Error;
|
||||
type Future = S::Future;
|
||||
|
||||
fn call(&self, req: Self::Request) -> Self::Future {
|
||||
(self.f)(req).into_future()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ConstService<S> {
|
||||
svc: Arc<S>,
|
||||
}
|
||||
|
||||
impl<S> NewService for ConstService<S>
|
||||
where
|
||||
S: Service,
|
||||
{
|
||||
type Request = S::Request;
|
||||
type Response = S::Response;
|
||||
type Error = S::Error;
|
||||
type Instance = Arc<S>;
|
||||
|
||||
fn new_service(&self) -> ::std::io::Result<Self::Instance> {
|
||||
Ok(self.svc.clone())
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user