| //! The Tokio runtime. |
| //! |
| //! Unlike other Rust programs, asynchronous applications require runtime |
| //! support. In particular, the following runtime services are necessary: |
| //! |
| //! * An **I/O event loop**, called the driver, which drives I/O resources and |
| //! dispatches I/O events to tasks that depend on them. |
| //! * A **scheduler** to execute [tasks] that use these I/O resources. |
| //! * A **timer** for scheduling work to run after a set period of time. |
| //! |
| //! Tokio's [`Runtime`] bundles all of these services as a single type, allowing |
| //! them to be started, shut down, and configured together. However, often it is |
| //! not required to configure a [`Runtime`] manually, and a user may just use the |
| //! [`tokio::main`] attribute macro, which creates a [`Runtime`] under the hood. |
| //! |
| //! # Usage |
| //! |
| //! When no fine tuning is required, the [`tokio::main`] attribute macro can be |
| //! used. |
| //! |
| //! ```no_run |
| //! use tokio::net::TcpListener; |
| //! use tokio::io::{AsyncReadExt, AsyncWriteExt}; |
| //! |
| //! #[tokio::main] |
| //! async fn main() -> Result<(), Box<dyn std::error::Error>> { |
| //! let listener = TcpListener::bind("127.0.0.1:8080").await?; |
| //! |
| //! loop { |
| //! let (mut socket, _) = listener.accept().await?; |
| //! |
| //! tokio::spawn(async move { |
| //! let mut buf = [0; 1024]; |
| //! |
| //! // In a loop, read data from the socket and write the data back. |
| //! loop { |
| //! let n = match socket.read(&mut buf).await { |
| //! // socket closed |
| //! Ok(n) if n == 0 => return, |
| //! Ok(n) => n, |
| //! Err(e) => { |
| //! println!("failed to read from socket; err = {:?}", e); |
| //! return; |
| //! } |
| //! }; |
| //! |
| //! // Write the data back |
| //! if let Err(e) = socket.write_all(&buf[0..n]).await { |
| //! println!("failed to write to socket; err = {:?}", e); |
| //! return; |
| //! } |
| //! } |
| //! }); |
| //! } |
| //! } |
| //! ``` |
| //! |
| //! 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. |
| //! |
| //! ```no_run |
| //! use tokio::net::TcpListener; |
| //! use tokio::io::{AsyncReadExt, AsyncWriteExt}; |
| //! use tokio::runtime::Runtime; |
| //! |
| //! fn main() -> Result<(), Box<dyn std::error::Error>> { |
| //! // Create the runtime |
| //! let rt = Runtime::new()?; |
| //! |
| //! // Spawn the root task |
| //! rt.block_on(async { |
| //! let listener = TcpListener::bind("127.0.0.1:8080").await?; |
| //! |
| //! loop { |
| //! let (mut socket, _) = listener.accept().await?; |
| //! |
| //! tokio::spawn(async move { |
| //! let mut buf = [0; 1024]; |
| //! |
| //! // In a loop, read data from the socket and write the data back. |
| //! loop { |
| //! let n = match socket.read(&mut buf).await { |
| //! // socket closed |
| //! Ok(n) if n == 0 => return, |
| //! Ok(n) => n, |
| //! Err(e) => { |
| //! println!("failed to read from socket; err = {:?}", e); |
| //! return; |
| //! } |
| //! }; |
| //! |
| //! // Write the data back |
| //! if let Err(e) = socket.write_all(&buf[0..n]).await { |
| //! println!("failed to write to socket; err = {:?}", e); |
| //! return; |
| //! } |
| //! } |
| //! }); |
| //! } |
| //! }) |
| //! } |
| //! ``` |
| //! |
| //! ## Runtime Configurations |
| //! |
| //! Tokio provides multiple task scheduling strategies, suitable for different |
| //! applications. The [runtime builder] or `#[tokio::main]` attribute may be |
| //! used to select which scheduler to use. |
| //! |
| //! #### Multi-Thread Scheduler |
| //! |
| //! The multi-thread scheduler executes futures on a _thread pool_, using a |
| //! work-stealing strategy. By default, it will start a worker thread for each |
| //! CPU core available on the system. This tends to be the ideal configuration |
| //! for most applications. The multi-thread scheduler requires the `rt-multi-thread` |
| //! feature flag, and is selected by default: |
| //! ``` |
| //! use tokio::runtime; |
| //! |
| //! # fn main() -> Result<(), Box<dyn std::error::Error>> { |
| //! let threaded_rt = runtime::Runtime::new()?; |
| //! # Ok(()) } |
| //! ``` |
| //! |
| //! Most applications should use the multi-thread scheduler, except in some |
| //! niche use-cases, such as when running only a single thread is required. |
| //! |
| //! #### Current-Thread Scheduler |
| //! |
| //! The current-thread scheduler provides a _single-threaded_ future executor. |
| //! All tasks will be created and executed on the current thread. This requires |
| //! the `rt` feature flag. |
| //! ``` |
| //! use tokio::runtime; |
| //! |
| //! # fn main() -> Result<(), Box<dyn std::error::Error>> { |
| //! let rt = runtime::Builder::new_current_thread() |
| //! .build()?; |
| //! # Ok(()) } |
| //! ``` |
| //! |
| //! #### Resource drivers |
| //! |
| //! When configuring a runtime by hand, no resource drivers are enabled by |
| //! default. In this case, attempting to use networking types or time types will |
| //! fail. In order to enable these types, the resource drivers must be enabled. |
| //! This is done with [`Builder::enable_io`] and [`Builder::enable_time`]. As a |
| //! shorthand, [`Builder::enable_all`] enables both resource drivers. |
| //! |
| //! ## Lifetime of spawned threads |
| //! |
| //! The runtime may spawn threads depending on its configuration and usage. The |
| //! multi-thread scheduler spawns threads to schedule tasks and for `spawn_blocking` |
| //! calls. |
| //! |
| //! While the `Runtime` is active, threads may shut down after periods of being |
| //! idle. Once `Runtime` is dropped, all runtime threads have usually been |
| //! terminated, but in the presence of unstoppable spawned work are not |
| //! guaranteed to have been terminated. See the |
| //! [struct level documentation](Runtime#shutdown) for more details. |
| //! |
| //! [tasks]: crate::task |
| //! [`Runtime`]: Runtime |
| //! [`tokio::spawn`]: crate::spawn |
| //! [`tokio::main`]: ../attr.main.html |
| //! [runtime builder]: crate::runtime::Builder |
| //! [`Runtime::new`]: crate::runtime::Runtime::new |
| //! [`Builder::threaded_scheduler`]: crate::runtime::Builder::threaded_scheduler |
| //! [`Builder::enable_io`]: crate::runtime::Builder::enable_io |
| //! [`Builder::enable_time`]: crate::runtime::Builder::enable_time |
| //! [`Builder::enable_all`]: crate::runtime::Builder::enable_all |
| |
| // At the top due to macros |
| #[cfg(test)] |
| #[cfg(not(target_family = "wasm"))] |
| #[macro_use] |
| mod tests; |
| |
| pub(crate) mod context; |
| |
| pub(crate) mod coop; |
| |
| pub(crate) mod park; |
| |
| mod driver; |
| |
| pub(crate) mod scheduler; |
| |
| cfg_io_driver_impl! { |
| pub(crate) mod io; |
| } |
| |
| cfg_process_driver! { |
| mod process; |
| } |
| |
| cfg_time! { |
| pub(crate) mod time; |
| } |
| |
| cfg_signal_internal_and_unix! { |
| pub(crate) mod signal; |
| } |
| |
| cfg_rt! { |
| pub(crate) mod task; |
| |
| mod config; |
| use config::Config; |
| |
| mod blocking; |
| #[cfg_attr(target_os = "wasi", allow(unused_imports))] |
| pub(crate) use blocking::spawn_blocking; |
| |
| cfg_trace! { |
| pub(crate) use blocking::Mandatory; |
| } |
| |
| cfg_fs! { |
| pub(crate) use blocking::spawn_mandatory_blocking; |
| } |
| |
| mod builder; |
| pub use self::builder::Builder; |
| cfg_unstable! { |
| mod id; |
| #[cfg_attr(not(tokio_unstable), allow(unreachable_pub))] |
| pub use id::Id; |
| |
| pub use self::builder::UnhandledPanic; |
| pub use crate::util::rand::RngSeed; |
| } |
| |
| cfg_taskdump! { |
| pub mod dump; |
| pub use dump::Dump; |
| } |
| |
| mod handle; |
| pub use handle::{EnterGuard, Handle, TryCurrentError}; |
| |
| mod runtime; |
| pub use runtime::{Runtime, RuntimeFlavor}; |
| |
| mod thread_id; |
| pub(crate) use thread_id::ThreadId; |
| |
| cfg_metrics! { |
| mod metrics; |
| pub use metrics::{RuntimeMetrics, HistogramScale}; |
| |
| pub(crate) use metrics::{MetricsBatch, SchedulerMetrics, WorkerMetrics, HistogramBuilder}; |
| |
| cfg_net! { |
| pub(crate) use metrics::IoDriverMetrics; |
| } |
| } |
| |
| cfg_not_metrics! { |
| pub(crate) mod metrics; |
| pub(crate) use metrics::{SchedulerMetrics, WorkerMetrics, MetricsBatch, HistogramBuilder}; |
| } |
| |
| /// After thread starts / before thread stops |
| type Callback = std::sync::Arc<dyn Fn() + Send + Sync>; |
| } |