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
//! A compatibility implementation that runs everything on the current thread.
//!
//! [`current_thread::Runtime`][rt] is similar to the primary
//! [compatibility `Runtime`][concurrent-rt] except that it runs all components
//! on the current  thread instead of using a thread pool. This means that it is
//! able to spawn futures that do not implement `Send`.
//!
//! Same as the default [`current_thread::Runtime`][default-rt] in the main
//! `tokio` crate, the [`tokio_compat::current_thread::Runtime`][rt] includes:
//!
//! * A [reactor] to drive I/O resources.
//! * An [executor] to execute tasks that use these I/O resources.
//! * A [timer] for scheduling work to run after a set period of time.
//!
//! Unlike the default `current_thread::Runtime`, however, the `tokio_compat`
//! version must spawn an additional background thread to run the `tokio` 0.1
//! [`Reactor`][reactor-01] and [`Timer`][timer-01]. This is necessary to
//! support legacy tasks, as the main thread is already running a `tokio` 0.2
//! `Reactor` and `Timer`.
//!
//! Note that [`current_thread::Runtime`][rt] does not implement `Send` itself
//! and cannot be safely moved to other threads
//!
//! # Spawning from other threads
//!
//! While [`current_thread::Runtime`][rt] does not implement `Send` and cannot
//! safely be moved to other threads, it provides a `Handle` that can be sent
//! to other threads and allows to spawn new tasks from there.
//!
//! For example:
//!
//! ```
//! use tokio_compat::runtime::current_thread::Runtime;
//! use std::thread;
//!
//! let runtime = Runtime::new().unwrap();
//! let handle = runtime.handle();
//!
//! thread::spawn(move || {
//!     // Spawn a `futures` 0.1 task on the other thread's runtime.
//!     let _ = handle.spawn(futures_01::future::lazy(|| {
//!         println!("hello from futures 0.1!");
//!         Ok(())
//!     }));
//!
//!     // Spawn a `std::future` task on the other thread's runtime.
//!     let _ = handle.spawn_std(async {
//!         println!("hello from std::future!");
//!     });
//! }).join().unwrap();
//! ```
//!
//! # Examples
//!
//! Creating a new `Runtime` and running a future `f` until its completion and
//! returning its result.
//!
//! ```
//! use tokio_compat::runtime::current_thread::Runtime;
//!
//! let runtime = Runtime::new().unwrap();
//!
//! // Use the runtime...
//! // runtime.block_on(f); // where f is a future
//! ```
//!
//! [rt]: struct.Runtime.html
//! [concurrent-rt]: ../struct.Runtime.html
//! [default-rt]:
//!     https://docs.rs/tokio/0.2.4/tokio/runtime/current_thread/struct.Runtime.html
//! [chan]: https://docs.rs/futures/0.1/futures/sync/mpsc/fn.channel.html
//! [reactor]: ../../reactor/struct.Reactor.html
//! [executor]: https://tokio.rs/docs/internals/runtime-model/#executors
//! [timer]: ../../timer/index.html
//! [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
use super::{compat, idle};

mod builder;
mod runtime;
mod task_executor;

pub use self::builder::Builder;
pub use self::runtime::{Handle, RunError, Runtime};
pub use self::task_executor::TaskExecutor;

use futures_01::future::Future as Future01;
use futures_util::compat::Future01CompatExt;
use std::future::Future;

/// Run the provided `futures` 0.1 future to completion using a runtime running on the current thread.
///
/// This first creates a new [`Runtime`], and calls [`Runtime::block_on`] with the provided future,
/// which blocks the current thread until the provided future completes. It then calls
/// [`Runtime::run`] to wait for any other spawned futures to resolve.
#[cfg_attr(docsrs, doc(cfg(feature = "rt-current-thread")))]
pub fn block_on_all<F>(future: F) -> Result<F::Item, F::Error>
where
    F: Future01,
{
    block_on_all_std(future.compat())
}

/// Run the provided `std::future` future to completion using a runtime running on the current thread.
///
/// This first creates a new [`Runtime`], and calls [`Runtime::block_on`] with the provided future,
/// which blocks the current thread until the provided future completes. It then calls
/// [`Runtime::run`] to wait for any other spawned futures to resolve.
#[cfg_attr(docsrs, doc(cfg(feature = "rt-current-thread")))]
pub fn block_on_all_std<F>(future: F) -> F::Output
where
    F: Future,
{
    let mut r = Runtime::new().expect("failed to start runtime on current thread");
    let v = r.block_on_std(future);
    r.run().expect("failed to resolve remaining futures");
    v
}

/// Start a current-thread runtime using the supplied `futures` 0.1 future to bootstrap execution.
///
/// # Panics
///
/// This function panics if called from the context of an executor.
#[cfg_attr(docsrs, doc(cfg(feature = "rt-current-thread")))]
pub fn run<F>(future: F)
where
    F: Future01<Item = (), Error = ()> + 'static,
{
    let mut r = Runtime::new().expect("failed to start runtime on current thread");
    r.spawn(future);
    r.run().expect("failed to resolve remaining futures");
}

/// Start a current-thread runtime using the supplied `std::future` ture to bootstrap execution.
///
/// # Panics
///
/// This function panics if called from the context of an executor.
#[cfg_attr(docsrs, doc(cfg(feature = "rt-current-thread")))]
pub fn run_std<F>(future: F)
where
    F: Future<Output = ()> + 'static,
{
    let mut r = Runtime::new().expect("failed to start runtime on current thread");
    r.block_on_std(future);
    r.run().expect("failed to resolve remaining futures");
}