• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 shutdown after periods of being
160 //! idle. Once `Runtime` is dropped, all runtime threads are forcibly shutdown.
161 //! Any tasks that have not yet completed will be dropped.
162 //!
163 //! [tasks]: crate::task
164 //! [`Runtime`]: Runtime
165 //! [`tokio::spawn`]: crate::spawn
166 //! [`tokio::main`]: ../attr.main.html
167 //! [runtime builder]: crate::runtime::Builder
168 //! [`Runtime::new`]: crate::runtime::Runtime::new
169 //! [`Builder::threaded_scheduler`]: crate::runtime::Builder::threaded_scheduler
170 //! [`Builder::enable_io`]: crate::runtime::Builder::enable_io
171 //! [`Builder::enable_time`]: crate::runtime::Builder::enable_time
172 //! [`Builder::enable_all`]: crate::runtime::Builder::enable_all
173 
174 // At the top due to macros
175 #[cfg(test)]
176 #[cfg(not(tokio_wasm))]
177 #[macro_use]
178 mod tests;
179 
180 pub(crate) mod context;
181 
182 pub(crate) mod coop;
183 
184 pub(crate) mod park;
185 
186 mod driver;
187 
188 pub(crate) mod scheduler;
189 
190 cfg_io_driver_impl! {
191     pub(crate) mod io;
192 }
193 
194 cfg_process_driver! {
195     mod process;
196 }
197 
198 cfg_time! {
199     pub(crate) mod time;
200 }
201 
202 cfg_signal_internal_and_unix! {
203     pub(crate) mod signal;
204 }
205 
206 cfg_rt! {
207     pub(crate) mod task;
208 
209     mod config;
210     use config::Config;
211 
212     mod blocking;
213     #[cfg_attr(tokio_wasi, allow(unused_imports))]
214     pub(crate) use blocking::spawn_blocking;
215 
216     cfg_trace! {
217         pub(crate) use blocking::Mandatory;
218     }
219 
220     cfg_fs! {
221         pub(crate) use blocking::spawn_mandatory_blocking;
222     }
223 
224     mod builder;
225     pub use self::builder::Builder;
226     cfg_unstable! {
227         pub use self::builder::UnhandledPanic;
228         pub use crate::util::rand::RngSeed;
229     }
230 
231     mod defer;
232     pub(crate) use defer::Defer;
233 
234     mod handle;
235     pub use handle::{EnterGuard, Handle, TryCurrentError};
236 
237     mod runtime;
238     pub use runtime::{Runtime, RuntimeFlavor};
239 
240     mod thread_id;
241     pub(crate) use thread_id::ThreadId;
242 
243     cfg_metrics! {
244         mod metrics;
245         pub use metrics::RuntimeMetrics;
246 
247         pub(crate) use metrics::{MetricsBatch, SchedulerMetrics, WorkerMetrics};
248 
249         cfg_net! {
250         pub(crate) use metrics::IoDriverMetrics;
251         }
252     }
253 
254     cfg_not_metrics! {
255         pub(crate) mod metrics;
256         pub(crate) use metrics::{SchedulerMetrics, WorkerMetrics, MetricsBatch};
257     }
258 
259     /// After thread starts / before thread stops
260     type Callback = std::sync::Arc<dyn Fn() + Send + Sync>;
261 }
262