1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
//! 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][futures-compat] 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.1 [`Reactor`][reactor-01] and
//!   [`Timer`][timer-01] 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`][on_idle_01] and [`run`][run_01] 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 a `futures` 0.1 future, and does not return a
//!   `JoinHandle` (like `tokio` 0.1).
//! * [`Runtime::spawn_std`] spawns a `std::future` future, and does not return
//!   a `JoinHandle`.
//! * [`Runtime::spawn_handle`] spawns a `futures` 0.1 future, and returns a
//!   `JoinHandle`.
//! * [`Runtime::spawn_handle_std`] spawns a `std::future` future, and returns a
//!   `JoinHandle` (like `tokio` 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:
//!
//! 1. The `shutdown_on_idle` and `run` methods no longer exist in `tokio` 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.
//! 2. 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, using [`executor::with_default`], so we are able to track
//!    idleness of futures spawned via 0.1's `tokio::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's `tokio::spawn`. Therefore,
//!    in order to provide a consistent API, `tokio-compat` makes a distinction
//!    between tasks spawned with and without `JoinHandle`s.
//!
//! For reference, spawning tasks via the following functions **will** count to
//! keep the runtime active in `run` or `shutdown_on_idle`:
//!
//! * [`Runtime::spawn`] and [`current_thread::Runtime::spawn`]
//! * [`Runtime::spawn_std`] and [`current_thread::Runtime::spawn_std`]
//! * [`TaskExecutor::spawn`] and [`current_thread::TaskExecutor::spawn_local`]
//! * [`TaskExecutor::spawn_std`] and [`current_thread::TaskExecutor::spawn_local_std`]
//! * [`current_thread::Handle::spawn`] and [`current_thread::Handle::spawn_std`]
//! * All implementations of `tokio` 0.1's [`Executor`] and [`TypedExecutor`]
//!   traits for types defined in `tokio-compat`.
//! * [`tokio::spawn`][spawn_01] **from the 0.1 version of `tokio`**
//! * `tokio` 0.1's [`DefaultExecutor`]
//!
//! 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`] and [`current_thread::Runtime::spawn_handle`]
//! * [`Runtime::spawn_handle_std`] and [`current_thread::Runtime::spawn_handle_std`]
//! * [`TaskExecutor::spawn_handle`] and [`current_thread::TaskExecutor::spawn_handle`]
//! * [`TaskExecutor::spawn_handle`] and [`current_thread::TaskExecutor::spawn_handle_std`]
//! * [`current_thread::Handle::spawn_handle`] and [`current_thread::Handle::spawn_handle_std`]
//! * [`tokio::spawn`][spawn_02], [`tokio::task::spawn_local`], and
//!   [`tokio::task::spawn_blocking`] **from the 0.2 version of `tokio`**
//!
//! [`JoinHandle`]: https://docs.rs/tokio/0.2.4/tokio/task/struct.JoinHandle.html
//! [`Runtime::spawn`]: struct.Runtime.html#method.spawn
//! [`Runtime::spawn_std`]: struct.Runtime.html#method.spawn_std
//! [`Runtime::spawn_handle`]: struct.Runtime.html#method.spawn_handle
//! [`Runtime::spawn_handle_std`]: struct.Runtime.html#method.spawn_handle_std
//! [`TaskExecutor`]: struct.TaskExecutor.html
//! [`TaskExecutor::spawn`]: struct.TaskExecutor.html#method.spawn
//! [`TaskExecutor::spawn_std`]: struct.TaskExecutor.html#method.spawn_std
//! [`TaskExecutor::spawn_handle`]: struct.TaskExecutor.html#method.spawn_handle
//! [`current_thread::Runtime::spawn`]: current_thread/struct.Runtime.html#method.spawn
//! [`current_thread::Runtime::spawn_std`]: current_thread/struct.Runtime.html#method.spawn_std
//! [`current_thread::Runtime::spawn_handle`]: current_thread/struct.Runtime.html#method.spawn_handle
//! [`current_thread::Runtime::spawn_handle_std`]: current_thread/struct.Runtime.html#method.spawn_handle_std
//! [`current_thread::TaskExecutor::spawn_local`]: current_thread/struct.TaskExecutor.html#method.spawn_local_std
//! [`current_thread::TaskExecutor::spawn_local_std`]: current_thread/struct.TaskExecutor.html#method.spawn_local_std
//! [`current_thread::TaskExecutor::spawn_handle`]: current_thread/struct.TaskExecutor.html#method.spawn_handle
//! [`current_thread::TaskExecutor::spawn_handle_std`]: current_thread/struct.TaskExecutor.html#method.spawn_handle_std
//! [`current_thread::Handle::spawn`]: current_thread/struct.Handle.html#method.spawn
//! [`current_thread::Handle::spawn_std`]: current_thread/struct.Handle.html#method.spawn_std
//! [`current_thread::Handle::spawn_handle`]: current_thread/struct.Handle.html#method.spawn_handle
//! [`current_thread::Handle::spawn_handle_std`]: current_thread/struct.Handle.html#method.spawn_handle_std
//! [`Executor`]: https://docs.rs/tokio/0.1.22/tokio/executor/trait.Executor.html
//! [`TypedExecutor`]: https://docs.rs/tokio/0.1.22/tokio/executor/trait.TypedExecutor.html
//! [`DefaultExecutor`]:  https://docs.rs/tokio/0.1.22/tokio/executor/struct.DefaultExecutor.html
//! [spawn_01]: https://docs.rs/tokio/0.1.22/tokio/executor/fn.spawn.html
//! [spawn_02]: https://docs.rs/tokio/0.2.4/tokio/fn.spawn.html
//! [run_01]: https://docs.rs/tokio/0.1.22/tokio/runtime/current_thread/struct.Runtime.html#method.run.html
//! [on_idle_01]: https://docs.rs/tokio/0.1.22/tokio/runtime/struct.Runtime.html#method.shutdown_on_idle.html
//! [`tokio::task::spawn_local`]: https://docs.rs/tokio/0.2.4/tokio/task/fn.spawn_local.html
//! [`tokio::task::spawn_blocking`]: https://docs.rs/tokio/0.2.4/tokio/task/fn.spawn_blocking.html
//! [`executor::with_default`]: https://docs.rs/tokio-executor/0.1.9/tokio_executor/fn.with_default.html
//!
//! ### Blocking
//!
//! The compatibility thread pool runtime does **not** currently support the
//! `tokio` 0.1 [`tokio_threadpool::blocking`][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.
//!
//! [blocking]: https://docs.rs/tokio-threadpool/0.1.16/tokio_threadpool/fn.blocking.html
//! [`task::block_in_place`]: https://docs.rs/tokio/0.2.4/tokio/task/fn.block_in_place.html
//! [`task::spawn_blocking`]: https://docs.rs/tokio/0.2.4/tokio/task/fn.spawn_blocking.html
//!
//! ## Examples
//!
//! Spawning both `tokio` 0.1 and `tokio` 0.2 futures:
//!
//! ```rust
//! 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`:
//!
//! ```rust
//! # use std::time::{Duration, Instant};
//! 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");
//! });
//! ```
//!
//! [`tokio::runtime`]: https://docs.rs/tokio/0.2.4/tokio/runtime/index.html
//! [futures-compat]: https://rust-lang-nursery.github.io/futures-api-docs/0.3.0-alpha.19/futures/compat/index.html
//! [`Runtime`]: struct.Runtime.html
//! [resource drivers]: https://docs.rs/tokio/0.2.4/tokio/runtime/index.html#resource-drivers
//! [thread pool]: https://docs.rs/tokio/0.2.4/tokio/runtime/index.html#threaded-scheduler
//! [timer-01]: https://docs.rs/tokio/0.1.22/tokio/timer/index.html
//! [reactor-01]: https://docs.rs/tokio/0.1.22/tokio/reactor/struct.Reactor.html
//! [`run`]: struct.Runtime.html#method.run
//! [`spawn`]: struct.Runtime.html#method.spawn
//! [`block_on`]: struct.Runtime.html#method.block_on
//! [`run_std`]: struct.Runtime.html#method.run_std
//! [`spawn_std`]: struct.Runtime.html#method.spawn_std
//! [`block_on_std`]: struct.Runtime.html#method.spawn_std
mod compat;
#[cfg(feature = "rt-current-thread")]
pub mod current_thread;
mod idle;
#[cfg(feature = "rt-full")]
mod threadpool;

#[cfg(feature = "rt-full")]
pub use threadpool::{run, run_std, Builder, Runtime, TaskExecutor};