Update Tokio to use std::future. (#1120)

A first pass at updating Tokio to use `std::future`.

Implementations of `Future` from the futures crate are updated to implement
`Future` from std. Implementations of `Stream` are moved to a feature flag.

This commits disables a number of crates that have not yet been updated.
This commit is contained in:
Carl Lerche
2019-06-24 12:34:30 -07:00
committed by GitHub
parent aa99950b9c
commit 06c473e628
150 changed files with 2694 additions and 9825 deletions
+3 -3
View File
@@ -23,8 +23,8 @@ categories = ["concurrency", "asynchronous"]
publish = false
[dependencies]
crossbeam-utils = "0.6.2"
futures = "0.1.19"
# crossbeam-utils = "0.6.2"
crossbeam-utils = { git = "https://github.com/stjepang/crossbeam", branch = "raw-parker" }
[dev-dependencies]
tokio = { version = "0.2.0", path = "../tokio" }
# tokio = { version = "0.2.0", path = "../tokio" }
+20 -4
View File
@@ -1,9 +1,8 @@
use futures::{self, Future};
use std::cell::{Cell, RefCell};
use std::error::Error;
use std::fmt;
use std::future::Future;
use std::marker::PhantomData;
use std::prelude::v1::*;
thread_local!(static ENTERED: Cell<bool> = Cell::new(false));
@@ -65,8 +64,25 @@ pub fn enter() -> Result<Enter, EnterError> {
impl Enter {
/// Blocks the thread on the specified future, returning the value with
/// which that future completes.
pub fn block_on<F: Future>(&mut self, f: F) -> Result<F::Item, F::Error> {
futures::executor::spawn(f).wait_future()
pub fn block_on<F: Future>(&mut self, mut f: F) -> F::Output {
use crate::park::{Park, ParkThread};
use std::pin::Pin;
use std::task::Context;
use std::task::Poll::Ready;
let park = ParkThread::new();
let waker = park.unpark().into_waker();
let mut cx = Context::from_waker(&waker);
// `block_on` takes ownership of `f`. Once it is pinned here, the original `f` binding can
// no longer be accessed, making the pinning safe.
let mut f = unsafe { Pin::new_unchecked(&mut f) };
loop {
if let Ready(v) = f.as_mut().poll(&mut cx) {
return v;
}
}
}
}
+7 -8
View File
@@ -1,5 +1,6 @@
use crate::SpawnError;
use futures::Future;
use std::future::Future;
use std::pin::Pin;
/// A value that executes futures.
///
@@ -82,16 +83,14 @@ pub trait Executor {
/// use futures::future::lazy;
///
/// # fn docs(my_executor: &mut dyn Executor) {
/// my_executor.spawn(Box::new(lazy(|| {
/// my_executor.spawn(Box::pin(lazy(|| {
/// println!("running on the executor");
/// Ok(())
/// }))).unwrap();
/// # }
/// ```
fn spawn(
&mut self,
future: Box<dyn Future<Item = (), Error = ()> + Send>,
) -> Result<(), SpawnError>;
fn spawn(&mut self, future: Pin<Box<dyn Future<Output = ()> + Send>>)
-> Result<(), SpawnError>;
/// Provides a best effort **hint** to whether or not `spawn` will succeed.
///
@@ -116,7 +115,7 @@ pub trait Executor {
///
/// # fn docs(my_executor: &mut dyn Executor) {
/// if my_executor.status().is_ok() {
/// my_executor.spawn(Box::new(lazy(|| {
/// my_executor.spawn(Box::pin(lazy(|| {
/// println!("running on the executor");
/// Ok(())
/// }))).unwrap();
@@ -133,7 +132,7 @@ pub trait Executor {
impl<E: Executor + ?Sized> Executor for Box<E> {
fn spawn(
&mut self,
future: Box<dyn Future<Item = (), Error = ()> + Send>,
future: Pin<Box<dyn Future<Output = ()> + Send>>,
) -> Result<(), SpawnError> {
(**self).spawn(future)
}
+7 -26
View File
@@ -1,6 +1,7 @@
use super::{Enter, Executor, SpawnError};
use futures::{future, Future};
use std::cell::Cell;
use std::future::Future;
use std::pin::Pin;
/// Executes futures on the default executor for the current execution context.
///
@@ -70,7 +71,7 @@ thread_local! {
impl super::Executor for DefaultExecutor {
fn spawn(
&mut self,
future: Box<dyn Future<Item = (), Error = ()> + Send>,
future: Pin<Box<dyn Future<Output = ()> + Send>>,
) -> Result<(), SpawnError> {
DefaultExecutor::with_current(|executor| executor.spawn(future))
.unwrap_or_else(|| Err(SpawnError::shutdown()))
@@ -84,10 +85,10 @@ impl super::Executor for DefaultExecutor {
impl<T> super::TypedExecutor<T> for DefaultExecutor
where
T: Future<Item = (), Error = ()> + Send + 'static,
T: Future<Output = ()> + Send + 'static,
{
fn spawn(&mut self, future: T) -> Result<(), SpawnError> {
super::Executor::spawn(self, Box::new(future))
super::Executor::spawn(self, Box::pin(future))
}
fn status(&self) -> Result<(), SpawnError> {
@@ -95,26 +96,6 @@ where
}
}
impl<T> future::Executor<T> for DefaultExecutor
where
T: Future<Item = (), Error = ()> + Send + 'static,
{
fn execute(&self, future: T) -> Result<(), future::ExecuteError<T>> {
if let Err(e) = super::Executor::status(self) {
let kind = if e.is_at_capacity() {
future::ExecuteErrorKind::NoCapacity
} else {
future::ExecuteErrorKind::Shutdown
};
return Err(future::ExecuteError::new(kind, future));
}
let _ = DefaultExecutor::with_current(|executor| executor.spawn(Box::new(future)));
Ok(())
}
}
// ===== global spawn fns =====
/// Submits a future for execution on the default executor -- usually a
@@ -153,9 +134,9 @@ where
/// ```
pub fn spawn<T>(future: T)
where
T: Future<Item = (), Error = ()> + Send + 'static,
T: Future<Output = ()> + Send + 'static,
{
DefaultExecutor::current().spawn(Box::new(future)).unwrap()
DefaultExecutor::current().spawn(Box::pin(future)).unwrap()
}
/// Set the default executor for the duration of the closure
+43
View File
@@ -46,8 +46,10 @@
use crossbeam_utils::sync::{Parker, Unparker};
use std::marker::PhantomData;
use std::mem;
use std::rc::Rc;
use std::sync::Arc;
use std::task::{RawWaker, RawWakerVTable, Waker};
use std::time::Duration;
/// Block the current thread.
@@ -223,3 +225,44 @@ impl Unpark for UnparkThread {
self.inner.unpark();
}
}
static VTABLE: RawWakerVTable = RawWakerVTable::new(clone, wake, wake_by_ref, drop);
impl UnparkThread {
pub(crate) fn into_waker(self) -> Waker {
unsafe {
let raw = unparker_to_raw_waker(self.inner);
Waker::from_raw(raw)
}
}
}
unsafe fn unparker_to_raw_waker(unparker: Unparker) -> RawWaker {
RawWaker::new(Unparker::into_raw(unparker), &VTABLE)
}
unsafe fn clone(raw: *const ()) -> RawWaker {
let unparker = Unparker::from_raw(raw);
// Increment the ref count
mem::forget(unparker.clone());
unparker_to_raw_waker(unparker)
}
unsafe fn wake(raw: *const ()) {
let unparker = Unparker::from_raw(raw);
unparker.unpark();
}
unsafe fn wake_by_ref(raw: *const ()) {
let unparker = Unparker::from_raw(raw);
unparker.unpark();
// We don't actually own a reference to the unparker
mem::forget(unparker);
}
unsafe fn drop(raw: *const ()) {
let _ = Unparker::from_raw(raw);
}
+18
View File
@@ -0,0 +1,18 @@
#![deny(warnings, rust_2018_idioms)]
#![feature(await_macro, async_await)]
#[test]
fn block_on_ready() {
let mut enter = tokio_executor::enter().unwrap();
let val = enter.block_on(async { 123 });
assert_eq!(val, 123);
}
#[test]
fn block_on_pending() {
let mut enter = tokio_executor::enter().unwrap();
let val = enter.block_on(async { 123 });
assert_eq!(val, 123);
}
+6 -9
View File
@@ -1,17 +1,20 @@
#![deny(warnings, rust_2018_idioms)]
#![feature(await_macro, async_await)]
use futures::{self, future::lazy, Future};
use tokio_executor::{self, DefaultExecutor};
use std::future::Future;
use std::pin::Pin;
mod out_of_executor_context {
use super::*;
use tokio_executor::Executor;
fn test<F, E>(spawn: F)
where
F: Fn(Box<dyn Future<Item = (), Error = ()> + Send>) -> Result<(), E>,
F: Fn(Pin<Box<dyn Future<Output = ()> + Send>>) -> Result<(), E>,
{
let res = spawn(Box::new(lazy(|| Ok(()))));
let res = spawn(Box::pin(async {}));
assert!(res.is_err());
}
@@ -19,10 +22,4 @@ mod out_of_executor_context {
fn spawn() {
test(|f| DefaultExecutor::current().spawn(f));
}
#[test]
fn execute() {
use futures::future::Executor as FuturesExecutor;
test(|f| DefaultExecutor::current().execute(f));
}
}