mirror of
https://github.com/fafhrd91/actix-net
synced 2025-06-26 19:47:43 +02:00
Migrate actix-net to std::future (#64)
* Migrate actix-codec, actix-rt, and actix-threadpool to std::future * update to latest tokio alpha and futures-rs * Migrate actix-service to std::future, This is a squash of ~8 commits, since it included a lot of experimentation. To see the commits, look into the semtexzv/std-future-service-tmp branch. * update futures-rs and tokio * Migrate actix-threadpool to std::future (#59) * Migrate actix-threadpool to std::future * Cosmetic refactor - turn log::error! into log::warn! as it doesn't throw any error - add Clone and Copy impls for Cancelled making it cheap to operate with - apply rustfmt * Bump up crate version to 0.2.0 and pre-fill its changelog * Disable patching 'actix-threadpool' crate in global workspace as unnecessary * Revert patching and fix 'actix-rt' * Migrate actix-rt to std::future (#47) * remove Pin from Service::poll_ready(); simplify combinators api; make code compile * disable tests * update travis config * refactor naming * drop IntoFuture trait * Migrate actix-server to std::future (#50) Still not finished, this is more WIP, this is an aggregation of several commits, which can be found in semtexzv/std-future-server-tmp branch * update actix-server * rename Factor to ServiceFactory * start server worker in start mehtod * update actix-utils * remove IntoTransform trait * Migrate actix-server::ssl::nativetls to std futures (#61) * Refactor 'nativetls' module * Migrate 'actix-server-config' to std futures - remove "uds" feature - disable features by default * Switch NativeTlsAcceptor to use 'tokio-tls' crate * Bikeshed features names and remove unnecessary dependencies for 'actix-server-config' crate * update openssl impl * migrate actix-connect to std::future * migrate actix-ioframe to std::future * update version to alpha.1 * fix boxed service * migrate server rustls support * migratte openssl and rustls connecttors * store the thread's handle with arbiter (#62) * update ssl connect tests * restore service tests * update readme
This commit is contained in:
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "actix-rt"
|
||||
version = "0.2.6"
|
||||
version = "1.0.0-alpha.1"
|
||||
authors = ["Nikolay Kim <fafhrd91@gmail.com>"]
|
||||
description = "Actix runtime"
|
||||
keywords = ["network", "framework", "async", "futures"]
|
||||
@ -18,10 +18,13 @@ name = "actix_rt"
|
||||
path = "src/lib.rs"
|
||||
|
||||
[dependencies]
|
||||
actix-threadpool = "0.1.1"
|
||||
futures = "0.1.25"
|
||||
tokio-current-thread = "0.1"
|
||||
tokio-executor = "0.1.5"
|
||||
tokio-reactor = "0.1.7"
|
||||
tokio-timer = "0.2.8"
|
||||
actix-threadpool = "0.2"
|
||||
futures = "0.3.1"
|
||||
|
||||
# TODO: Replace this with dependency on tokio-runtime once it is ready
|
||||
tokio = { version = "0.2.0-alpha.6" }
|
||||
tokio-timer = "=0.3.0-alpha.6"
|
||||
tokio-executor = "=0.2.0-alpha.6"
|
||||
tokio-net = "=0.2.0-alpha.6"
|
||||
|
||||
copyless = "0.1.4"
|
||||
|
@ -1,13 +1,15 @@
|
||||
use std::any::{Any, TypeId};
|
||||
use std::cell::{Cell, RefCell};
|
||||
use std::collections::HashMap;
|
||||
use std::pin::Pin;
|
||||
use std::sync::atomic::{AtomicUsize, Ordering};
|
||||
use std::task::{Context, Poll};
|
||||
use std::{fmt, thread};
|
||||
|
||||
use futures::sync::mpsc::{unbounded, UnboundedReceiver, UnboundedSender};
|
||||
use futures::sync::oneshot::{channel, Canceled, Sender};
|
||||
use futures::{future, Async, Future, IntoFuture, Poll, Stream};
|
||||
use tokio_current_thread::spawn;
|
||||
use futures::channel::mpsc::{unbounded, UnboundedReceiver, UnboundedSender};
|
||||
use futures::channel::oneshot::{channel, Canceled, Sender};
|
||||
use futures::{future, Future, FutureExt, Stream};
|
||||
use tokio::runtime::current_thread::spawn;
|
||||
|
||||
use crate::builder::Builder;
|
||||
use crate::system::System;
|
||||
@ -17,7 +19,7 @@ use copyless::BoxHelper;
|
||||
thread_local!(
|
||||
static ADDR: RefCell<Option<Arbiter>> = RefCell::new(None);
|
||||
static RUNNING: Cell<bool> = Cell::new(false);
|
||||
static Q: RefCell<Vec<Box<dyn Future<Item = (), Error = ()>>>> = RefCell::new(Vec::new());
|
||||
static Q: RefCell<Vec<Box<dyn Future<Output = ()>>>> = RefCell::new(Vec::new());
|
||||
static STORAGE: RefCell<HashMap<TypeId, Box<dyn Any>>> = RefCell::new(HashMap::new());
|
||||
);
|
||||
|
||||
@ -25,7 +27,7 @@ pub(crate) static COUNT: AtomicUsize = AtomicUsize::new(0);
|
||||
|
||||
pub(crate) enum ArbiterCommand {
|
||||
Stop,
|
||||
Execute(Box<dyn Future<Item = (), Error = ()> + Send>),
|
||||
Execute(Box<dyn Future<Output = ()> + Unpin + Send>),
|
||||
ExecuteFn(Box<dyn FnExec>),
|
||||
}
|
||||
|
||||
@ -96,41 +98,49 @@ impl Arbiter {
|
||||
let (arb_tx, arb_rx) = unbounded();
|
||||
let arb_tx2 = arb_tx.clone();
|
||||
|
||||
let handle = thread::Builder::new().name(name.clone()).spawn(move || {
|
||||
let mut rt = Builder::new().build_rt().expect("Can not create Runtime");
|
||||
let arb = Arbiter::with_sender(arb_tx);
|
||||
let handle = thread::Builder::new()
|
||||
.name(name.clone())
|
||||
.spawn(move || {
|
||||
let mut rt = Builder::new().build_rt().expect("Can not create Runtime");
|
||||
let arb = Arbiter::with_sender(arb_tx);
|
||||
|
||||
let (stop, stop_rx) = channel();
|
||||
RUNNING.with(|cell| cell.set(true));
|
||||
STORAGE.with(|cell| cell.borrow_mut().clear());
|
||||
let (stop, stop_rx) = channel();
|
||||
RUNNING.with(|cell| cell.set(true));
|
||||
STORAGE.with(|cell| cell.borrow_mut().clear());
|
||||
|
||||
System::set_current(sys);
|
||||
System::set_current(sys);
|
||||
|
||||
// start arbiter controller
|
||||
rt.spawn(ArbiterController {
|
||||
stop: Some(stop),
|
||||
rx: arb_rx,
|
||||
// start arbiter controller
|
||||
rt.spawn(ArbiterController {
|
||||
stop: Some(stop),
|
||||
rx: arb_rx,
|
||||
});
|
||||
ADDR.with(|cell| *cell.borrow_mut() = Some(arb.clone()));
|
||||
|
||||
// register arbiter
|
||||
let _ = System::current()
|
||||
.sys()
|
||||
.unbounded_send(SystemCommand::RegisterArbiter(id, arb.clone()));
|
||||
|
||||
// run loop
|
||||
let _ = match rt.block_on(stop_rx) {
|
||||
Ok(code) => code,
|
||||
Err(_) => 1,
|
||||
};
|
||||
|
||||
// unregister arbiter
|
||||
let _ = System::current()
|
||||
.sys()
|
||||
.unbounded_send(SystemCommand::UnregisterArbiter(id));
|
||||
})
|
||||
.unwrap_or_else(|err| {
|
||||
panic!("Cannot spawn an arbiter's thread {:?}: {:?}", &name, err)
|
||||
});
|
||||
ADDR.with(|cell| *cell.borrow_mut() = Some(arb.clone()));
|
||||
|
||||
// register arbiter
|
||||
let _ = System::current()
|
||||
.sys()
|
||||
.unbounded_send(SystemCommand::RegisterArbiter(id, arb.clone()));
|
||||
|
||||
// run loop
|
||||
let _ = match rt.block_on(stop_rx) {
|
||||
Ok(code) => code,
|
||||
Err(_) => 1,
|
||||
};
|
||||
|
||||
// unregister arbiter
|
||||
let _ = System::current()
|
||||
.sys()
|
||||
.unbounded_send(SystemCommand::UnregisterArbiter(id));
|
||||
}).unwrap_or_else(|err| panic!("Cannot spawn an arbiter's thread {:?}: {:?}", &name, err));
|
||||
|
||||
Arbiter{sender: arb_tx2, thread_handle: Some(handle)}
|
||||
Arbiter {
|
||||
sender: arb_tx2,
|
||||
thread_handle: Some(handle),
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn run_system() {
|
||||
@ -138,7 +148,9 @@ impl Arbiter {
|
||||
Q.with(|cell| {
|
||||
let mut v = cell.borrow_mut();
|
||||
for fut in v.drain(..) {
|
||||
spawn(fut);
|
||||
// We pin the boxed future, so it can never again be moved.
|
||||
let fut = unsafe { Pin::new_unchecked(fut) };
|
||||
tokio_executor::current_thread::spawn(fut);
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -152,12 +164,15 @@ impl Arbiter {
|
||||
/// thread.
|
||||
pub fn spawn<F>(future: F)
|
||||
where
|
||||
F: Future<Item = (), Error = ()> + 'static,
|
||||
F: Future<Output = ()> + 'static,
|
||||
{
|
||||
RUNNING.with(move |cell| {
|
||||
if cell.get() {
|
||||
spawn(Box::alloc().init(future));
|
||||
// Spawn the future on running executor
|
||||
spawn(future);
|
||||
} else {
|
||||
// Box the future and push it to the queue, this results in double boxing
|
||||
// because the executor boxes the future again, but works for now
|
||||
Q.with(move |cell| cell.borrow_mut().push(Box::alloc().init(future)));
|
||||
}
|
||||
});
|
||||
@ -169,15 +184,15 @@ impl Arbiter {
|
||||
pub fn spawn_fn<F, R>(f: F)
|
||||
where
|
||||
F: FnOnce() -> R + 'static,
|
||||
R: IntoFuture<Item = (), Error = ()> + 'static,
|
||||
R: Future<Output = ()> + 'static,
|
||||
{
|
||||
Arbiter::spawn(future::lazy(f))
|
||||
Arbiter::spawn(future::lazy(|_| f()).flatten())
|
||||
}
|
||||
|
||||
/// Send a future to the Arbiter's thread, and spawn it.
|
||||
pub fn send<F>(&self, future: F)
|
||||
where
|
||||
F: Future<Item = (), Error = ()> + Send + 'static,
|
||||
F: Future<Output = ()> + Send + Unpin + 'static,
|
||||
{
|
||||
let _ = self
|
||||
.sender
|
||||
@ -200,7 +215,7 @@ impl Arbiter {
|
||||
/// Send a function to the Arbiter's thread. This function will be executed asynchronously.
|
||||
/// A future is created, and when resolved will contain the result of the function sent
|
||||
/// to the Arbiters thread.
|
||||
pub fn exec<F, R>(&self, f: F) -> impl Future<Item = R, Error = Canceled>
|
||||
pub fn exec<F, R>(&self, f: F) -> impl Future<Output = Result<R, Canceled>>
|
||||
where
|
||||
F: FnOnce() -> R + Send + 'static,
|
||||
R: Send + 'static,
|
||||
@ -261,15 +276,17 @@ impl Arbiter {
|
||||
}
|
||||
|
||||
fn with_sender(sender: UnboundedSender<ArbiterCommand>) -> Self {
|
||||
Self{sender, thread_handle: None}
|
||||
Self {
|
||||
sender,
|
||||
thread_handle: None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Wait for the event loop to stop by joining the underlying thread (if have Some).
|
||||
pub fn join(&mut self) -> thread::Result<()>{
|
||||
pub fn join(&mut self) -> thread::Result<()> {
|
||||
if let Some(thread_handle) = self.thread_handle.take() {
|
||||
thread_handle.join()
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
@ -294,19 +311,18 @@ impl Drop for ArbiterController {
|
||||
}
|
||||
|
||||
impl Future for ArbiterController {
|
||||
type Item = ();
|
||||
type Error = ();
|
||||
type Output = ();
|
||||
|
||||
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
|
||||
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||
loop {
|
||||
match self.rx.poll() {
|
||||
Ok(Async::Ready(None)) | Err(_) => return Ok(Async::Ready(())),
|
||||
Ok(Async::Ready(Some(item))) => match item {
|
||||
match Pin::new(&mut self.rx).poll_next(cx) {
|
||||
Poll::Ready(None) => return Poll::Ready(()),
|
||||
Poll::Ready(Some(item)) => match item {
|
||||
ArbiterCommand::Stop => {
|
||||
if let Some(stop) = self.stop.take() {
|
||||
let _ = stop.send(0);
|
||||
};
|
||||
return Ok(Async::Ready(()));
|
||||
return Poll::Ready(());
|
||||
}
|
||||
ArbiterCommand::Execute(fut) => {
|
||||
spawn(fut);
|
||||
@ -315,7 +331,7 @@ impl Future for ArbiterController {
|
||||
f.call_box();
|
||||
}
|
||||
},
|
||||
Ok(Async::NotReady) => return Ok(Async::NotReady),
|
||||
Poll::Pending => return Poll::Pending,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -346,14 +362,13 @@ impl SystemArbiter {
|
||||
}
|
||||
|
||||
impl Future for SystemArbiter {
|
||||
type Item = ();
|
||||
type Error = ();
|
||||
type Output = ();
|
||||
|
||||
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
|
||||
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||
loop {
|
||||
match self.commands.poll() {
|
||||
Ok(Async::Ready(None)) | Err(_) => return Ok(Async::Ready(())),
|
||||
Ok(Async::Ready(Some(cmd))) => match cmd {
|
||||
match Pin::new(&mut self.commands).poll_next(cx) {
|
||||
Poll::Ready(None) => return Poll::Ready(()),
|
||||
Poll::Ready(Some(cmd)) => match cmd {
|
||||
SystemCommand::Exit(code) => {
|
||||
// stop arbiters
|
||||
for arb in self.arbiters.values() {
|
||||
@ -371,7 +386,7 @@ impl Future for SystemArbiter {
|
||||
self.arbiters.remove(&name);
|
||||
}
|
||||
},
|
||||
Ok(Async::NotReady) => return Ok(Async::NotReady),
|
||||
Poll::Pending => return Poll::Pending,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,19 +1,19 @@
|
||||
use std::borrow::Cow;
|
||||
use std::io;
|
||||
|
||||
use futures::future;
|
||||
use futures::channel::mpsc::unbounded;
|
||||
use futures::channel::oneshot::{channel, Receiver};
|
||||
use futures::future::{lazy, Future};
|
||||
use futures::sync::mpsc::unbounded;
|
||||
use futures::sync::oneshot::{channel, Receiver};
|
||||
use futures::{future, FutureExt};
|
||||
|
||||
use tokio_current_thread::{CurrentThread, Handle};
|
||||
use tokio_reactor::Reactor;
|
||||
use tokio_timer::clock::Clock;
|
||||
use tokio_timer::timer::Timer;
|
||||
use tokio::runtime::current_thread::Handle;
|
||||
use tokio_net::driver::Reactor;
|
||||
use tokio_timer::{clock::Clock, timer::Timer};
|
||||
|
||||
use crate::arbiter::{Arbiter, SystemArbiter};
|
||||
use crate::runtime::Runtime;
|
||||
use crate::system::System;
|
||||
use tokio_executor::current_thread::CurrentThread;
|
||||
|
||||
/// Builder struct for a actix runtime.
|
||||
///
|
||||
@ -118,7 +118,7 @@ impl Builder {
|
||||
rt.spawn(arb);
|
||||
|
||||
// init system arbiter and run configuration method
|
||||
let _ = rt.block_on(lazy(move || {
|
||||
let _ = rt.block_on(lazy(move |_| {
|
||||
f();
|
||||
Ok::<_, ()>(())
|
||||
}));
|
||||
@ -159,30 +159,31 @@ pub(crate) struct AsyncSystemRunner {
|
||||
impl AsyncSystemRunner {
|
||||
/// This function will start event loop and returns a future that
|
||||
/// resolves once the `System::stop()` function is called.
|
||||
pub(crate) fn run_nonblocking(self) -> impl Future<Item = (), Error = io::Error> + Send {
|
||||
pub(crate) fn run_nonblocking(self) -> impl Future<Output = Result<(), io::Error>> + Send {
|
||||
let AsyncSystemRunner { stop, .. } = self;
|
||||
|
||||
// run loop
|
||||
future::lazy(|| {
|
||||
future::lazy(|_| {
|
||||
Arbiter::run_system();
|
||||
stop.then(|res| match res {
|
||||
Ok(code) => {
|
||||
if code != 0 {
|
||||
Err(io::Error::new(
|
||||
io::ErrorKind::Other,
|
||||
format!("Non-zero exit code: {}", code),
|
||||
))
|
||||
} else {
|
||||
Ok(())
|
||||
async {
|
||||
let res = match stop.await {
|
||||
Ok(code) => {
|
||||
if code != 0 {
|
||||
Err(io::Error::new(
|
||||
io::ErrorKind::Other,
|
||||
format!("Non-zero exit code: {}", code),
|
||||
))
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(e) => Err(io::Error::new(io::ErrorKind::Other, e)),
|
||||
})
|
||||
.then(|result| {
|
||||
Err(e) => Err(io::Error::new(io::ErrorKind::Other, e)),
|
||||
};
|
||||
Arbiter::stop_system();
|
||||
result
|
||||
})
|
||||
return res;
|
||||
}
|
||||
})
|
||||
.flatten()
|
||||
}
|
||||
}
|
||||
|
||||
@ -202,10 +203,10 @@ impl SystemRunner {
|
||||
let SystemRunner { mut rt, stop, .. } = self;
|
||||
|
||||
// run loop
|
||||
let _ = rt.block_on(lazy(move || {
|
||||
let _ = rt.block_on(async {
|
||||
Arbiter::run_system();
|
||||
Ok::<_, ()>(())
|
||||
}));
|
||||
});
|
||||
let result = match rt.block_on(stop) {
|
||||
Ok(code) => {
|
||||
if code != 0 {
|
||||
@ -224,19 +225,19 @@ impl SystemRunner {
|
||||
}
|
||||
|
||||
/// Execute a future and wait for result.
|
||||
pub fn block_on<F, I, E>(&mut self, fut: F) -> Result<I, E>
|
||||
pub fn block_on<F, O>(&mut self, fut: F) -> O
|
||||
where
|
||||
F: Future<Item = I, Error = E>,
|
||||
F: Future<Output = O>,
|
||||
{
|
||||
let _ = self.rt.block_on(lazy(move || {
|
||||
let _ = self.rt.block_on(async {
|
||||
Arbiter::run_system();
|
||||
Ok::<_, ()>(())
|
||||
}));
|
||||
});
|
||||
|
||||
let res = self.rt.block_on(fut);
|
||||
let _ = self.rt.block_on(lazy(move || {
|
||||
let _ = self.rt.block_on(async {
|
||||
Arbiter::stop_system();
|
||||
Ok::<_, ()>(())
|
||||
}));
|
||||
});
|
||||
|
||||
res
|
||||
}
|
||||
}
|
||||
|
@ -20,7 +20,7 @@ pub use actix_threadpool as blocking;
|
||||
/// This function panics if actix system is not running.
|
||||
pub fn spawn<F>(f: F)
|
||||
where
|
||||
F: futures::Future<Item = (), Error = ()> + 'static,
|
||||
F: futures::Future<Output = ()> + 'static,
|
||||
{
|
||||
if !System::is_set() {
|
||||
panic!("System is not running");
|
||||
|
@ -2,11 +2,12 @@ use std::error::Error;
|
||||
use std::{fmt, io};
|
||||
|
||||
use futures::Future;
|
||||
use tokio_current_thread::{self as current_thread, CurrentThread};
|
||||
use tokio_executor;
|
||||
use tokio_reactor::{self, Reactor};
|
||||
use tokio_timer::clock::{self, Clock};
|
||||
use tokio_timer::timer::{self, Timer};
|
||||
use tokio_executor::current_thread::{self, CurrentThread};
|
||||
use tokio_net::driver::{Handle as ReactorHandle, Reactor};
|
||||
use tokio_timer::{
|
||||
clock::Clock,
|
||||
timer::{self, Timer},
|
||||
};
|
||||
|
||||
use crate::builder::Builder;
|
||||
|
||||
@ -18,7 +19,7 @@ use crate::builder::Builder;
|
||||
/// [mod]: index.html
|
||||
#[derive(Debug)]
|
||||
pub struct Runtime {
|
||||
reactor_handle: tokio_reactor::Handle,
|
||||
reactor_handle: ReactorHandle,
|
||||
timer_handle: timer::Handle,
|
||||
clock: Clock,
|
||||
executor: CurrentThread<Timer<Reactor>>,
|
||||
@ -53,7 +54,7 @@ impl Runtime {
|
||||
}
|
||||
|
||||
pub(super) fn new2(
|
||||
reactor_handle: tokio_reactor::Handle,
|
||||
reactor_handle: ReactorHandle,
|
||||
timer_handle: timer::Handle,
|
||||
clock: Clock,
|
||||
executor: CurrentThread<Timer<Reactor>>,
|
||||
@ -83,9 +84,8 @@ impl Runtime {
|
||||
/// let mut rt = Runtime::new().unwrap();
|
||||
///
|
||||
/// // Spawn a future onto the runtime
|
||||
/// rt.spawn(future::lazy(|| {
|
||||
/// rt.spawn(future::lazy(|_| {
|
||||
/// println!("running on the runtime");
|
||||
/// Ok(())
|
||||
/// }));
|
||||
/// # }
|
||||
/// # pub fn main() {}
|
||||
@ -97,7 +97,7 @@ impl Runtime {
|
||||
/// is currently at capacity and is unable to spawn a new future.
|
||||
pub fn spawn<F>(&mut self, future: F) -> &mut Self
|
||||
where
|
||||
F: Future<Item = (), Error = ()> + 'static,
|
||||
F: Future<Output = ()> + 'static,
|
||||
{
|
||||
self.executor.spawn(future);
|
||||
self
|
||||
@ -119,14 +119,14 @@ impl Runtime {
|
||||
///
|
||||
/// The caller is responsible for ensuring that other spawned futures
|
||||
/// complete execution by calling `block_on` or `run`.
|
||||
pub fn block_on<F>(&mut self, f: F) -> Result<F::Item, F::Error>
|
||||
pub fn block_on<F>(&mut self, f: F) -> F::Output
|
||||
where
|
||||
F: Future,
|
||||
{
|
||||
self.enter(|executor| {
|
||||
// Run the provided future
|
||||
let ret = executor.block_on(f);
|
||||
ret.map_err(|e| e.into_inner().expect("unexpected execution error"))
|
||||
ret
|
||||
})
|
||||
}
|
||||
|
||||
@ -139,7 +139,7 @@ impl Runtime {
|
||||
|
||||
fn enter<F, R>(&mut self, f: F) -> R
|
||||
where
|
||||
F: FnOnce(&mut current_thread::Entered<Timer<Reactor>>) -> R,
|
||||
F: FnOnce(&mut CurrentThread<Timer<Reactor>>) -> R,
|
||||
{
|
||||
let Runtime {
|
||||
ref reactor_handle,
|
||||
@ -149,25 +149,13 @@ impl Runtime {
|
||||
..
|
||||
} = *self;
|
||||
|
||||
// Binds an executor to this thread
|
||||
let mut enter = tokio_executor::enter().expect("Multiple executors at once");
|
||||
|
||||
// This will set the default handle and timer to use inside the closure
|
||||
// and run the future.
|
||||
tokio_reactor::with_default(&reactor_handle, &mut enter, |enter| {
|
||||
clock::with_default(clock, enter, |enter| {
|
||||
timer::with_default(&timer_handle, enter, |enter| {
|
||||
// The TaskExecutor is a fake executor that looks into the
|
||||
// current single-threaded executor when used. This is a trick,
|
||||
// because we need two mutable references to the executor (one
|
||||
// to run the provided future, another to install as the default
|
||||
// one). We use the fake one here as the default one.
|
||||
let mut default_executor = current_thread::TaskExecutor::current();
|
||||
tokio_executor::with_default(&mut default_executor, enter, |enter| {
|
||||
let mut executor = executor.enter(enter);
|
||||
f(&mut executor)
|
||||
})
|
||||
})
|
||||
// WARN: We do not enter the executor here, since in tokio 0.2 the executor is entered
|
||||
// automatically inside its `block_on` and `run` methods
|
||||
tokio_executor::with_default(&mut current_thread::TaskExecutor::current(), || {
|
||||
tokio_timer::clock::with_default(clock, || {
|
||||
let _reactor_guard = tokio_net::driver::set_default(reactor_handle);
|
||||
let _timer_guard = tokio_timer::set_default(timer_handle);
|
||||
f(executor)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
@ -2,9 +2,9 @@ use std::cell::RefCell;
|
||||
use std::io;
|
||||
use std::sync::atomic::{AtomicUsize, Ordering};
|
||||
|
||||
use futures::sync::mpsc::UnboundedSender;
|
||||
use futures::channel::mpsc::UnboundedSender;
|
||||
use futures::Future;
|
||||
use tokio_current_thread::Handle;
|
||||
use tokio::runtime::current_thread::Handle;
|
||||
|
||||
use crate::arbiter::{Arbiter, SystemCommand};
|
||||
use crate::builder::{Builder, SystemRunner};
|
||||
@ -64,7 +64,7 @@ impl System {
|
||||
pub fn run_in_executor<T: Into<String>>(
|
||||
name: T,
|
||||
executor: Handle,
|
||||
) -> impl Future<Item = (), Error = io::Error> + Send {
|
||||
) -> impl Future<Output = Result<(), io::Error>> + Send {
|
||||
Self::builder()
|
||||
.name(name)
|
||||
.build_async(executor)
|
||||
|
Reference in New Issue
Block a user