1 //! The Tokio runtime. 2 //! 3 //! Unlike other Rust programs, asynchronous applications require runtime 4 //! support. In particular, the following runtime services are necessary: 5 //! 6 //! * An **I/O event loop**, called the driver, which drives I/O resources and 7 //! dispatches I/O events to tasks that depend on them. 8 //! * A **scheduler** to execute [tasks] that use these I/O resources. 9 //! * A **timer** for scheduling work to run after a set period of time. 10 //! 11 //! Tokio's [`Runtime`] bundles all of these services as a single type, allowing 12 //! them to be started, shut down, and configured together. However, often it is 13 //! not required to configure a [`Runtime`] manually, and a user may just use the 14 //! [`tokio::main`] attribute macro, which creates a [`Runtime`] under the hood. 15 //! 16 //! # Usage 17 //! 18 //! When no fine tuning is required, the [`tokio::main`] attribute macro can be 19 //! used. 20 //! 21 //! ```no_run 22 //! use tokio::net::TcpListener; 23 //! use tokio::io::{AsyncReadExt, AsyncWriteExt}; 24 //! 25 //! #[tokio::main] 26 //! async fn main() -> Result<(), Box<dyn std::error::Error>> { 27 //! let listener = TcpListener::bind("127.0.0.1:8080").await?; 28 //! 29 //! loop { 30 //! let (mut socket, _) = listener.accept().await?; 31 //! 32 //! tokio::spawn(async move { 33 //! let mut buf = [0; 1024]; 34 //! 35 //! // In a loop, read data from the socket and write the data back. 36 //! loop { 37 //! let n = match socket.read(&mut buf).await { 38 //! // socket closed 39 //! Ok(n) if n == 0 => return, 40 //! Ok(n) => n, 41 //! Err(e) => { 42 //! println!("failed to read from socket; err = {:?}", e); 43 //! return; 44 //! } 45 //! }; 46 //! 47 //! // Write the data back 48 //! if let Err(e) = socket.write_all(&buf[0..n]).await { 49 //! println!("failed to write to socket; err = {:?}", e); 50 //! return; 51 //! } 52 //! } 53 //! }); 54 //! } 55 //! } 56 //! ``` 57 //! 58 //! From within the context of the runtime, additional tasks are spawned using 59 //! the [`tokio::spawn`] function. Futures spawned using this function will be 60 //! executed on the same thread pool used by the [`Runtime`]. 61 //! 62 //! A [`Runtime`] instance can also be used directly. 63 //! 64 //! ```no_run 65 //! use tokio::net::TcpListener; 66 //! use tokio::io::{AsyncReadExt, AsyncWriteExt}; 67 //! use tokio::runtime::Runtime; 68 //! 69 //! fn main() -> Result<(), Box<dyn std::error::Error>> { 70 //! // Create the runtime 71 //! let rt = Runtime::new()?; 72 //! 73 //! // Spawn the root task 74 //! rt.block_on(async { 75 //! let listener = TcpListener::bind("127.0.0.1:8080").await?; 76 //! 77 //! loop { 78 //! let (mut socket, _) = listener.accept().await?; 79 //! 80 //! tokio::spawn(async move { 81 //! let mut buf = [0; 1024]; 82 //! 83 //! // In a loop, read data from the socket and write the data back. 84 //! loop { 85 //! let n = match socket.read(&mut buf).await { 86 //! // socket closed 87 //! Ok(n) if n == 0 => return, 88 //! Ok(n) => n, 89 //! Err(e) => { 90 //! println!("failed to read from socket; err = {:?}", e); 91 //! return; 92 //! } 93 //! }; 94 //! 95 //! // Write the data back 96 //! if let Err(e) = socket.write_all(&buf[0..n]).await { 97 //! println!("failed to write to socket; err = {:?}", e); 98 //! return; 99 //! } 100 //! } 101 //! }); 102 //! } 103 //! }) 104 //! } 105 //! ``` 106 //! 107 //! ## Runtime Configurations 108 //! 109 //! Tokio provides multiple task scheduling strategies, suitable for different 110 //! applications. The [runtime builder] or `#[tokio::main]` attribute may be 111 //! used to select which scheduler to use. 112 //! 113 //! #### Multi-Thread Scheduler 114 //! 115 //! The multi-thread scheduler executes futures on a _thread pool_, using a 116 //! work-stealing strategy. By default, it will start a worker thread for each 117 //! CPU core available on the system. This tends to be the ideal configuration 118 //! for most applications. The multi-thread scheduler requires the `rt-multi-thread` 119 //! feature flag, and is selected by default: 120 //! ``` 121 //! use tokio::runtime; 122 //! 123 //! # fn main() -> Result<(), Box<dyn std::error::Error>> { 124 //! let threaded_rt = runtime::Runtime::new()?; 125 //! # Ok(()) } 126 //! ``` 127 //! 128 //! Most applications should use the multi-thread scheduler, except in some 129 //! niche use-cases, such as when running only a single thread is required. 130 //! 131 //! #### Current-Thread Scheduler 132 //! 133 //! The current-thread scheduler provides a _single-threaded_ future executor. 134 //! All tasks will be created and executed on the current thread. This requires 135 //! the `rt` feature flag. 136 //! ``` 137 //! use tokio::runtime; 138 //! 139 //! # fn main() -> Result<(), Box<dyn std::error::Error>> { 140 //! let rt = runtime::Builder::new_current_thread() 141 //! .build()?; 142 //! # Ok(()) } 143 //! ``` 144 //! 145 //! #### Resource drivers 146 //! 147 //! When configuring a runtime by hand, no resource drivers are enabled by 148 //! default. In this case, attempting to use networking types or time types will 149 //! fail. In order to enable these types, the resource drivers must be enabled. 150 //! This is done with [`Builder::enable_io`] and [`Builder::enable_time`]. As a 151 //! shorthand, [`Builder::enable_all`] enables both resource drivers. 152 //! 153 //! ## Lifetime of spawned threads 154 //! 155 //! The runtime may spawn threads depending on its configuration and usage. The 156 //! multi-thread scheduler spawns threads to schedule tasks and for `spawn_blocking` 157 //! calls. 158 //! 159 //! While the `Runtime` is active, threads may shut down after periods of being 160 //! idle. Once `Runtime` is dropped, all runtime threads have usually been 161 //! terminated, but in the presence of unstoppable spawned work are not 162 //! guaranteed to have been terminated. See the 163 //! [struct level documentation](Runtime#shutdown) for more details. 164 //! 165 //! [tasks]: crate::task 166 //! [`Runtime`]: Runtime 167 //! [`tokio::spawn`]: crate::spawn 168 //! [`tokio::main`]: ../attr.main.html 169 //! [runtime builder]: crate::runtime::Builder 170 //! [`Runtime::new`]: crate::runtime::Runtime::new 171 //! [`Builder::threaded_scheduler`]: crate::runtime::Builder::threaded_scheduler 172 //! [`Builder::enable_io`]: crate::runtime::Builder::enable_io 173 //! [`Builder::enable_time`]: crate::runtime::Builder::enable_time 174 //! [`Builder::enable_all`]: crate::runtime::Builder::enable_all 175 176 // At the top due to macros 177 #[cfg(test)] 178 #[cfg(not(target_family = "wasm"))] 179 #[macro_use] 180 mod tests; 181 182 pub(crate) mod context; 183 184 pub(crate) mod coop; 185 186 pub(crate) mod park; 187 188 mod driver; 189 190 pub(crate) mod scheduler; 191 192 cfg_io_driver_impl! { 193 pub(crate) mod io; 194 } 195 196 cfg_process_driver! { 197 mod process; 198 } 199 200 cfg_time! { 201 pub(crate) mod time; 202 } 203 204 cfg_signal_internal_and_unix! { 205 pub(crate) mod signal; 206 } 207 208 cfg_rt! { 209 pub(crate) mod task; 210 211 mod config; 212 use config::Config; 213 214 mod blocking; 215 #[cfg_attr(target_os = "wasi", allow(unused_imports))] 216 pub(crate) use blocking::spawn_blocking; 217 218 cfg_trace! { 219 pub(crate) use blocking::Mandatory; 220 } 221 222 cfg_fs! { 223 pub(crate) use blocking::spawn_mandatory_blocking; 224 } 225 226 mod builder; 227 pub use self::builder::Builder; 228 cfg_unstable! { 229 mod id; 230 #[cfg_attr(not(tokio_unstable), allow(unreachable_pub))] 231 pub use id::Id; 232 233 pub use self::builder::UnhandledPanic; 234 pub use crate::util::rand::RngSeed; 235 } 236 237 cfg_taskdump! { 238 pub mod dump; 239 pub use dump::Dump; 240 } 241 242 mod handle; 243 pub use handle::{EnterGuard, Handle, TryCurrentError}; 244 245 mod runtime; 246 pub use runtime::{Runtime, RuntimeFlavor}; 247 248 mod thread_id; 249 pub(crate) use thread_id::ThreadId; 250 251 cfg_metrics! { 252 mod metrics; 253 pub use metrics::{RuntimeMetrics, HistogramScale}; 254 255 pub(crate) use metrics::{MetricsBatch, SchedulerMetrics, WorkerMetrics, HistogramBuilder}; 256 257 cfg_net! { 258 pub(crate) use metrics::IoDriverMetrics; 259 } 260 } 261 262 cfg_not_metrics! { 263 pub(crate) mod metrics; 264 pub(crate) use metrics::{SchedulerMetrics, WorkerMetrics, MetricsBatch, HistogramBuilder}; 265 } 266 267 /// After thread starts / before thread stops 268 type Callback = std::sync::Arc<dyn Fn() + Send + Sync>; 269 } 270