1 #![doc(html_root_url = "https://docs.rs/tokio-macros/1.1.0")]
2 #![allow(clippy::needless_doctest_main)]
3 #![warn(
4 missing_debug_implementations,
5 missing_docs,
6 rust_2018_idioms,
7 unreachable_pub
8 )]
9 #![cfg_attr(docsrs, deny(broken_intra_doc_links))]
10 #![doc(test(
11 no_crate_inject,
12 attr(deny(warnings, rust_2018_idioms), allow(dead_code, unused_variables))
13 ))]
14
15 //! Macros for use with Tokio
16
17 // This `extern` is required for older `rustc` versions but newer `rustc`
18 // versions warn about the unused `extern crate`.
19 #[allow(unused_extern_crates)]
20 extern crate proc_macro;
21
22 mod entry;
23 mod select;
24
25 use proc_macro::TokenStream;
26
27 /// Marks async function to be executed by the selected runtime. This macro
28 /// helps set up a `Runtime` without requiring the user to use
29 /// [Runtime](../tokio/runtime/struct.Runtime.html) or
30 /// [Builder](../tokio/runtime/struct.Builder.html) directly.
31 ///
32 /// Note: This macro is designed to be simplistic and targets applications that
33 /// do not require a complex setup. If the provided functionality is not
34 /// sufficient, you may be interested in using
35 /// [Builder](../tokio/runtime/struct.Builder.html), which provides a more
36 /// powerful interface.
37 ///
38 /// Note: This macro can be used on any function and not just the `main`
39 /// function. Using it on a non-main function makes the function behave as if it
40 /// was synchronous by starting a new runtime each time it is called. If the
41 /// function is called often, it is preferable to create the runtime using the
42 /// runtime builder so the runtime can be reused across calls.
43 ///
44 /// # Multi-threaded runtime
45 ///
46 /// To use the multi-threaded runtime, the macro can be configured using
47 ///
48 /// ```
49 /// #[tokio::main(flavor = "multi_thread", worker_threads = 10)]
50 /// # async fn main() {}
51 /// ```
52 ///
53 /// The `worker_threads` option configures the number of worker threads, and
54 /// defaults to the number of cpus on the system. This is the default flavor.
55 ///
56 /// Note: The multi-threaded runtime requires the `rt-multi-thread` feature
57 /// flag.
58 ///
59 /// # Current thread runtime
60 ///
61 /// To use the single-threaded runtime known as the `current_thread` runtime,
62 /// the macro can be configured using
63 ///
64 /// ```
65 /// #[tokio::main(flavor = "current_thread")]
66 /// # async fn main() {}
67 /// ```
68 ///
69 /// ## Function arguments:
70 ///
71 /// Arguments are allowed for any functions aside from `main` which is special
72 ///
73 /// ## Usage
74 ///
75 /// ### Using the multi-thread runtime
76 ///
77 /// ```rust
78 /// #[tokio::main]
79 /// async fn main() {
80 /// println!("Hello world");
81 /// }
82 /// ```
83 ///
84 /// Equivalent code not using `#[tokio::main]`
85 ///
86 /// ```rust
87 /// fn main() {
88 /// tokio::runtime::Builder::new_multi_thread()
89 /// .enable_all()
90 /// .build()
91 /// .unwrap()
92 /// .block_on(async {
93 /// println!("Hello world");
94 /// })
95 /// }
96 /// ```
97 ///
98 /// ### Using current thread runtime
99 ///
100 /// The basic scheduler is single-threaded.
101 ///
102 /// ```rust
103 /// #[tokio::main(flavor = "current_thread")]
104 /// async fn main() {
105 /// println!("Hello world");
106 /// }
107 /// ```
108 ///
109 /// Equivalent code not using `#[tokio::main]`
110 ///
111 /// ```rust
112 /// fn main() {
113 /// tokio::runtime::Builder::new_current_thread()
114 /// .enable_all()
115 /// .build()
116 /// .unwrap()
117 /// .block_on(async {
118 /// println!("Hello world");
119 /// })
120 /// }
121 /// ```
122 ///
123 /// ### Set number of worker threads
124 ///
125 /// ```rust
126 /// #[tokio::main(worker_threads = 2)]
127 /// async fn main() {
128 /// println!("Hello world");
129 /// }
130 /// ```
131 ///
132 /// Equivalent code not using `#[tokio::main]`
133 ///
134 /// ```rust
135 /// fn main() {
136 /// tokio::runtime::Builder::new_multi_thread()
137 /// .worker_threads(2)
138 /// .enable_all()
139 /// .build()
140 /// .unwrap()
141 /// .block_on(async {
142 /// println!("Hello world");
143 /// })
144 /// }
145 /// ```
146 ///
147 /// ### Configure the runtime to start with time paused
148 ///
149 /// ```rust
150 /// #[tokio::main(flavor = "current_thread", start_paused = true)]
151 /// async fn main() {
152 /// println!("Hello world");
153 /// }
154 /// ```
155 ///
156 /// Equivalent code not using `#[tokio::main]`
157 ///
158 /// ```rust
159 /// fn main() {
160 /// tokio::runtime::Builder::new_current_thread()
161 /// .enable_all()
162 /// .start_paused(true)
163 /// .build()
164 /// .unwrap()
165 /// .block_on(async {
166 /// println!("Hello world");
167 /// })
168 /// }
169 /// ```
170 ///
171 /// ### NOTE:
172 ///
173 /// If you rename the Tokio crate in your dependencies this macro will not work.
174 /// If you must rename the current version of Tokio because you're also using an
175 /// older version of Tokio, you _must_ make the current version of Tokio
176 /// available as `tokio` in the module where this macro is expanded.
177 #[proc_macro_attribute]
178 #[cfg(not(test))] // Work around for rust-lang/rust#62127
main(args: TokenStream, item: TokenStream) -> TokenStream179 pub fn main(args: TokenStream, item: TokenStream) -> TokenStream {
180 entry::main(args, item, true)
181 }
182
183 /// Marks async function to be executed by selected runtime. This macro helps set up a `Runtime`
184 /// without requiring the user to use [Runtime](../tokio/runtime/struct.Runtime.html) or
185 /// [Builder](../tokio/runtime/struct.builder.html) directly.
186 ///
187 /// ## Function arguments:
188 ///
189 /// Arguments are allowed for any functions aside from `main` which is special
190 ///
191 /// ## Usage
192 ///
193 /// ### Using default
194 ///
195 /// ```rust
196 /// #[tokio::main(flavor = "current_thread")]
197 /// async fn main() {
198 /// println!("Hello world");
199 /// }
200 /// ```
201 ///
202 /// Equivalent code not using `#[tokio::main]`
203 ///
204 /// ```rust
205 /// fn main() {
206 /// tokio::runtime::Builder::new_current_thread()
207 /// .enable_all()
208 /// .build()
209 /// .unwrap()
210 /// .block_on(async {
211 /// println!("Hello world");
212 /// })
213 /// }
214 /// ```
215 ///
216 /// ### NOTE:
217 ///
218 /// If you rename the Tokio crate in your dependencies this macro will not work.
219 /// If you must rename the current version of Tokio because you're also using an
220 /// older version of Tokio, you _must_ make the current version of Tokio
221 /// available as `tokio` in the module where this macro is expanded.
222 #[proc_macro_attribute]
223 #[cfg(not(test))] // Work around for rust-lang/rust#62127
main_rt(args: TokenStream, item: TokenStream) -> TokenStream224 pub fn main_rt(args: TokenStream, item: TokenStream) -> TokenStream {
225 entry::main(args, item, false)
226 }
227
228 /// Marks async function to be executed by runtime, suitable to test environment
229 ///
230 /// ## Usage
231 ///
232 /// ### Multi-thread runtime
233 ///
234 /// ```no_run
235 /// #[tokio::test(flavor = "multi_thread", worker_threads = 1)]
236 /// async fn my_test() {
237 /// assert!(true);
238 /// }
239 /// ```
240 ///
241 /// ### Using default
242 ///
243 /// The default test runtime is single-threaded.
244 ///
245 /// ```no_run
246 /// #[tokio::test]
247 /// async fn my_test() {
248 /// assert!(true);
249 /// }
250 /// ```
251 ///
252 /// ### Configure the runtime to start with time paused
253 ///
254 /// ```no_run
255 /// #[tokio::test(start_paused = true)]
256 /// async fn my_test() {
257 /// assert!(true);
258 /// }
259 /// ```
260 ///
261 /// ### NOTE:
262 ///
263 /// If you rename the Tokio crate in your dependencies this macro will not work.
264 /// If you must rename the current version of Tokio because you're also using an
265 /// older version of Tokio, you _must_ make the current version of Tokio
266 /// available as `tokio` in the module where this macro is expanded.
267 #[proc_macro_attribute]
test(args: TokenStream, item: TokenStream) -> TokenStream268 pub fn test(args: TokenStream, item: TokenStream) -> TokenStream {
269 entry::test(args, item, true)
270 }
271
272 /// Marks async function to be executed by runtime, suitable to test environment
273 ///
274 /// ## Usage
275 ///
276 /// ```no_run
277 /// #[tokio::test]
278 /// async fn my_test() {
279 /// assert!(true);
280 /// }
281 /// ```
282 ///
283 /// ### NOTE:
284 ///
285 /// If you rename the Tokio crate in your dependencies this macro will not work.
286 /// If you must rename the current version of Tokio because you're also using an
287 /// older version of Tokio, you _must_ make the current version of Tokio
288 /// available as `tokio` in the module where this macro is expanded.
289 #[proc_macro_attribute]
test_rt(args: TokenStream, item: TokenStream) -> TokenStream290 pub fn test_rt(args: TokenStream, item: TokenStream) -> TokenStream {
291 entry::test(args, item, false)
292 }
293
294 /// Always fails with the error message below.
295 /// ```text
296 /// The #[tokio::main] macro requires rt or rt-multi-thread.
297 /// ```
298 #[proc_macro_attribute]
main_fail(_args: TokenStream, _item: TokenStream) -> TokenStream299 pub fn main_fail(_args: TokenStream, _item: TokenStream) -> TokenStream {
300 syn::Error::new(
301 proc_macro2::Span::call_site(),
302 "The #[tokio::main] macro requires rt or rt-multi-thread.",
303 )
304 .to_compile_error()
305 .into()
306 }
307
308 /// Always fails with the error message below.
309 /// ```text
310 /// The #[tokio::test] macro requires rt or rt-multi-thread.
311 /// ```
312 #[proc_macro_attribute]
test_fail(_args: TokenStream, _item: TokenStream) -> TokenStream313 pub fn test_fail(_args: TokenStream, _item: TokenStream) -> TokenStream {
314 syn::Error::new(
315 proc_macro2::Span::call_site(),
316 "The #[tokio::test] macro requires rt or rt-multi-thread.",
317 )
318 .to_compile_error()
319 .into()
320 }
321
322 /// Implementation detail of the `select!` macro. This macro is **not** intended
323 /// to be used as part of the public API and is permitted to change.
324 #[proc_macro]
325 #[doc(hidden)]
select_priv_declare_output_enum(input: TokenStream) -> TokenStream326 pub fn select_priv_declare_output_enum(input: TokenStream) -> TokenStream {
327 select::declare_output_enum(input)
328 }
329