[−][src]Module tokio_compat::runtime
feature="rt-current-thread"
or feature="rt-full"
only.Runtimes compatible with both tokio
0.1 and tokio
0.2 futures.
This module is similar to the tokio::runtime
module, with one
key difference: the runtimes in this crate are capable of executing
both futures
0.1 futures that use the tokio
0.1 runtime services
(i.e. timer
, reactor
, and executor
), and std::future
futures that use the tokio
0.2 runtime services.
The futures
crate's compat
module provides
interoperability between futures
0.1 and std::future
future types
(e.g. implementing std::future::Future
for a type that implements the
futures
0.1 Future
trait). However, this on its own is insufficient to
run code written against tokio
0.1 on a tokio
0.2 runtime, if that code
also relies on tokio
's runtime services. If legacy tasks are executed that
rely on tokio::timer
, perform IO using tokio
's reactor, or call
tokio::spawn
, those API calls will fail unless there is also a runtime
compatibility layer.
tokio-compat
's runtime
module contains modified versions of the tokio
0.2 Runtime
and current_thread::Runtime
that are capable of providing
tokio
0.1 and tokio
0.2-compatible runtime services.
Creating a Runtime
does the following:
- Start a thread pool for executing futures.
- Run resource drivers for the timer and I/O resources.
- Run a single
tokio
0.1Reactor
andTimer
on a background thread, for legacy tasks.
Legacy futures
0.1 tasks will be executed by the tokio
0.2 thread pool
workers, alongside std::future
tasks. However, they will use the timer and
reactor provided by the compatibility background thread.
Using the Compatibility Runtime
Spawning
In order to allow drop-in compatibility for legacy codebases using
tokio
0.1, the run
, spawn
, and block_on
methods provided by the
compatibility runtimes take futures
0.1 futures. This allows the
compatibility runtimes to replace the tokio
0.1 runtimes in those codebases
without requiring changes to unrelated code. The compatibility runtimes
also provide std::future
-compatible versions of these methods, named
run_std
, spawn_std
, and block_on_std
.
Shutting Down
Tokio 0.1 and Tokio 0.2 provide subtly different behavior around spawning
tasks and shutting down runtimes. In 0.1, the threadpool and current-thread
runtimes provide shutdown_on_idle
and run
methods,
respectively, which will shut the runtime down when when there are no more
tasks currently executing. In Tokio 0.2, these methods no longer exist.
Instead, 0.2's runtime will shut down when the future passed to block_on
finishes, and the spawn
function now returns a JoinHandle
, which can
be used to await the completion of the spawned future. By awaiting these
JoinHandle
s, the 0.2 user now has much more fine-grained control over
which tasks keep the runtime active. Additionally, 0.2's runtimes can avoid
the overhead of tracking the global number of running tasks for determining
idleness.
How, then, do we bridge the gaps between these two models? The
tokio-compat
runtimes provide separate APIs for spawning both Tokio 0.1
and Tokio
0.2 tasks with with and without JoinHandle
s. For example,
the Runtime
type has the following methods:
Runtime::spawn
spawns afutures
0.1 future, and does not return aJoinHandle
(liketokio
0.1).Runtime::spawn_std
spawns astd::future
future, and does not return aJoinHandle
.Runtime::spawn_handle
spawns afutures
0.1 future, and returns aJoinHandle
.Runtime::spawn_handle_std
spawns astd::future
future, and returns aJoinHandle
(liketokio
0.2).
Other types which spawn futures, like TaskExecutor
, provide similar APIs.
The tokio-compat
current-thread and thread pool runtimes also provide
their own versions of run
and shutdown_on_idle
, respectively. However,
only tasks spawned without JoinHandle
s "count" against idleness. This
means that if a task is spawned by a function returning a JoinHandle
, it
will not keep the runtime active if no other tasks are running.
Why is this the case? There are two primary reasons:
- The
shutdown_on_idle
andrun
methods no longer exist intokio
0.2. Therefore, codebases transitioning from 0.1 to 0.2 will no longer be able to use these APIs when they are fully transitioned to 0.2. Therefore, the compatibility runtime provides them to enable incremental transitions to the new APIs, but ideally, code using them should eventually be rewritten to use the new style. - In order to implement idleness tracking on the compatibility runtimes, it
is necessary to override the behavior of
tokio::spawn
. This is possible in Tokio 0.1, usingexecutor::with_default
, so we are able to track idleness of futures spawned via 0.1'stokio::spawn
. However, Tokio 0.2 does not allow overriding spawn's behavior, so we are not able to track the idleness of futures spawned by 0.2'stokio::spawn
. Therefore, in order to provide a consistent API,tokio-compat
makes a distinction between tasks spawned with and withoutJoinHandle
s.
For reference, spawning tasks via the following functions will count to
keep the runtime active in run
or shutdown_on_idle
:
Runtime::spawn
andcurrent_thread::Runtime::spawn
Runtime::spawn_std
andcurrent_thread::Runtime::spawn_std
TaskExecutor::spawn
andcurrent_thread::TaskExecutor::spawn_local
TaskExecutor::spawn_std
andcurrent_thread::TaskExecutor::spawn_local_std
current_thread::Handle::spawn
andcurrent_thread::Handle::spawn_std
- All implementations of
tokio
0.1'sExecutor
andTypedExecutor
traits for types defined intokio-compat
. tokio::spawn
from the 0.1 version oftokio
tokio
0.1'sDefaultExecutor
Meanwhile, the tasks spawned by the these functions will not count to
keep the runtime active, and return JoinHandle
s that must be await
ed
instead:
Runtime::spawn_handle
andcurrent_thread::Runtime::spawn_handle
Runtime::spawn_handle_std
andcurrent_thread::Runtime::spawn_handle_std
TaskExecutor::spawn_handle
andcurrent_thread::TaskExecutor::spawn_handle
TaskExecutor::spawn_handle
andcurrent_thread::TaskExecutor::spawn_handle_std
current_thread::Handle::spawn_handle
andcurrent_thread::Handle::spawn_handle_std
tokio::spawn
,tokio::task::spawn_local
, andtokio::task::spawn_blocking
from the 0.2 version oftokio
Blocking
The compatibility thread pool runtime does not currently support the
tokio
0.1 tokio_threadpool::blocking
API. Calls to the
legacy version of blocking
made on the compatibility runtime will currently
fail. In the future, tokio-compat
will allow transparently replacing
legacy blocking
with the tokio
0.2 blocking APIs, but in the meantime,
it will be necessary to convert this code to call into the tokio
0.2
task::block_in_place
and task::spawn_blocking
APIs instead.
Examples
Spawning both tokio
0.1 and tokio
0.2 futures:
use futures_01::future::lazy; tokio_compat::run(lazy(|| { // spawn a `futures` 0.1 future using the `spawn` function from the // `tokio` 0.1 crate: tokio_01::spawn(lazy(|| { println!("hello from tokio 0.1!"); Ok(()) })); // spawn an `async` block future on the same runtime using `tokio` // 0.2's `spawn`: tokio_02::spawn(async { println!("hello from tokio 0.2!"); }); Ok(()) }))
Futures on the compat runtime can use timer
APIs from both 0.1 and 0.2
versions of tokio
:
use tokio_compat::prelude::*; tokio_compat::run_std(async { // Wait for a `tokio` 0.1 `Delay`... let when = Instant::now() + Duration::from_millis(10); tokio_01::timer::Delay::new(when) // convert the delay future into a `std::future` that we can `await`. .compat() .await .expect("tokio 0.1 timer should work!"); println!("10 ms have elapsed"); // Wait for a `tokio` 0.2 `Delay`... tokio_02::time::delay_for(Duration::from_millis(20)).await; println!("20 ms have elapsed"); });
Modules
current_thread | feature="rt-current-thread" or feature="rt-full" A compatibility implementation that runs everything on the current thread. |
Structs
Builder | (feature="rt-current-thread" or feature="rt-full" ) and feature="rt-full" Builds a compatibility runtime with custom configuration values. |
Runtime | (feature="rt-current-thread" or feature="rt-full" ) and feature="rt-full" A thread pool runtime that can run tasks that use both |
TaskExecutor | (feature="rt-current-thread" or feature="rt-full" ) and feature="rt-full" Executes futures on the runtime |
Functions
run | (feature="rt-current-thread" or feature="rt-full" ) and feature="rt-full" Start the Tokio runtime using the supplied |
run_std | (feature="rt-current-thread" or feature="rt-full" ) and feature="rt-full" Start the Tokio runtime using the supplied |