//! A batteries included runtime for applications using Tokio. //! //! Applications using Tokio require some runtime support in order to work: //! //! * A [reactor] to drive I/O resources. //! * An [executor] to execute tasks that use these I/O resources. //! //! While it is possible to setup each component manually, this involves a bunch //! of boilerplate. //! //! [`Runtime`] bundles all of these various runtime components into a single //! handle that can be started and shutdown together, eliminating the necessary //! boilerplate to run a Tokio application. //! //! Most applications wont need to use [`Runtime`] directly. Instead, they will //! use the [`run`] function, which uses [`Runtime`] under the hood. //! //! Creating a [`Runtime`] does the following: //! //! * Spawn a background thread running a [`Reactor`] instance. //! * Start a [`ThreadPool`] for executing futures. //! //! The thread pool uses a work-stealing strategy and is configured to start a //! worker thread for each CPU core available on the system. This tends to be //! the ideal setup for Tokio applications. //! //! # Usage //! //! Most applications will use the [`run`] function. This takes a future to //! "seed" the application, blocking the thread until the runtime becomes //! [idle]. //! //! ```rust //! # extern crate tokio; //! # extern crate futures; //! # use futures::{Future, Stream}; //! use tokio::net::TcpListener; //! //! # fn process(_: T) -> Box + Send> { //! # unimplemented!(); //! # } //! # fn dox() { //! # let addr = "127.0.0.1:8080".parse().unwrap(); //! let listener = TcpListener::bind(&addr).unwrap(); //! //! let server = listener.incoming() //! .map_err(|e| println!("error = {:?}", e)) //! .for_each(|socket| { //! tokio::spawn(process(socket)) //! }); //! //! tokio::run(server); //! # } //! # pub fn main() {} //! ``` //! //! In this function, the `run` function blocks until the runtime becomes idle. //! See [`shutdown_on_idle`][idle] for more shutdown details. //! //! From within the context of the runtime, additional tasks are spawned using //! the [`tokio::spawn`] function. Futures spawned using this function will be //! executed on the same thread pool used by the [`Runtime`]. //! //! A [`Runtime`] instance can also be used directly. //! //! ```rust //! # extern crate tokio; //! # extern crate futures; //! # use futures::{Future, Stream}; //! use tokio::runtime::Runtime; //! use tokio::net::TcpListener; //! //! # fn process(_: T) -> Box + Send> { //! # unimplemented!(); //! # } //! # fn dox() { //! # let addr = "127.0.0.1:8080".parse().unwrap(); //! let listener = TcpListener::bind(&addr).unwrap(); //! //! let server = listener.incoming() //! .map_err(|e| println!("error = {:?}", e)) //! .for_each(|socket| { //! tokio::spawn(process(socket)) //! }); //! //! // Create the runtime //! let mut rt = Runtime::new().unwrap(); //! //! // Spawn the server task //! rt.spawn(server); //! //! // Wait until the runtime becomes idle and shut it down. //! rt.shutdown_on_idle() //! .wait().unwrap(); //! # } //! # pub fn main() {} //! ``` //! //! [reactor]: ../reactor/struct.Reactor.html //! [executor]: https://tokio.rs/docs/getting-started/runtime-model/#executors //! [`Runtime`]: struct.Runtime.html //! [`ThreadPool`]: ../executor/thread_pool/struct.ThreadPool.html //! [`run`]: fn.run.html //! [idle]: struct.Runtime.html#method.shutdown_on_idle //! [`tokio::spawn`]: ../executor/fn.spawn.html use reactor::{Reactor, Handle, Background}; use tokio_threadpool::{self as threadpool, ThreadPool, Sender}; use futures::Poll; use futures::future::{self, Future}; use std::{fmt, io}; #[cfg(feature = "unstable-futures")] use futures2; /// Handle to the Tokio runtime. /// /// The Tokio runtime includes a reactor as well as an executor for running /// tasks. /// /// See [module level][mod] documentation for more details. /// /// [mod]: index.html #[derive(Debug)] pub struct Runtime { inner: Option, } /// Executes futures on the runtime /// /// All futures spawned using this executor will be submitted to the associated /// Runtime's executor. This executor is usually a thread pool. /// /// For more details, see the [module level](index.html) documentation. #[derive(Debug, Clone)] pub struct TaskExecutor { inner: Sender, } /// A future that resolves when the Tokio `Runtime` is shut down. pub struct Shutdown { inner: Box + Send>, } #[derive(Debug)] struct Inner { /// Reactor running on a background thread. reactor: Background, /// Task execution pool. pool: ThreadPool, } // ===== impl Runtime ===== /// Start the Tokio runtime using the supplied future to bootstrap execution. /// /// This function is used to bootstrap the execution of a Tokio application. It /// does the following: /// /// * Start the Tokio runtime using a default configuration. /// * Spawn the given future onto the thread pool. /// * Block the current thread until the runtime shuts down. /// /// Note that the function will not return immediately once `future` has /// completed. Instead it waits for the entire runtime to become idle. /// /// See the [module level][mod] documentation for more details. /// /// # Examples /// /// ```rust /// # extern crate tokio; /// # extern crate futures; /// # use futures::{Future, Stream}; /// use tokio::net::TcpListener; /// /// # fn process(_: T) -> Box + Send> { /// # unimplemented!(); /// # } /// # fn dox() { /// # let addr = "127.0.0.1:8080".parse().unwrap(); /// let listener = TcpListener::bind(&addr).unwrap(); /// /// let server = listener.incoming() /// .map_err(|e| println!("error = {:?}", e)) /// .for_each(|socket| { /// tokio::spawn(process(socket)) /// }); /// /// tokio::run(server); /// # } /// # pub fn main() {} /// ``` /// /// # Panics /// /// This function panics if called from the context of an executor. /// /// [mod]: ../index.html pub fn run(future: F) where F: Future + Send + 'static, { let mut runtime = Runtime::new().unwrap(); runtime.spawn(future); runtime.shutdown_on_idle().wait().unwrap(); } /// Start the Tokio runtime using the supplied future to bootstrap execution. /// /// Identical to `run` but works with futures 0.2-style futures. #[cfg(feature = "unstable-futures")] pub fn run2(future: F) where F: futures2::Future + Send + 'static, { let mut runtime = Runtime::new().unwrap(); runtime.spawn2(future); runtime.shutdown_on_idle().wait().unwrap(); } impl Runtime { /// Create a new runtime instance with default configuration values. /// /// See [module level][mod] documentation for more details. /// /// [mod]: index.html pub fn new() -> io::Result { // Spawn a reactor on a background thread. let reactor = Reactor::new()?.background()?; // Get a handle to the reactor. let handle = reactor.handle().clone(); let pool = threadpool::Builder::new() .name_prefix("tokio-runtime-worker-") .around_worker(move |w, enter| { ::tokio_reactor::with_default(&handle, enter, |_| { w.run(); }); }) .build(); Ok(Runtime { inner: Some(Inner { reactor, pool, }), }) } /// Return a reference to the reactor handle for this runtime instance. pub fn handle(&self) -> &Handle { self.inner().reactor.handle() } /// Return a handle to the runtime's executor. pub fn executor(&self) -> TaskExecutor { let inner = self.inner().pool.sender().clone(); TaskExecutor { inner } } /// Spawn a future onto the Tokio runtime. /// /// This spawns the given future onto the runtime's executor, usually a /// thread pool. The thread pool is then responsible for polling the future /// until it completes. /// /// See [module level][mod] documentation for more details. /// /// [mod]: index.html /// /// # Examples /// /// ```rust /// # extern crate tokio; /// # extern crate futures; /// # use futures::{future, Future, Stream}; /// use tokio::runtime::Runtime; /// /// # fn dox() { /// // Create the runtime /// let mut rt = Runtime::new().unwrap(); /// /// // Spawn a future onto the runtime /// rt.spawn(future::lazy(|| { /// println!("now running on a worker thread"); /// Ok(()) /// })); /// # } /// # pub fn main() {} /// ``` /// /// # Panics /// /// This function panics if the spawn fails. Failure occurs if the executor /// is currently at capacity and is unable to spawn a new future. pub fn spawn(&mut self, future: F) -> &mut Self where F: Future + Send + 'static, { self.inner_mut().pool.sender().spawn(future).unwrap(); self } /// Spawn a futures 0.2-style future onto the Tokio runtime. /// /// Otherwise identical to `spawn` #[cfg(feature = "unstable-futures")] pub fn spawn2(&mut self, future: F) -> &mut Self where F: futures2::Future + Send + 'static, { futures2::executor::Executor::spawn( self.inner_mut().pool.sender_mut(), Box::new(future) ).unwrap(); self } /// Signals the runtime to shutdown once it becomes idle. /// /// Returns a future that completes once the shutdown operation has /// completed. /// /// This function can be used to perform a graceful shutdown of the runtime. /// /// The runtime enters an idle state once **all** of the following occur. /// /// * The thread pool has no tasks to execute, i.e., all tasks that were /// spawned have completed. /// * The reactor is not managing any I/O resources. /// /// See [module level][mod] documentation for more details. /// /// [mod]: index.html pub fn shutdown_on_idle(mut self) -> Shutdown { let inner = self.inner.take().unwrap(); let inner = Box::new({ let pool = inner.pool; let reactor = inner.reactor; pool.shutdown_on_idle().and_then(|_| { reactor.shutdown_on_idle() }) }); Shutdown { inner } } /// Signals the runtime to shutdown immediately. /// /// Returns a future that completes once the shutdown operation has /// completed. /// /// This function will forcibly shutdown the runtime, causing any /// in-progress work to become canceled. The shutdown steps are: /// /// * Drain any scheduled work queues. /// * Drop any futures that have not yet completed. /// * Drop the reactor. /// /// Once the reactor has dropped, any outstanding I/O resources bound to /// that reactor will no longer function. Calling any method on them will /// result in an error. /// /// See [module level][mod] documentation for more details. /// /// [mod]: index.html pub fn shutdown_now(mut self) -> Shutdown { let inner = self.inner.take().unwrap(); Shutdown::shutdown_now(inner) } fn inner(&self) -> &Inner { self.inner.as_ref().unwrap() } fn inner_mut(&mut self) -> &mut Inner { self.inner.as_mut().unwrap() } } impl Drop for Runtime { fn drop(&mut self) { if let Some(inner) = self.inner.take() { let shutdown = Shutdown::shutdown_now(inner); let _ = shutdown.wait(); } } } // ===== impl TaskExecutor ===== impl TaskExecutor { /// Spawn a future onto the Tokio runtime. /// /// This spawns the given future onto the runtime's executor, usually a /// thread pool. The thread pool is then responsible for polling the future /// until it completes. /// /// See [module level][mod] documentation for more details. /// /// [mod]: index.html /// /// # Examples /// /// ```rust /// # extern crate tokio; /// # extern crate futures; /// # use futures::{future, Future, Stream}; /// use tokio::runtime::Runtime; /// /// # fn dox() { /// // Create the runtime /// let mut rt = Runtime::new().unwrap(); /// let executor = rt.executor(); /// /// // Spawn a future onto the runtime /// executor.spawn(future::lazy(|| { /// println!("now running on a worker thread"); /// Ok(()) /// })); /// # } /// # pub fn main() {} /// ``` /// /// # Panics /// /// This function panics if the spawn fails. Failure occurs if the executor /// is currently at capacity and is unable to spawn a new future. pub fn spawn(&self, future: F) where F: Future + Send + 'static, { self.inner.spawn(future).unwrap(); } } impl future::Executor for TaskExecutor where T: Future + Send + 'static, { fn execute(&self, future: T) -> Result<(), future::ExecuteError> { self.inner.execute(future) } } impl ::executor::Executor for TaskExecutor { fn spawn(&mut self, future: Box + Send>) -> Result<(), ::executor::SpawnError> { self.inner.spawn(future) } #[cfg(feature = "unstable-futures")] fn spawn2(&mut self, future: Box + Send>) -> Result<(), futures2::executor::SpawnError> { self.inner.spawn2(future) } } #[cfg(feature = "unstable-futures")] type Task2 = Box + Send>; #[cfg(feature = "unstable-futures")] impl futures2::executor::Executor for TaskExecutor { fn spawn(&mut self, f: Task2) -> Result<(), futures2::executor::SpawnError> { futures2::executor::Executor::spawn(&mut self.inner, f) } fn status(&self) -> Result<(), futures2::executor::SpawnError> { futures2::executor::Executor::status(&self.inner) } } // ===== impl Shutdown ===== impl Shutdown { fn shutdown_now(inner: Inner) -> Self { let inner = Box::new({ let pool = inner.pool; let reactor = inner.reactor; pool.shutdown_now().and_then(|_| { reactor.shutdown_now() .then(|_| { Ok(()) }) }) }); Shutdown { inner } } } impl Future for Shutdown { type Item = (); type Error = (); fn poll(&mut self) -> Poll<(), ()> { try_ready!(self.inner.poll()); Ok(().into()) } } impl fmt::Debug for Shutdown { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { fmt.debug_struct("Shutdown") .field("inner", &"Box>") .finish() } }