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(tokio_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 (tokio_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 | pub use self::builder::UnhandledPanic; |
230 | pub use crate::util::rand::RngSeed; |
231 | } |
232 | |
233 | cfg_taskdump! { |
234 | pub mod dump; |
235 | pub use dump::Dump; |
236 | } |
237 | |
238 | mod handle; |
239 | pub use handle::{EnterGuard, Handle, TryCurrentError}; |
240 | |
241 | mod runtime; |
242 | pub use runtime::{Runtime, RuntimeFlavor}; |
243 | |
244 | mod thread_id; |
245 | pub(crate) use thread_id::ThreadId; |
246 | |
247 | cfg_metrics! { |
248 | mod metrics; |
249 | pub use metrics::{RuntimeMetrics, HistogramScale}; |
250 | |
251 | pub(crate) use metrics::{MetricsBatch, SchedulerMetrics, WorkerMetrics, HistogramBuilder}; |
252 | |
253 | cfg_net! { |
254 | pub(crate) use metrics::IoDriverMetrics; |
255 | } |
256 | } |
257 | |
258 | cfg_not_metrics! { |
259 | pub(crate) mod metrics; |
260 | pub(crate) use metrics::{SchedulerMetrics, WorkerMetrics, MetricsBatch, HistogramBuilder}; |
261 | } |
262 | |
263 | /// After thread starts / before thread stops |
264 | type Callback = std::sync::Arc<dyn Fn() + Send + Sync>; |
265 | } |
266 | |