1 | #![allow (unknown_lints, unexpected_cfgs)] |
2 | #![allow (clippy::needless_doctest_main)] |
3 | #![warn ( |
4 | missing_debug_implementations, |
5 | missing_docs, |
6 | rust_2018_idioms, |
7 | unreachable_pub |
8 | )] |
9 | #![doc (test( |
10 | no_crate_inject, |
11 | attr(deny(warnings, rust_2018_idioms), allow(dead_code, unused_variables)) |
12 | ))] |
13 | |
14 | //! Macros for use with Tokio |
15 | |
16 | // This `extern` is required for older `rustc` versions but newer `rustc` |
17 | // versions warn about the unused `extern crate`. |
18 | #[allow (unused_extern_crates)] |
19 | extern crate proc_macro; |
20 | |
21 | mod entry; |
22 | mod select; |
23 | |
24 | use proc_macro::TokenStream; |
25 | |
26 | /// Marks async function to be executed by the selected runtime. This macro |
27 | /// helps set up a `Runtime` without requiring the user to use |
28 | /// [Runtime](../tokio/runtime/struct.Runtime.html) or |
29 | /// [Builder](../tokio/runtime/struct.Builder.html) directly. |
30 | /// |
31 | /// Note: This macro is designed to be simplistic and targets applications that |
32 | /// do not require a complex setup. If the provided functionality is not |
33 | /// sufficient, you may be interested in using |
34 | /// [Builder](../tokio/runtime/struct.Builder.html), which provides a more |
35 | /// powerful interface. |
36 | /// |
37 | /// Note: This macro can be used on any function and not just the `main` |
38 | /// function. Using it on a non-main function makes the function behave as if it |
39 | /// was synchronous by starting a new runtime each time it is called. If the |
40 | /// function is called often, it is preferable to create the runtime using the |
41 | /// runtime builder so the runtime can be reused across calls. |
42 | /// |
43 | /// # Non-worker async function |
44 | /// |
45 | /// Note that the async function marked with this macro does not run as a |
46 | /// worker. The expectation is that other tasks are spawned by the function here. |
47 | /// Awaiting on other futures from the function provided here will not |
48 | /// perform as fast as those spawned as workers. |
49 | /// |
50 | /// # Multi-threaded runtime |
51 | /// |
52 | /// To use the multi-threaded runtime, the macro can be configured using |
53 | /// |
54 | /// ``` |
55 | /// #[tokio::main(flavor = "multi_thread" , worker_threads = 10)] |
56 | /// # async fn main() {} |
57 | /// ``` |
58 | /// |
59 | /// The `worker_threads` option configures the number of worker threads, and |
60 | /// defaults to the number of cpus on the system. This is the default flavor. |
61 | /// |
62 | /// Note: The multi-threaded runtime requires the `rt-multi-thread` feature |
63 | /// flag. |
64 | /// |
65 | /// # Current thread runtime |
66 | /// |
67 | /// To use the single-threaded runtime known as the `current_thread` runtime, |
68 | /// the macro can be configured using |
69 | /// |
70 | /// ``` |
71 | /// #[tokio::main(flavor = "current_thread" )] |
72 | /// # async fn main() {} |
73 | /// ``` |
74 | /// |
75 | /// ## Function arguments: |
76 | /// |
77 | /// Arguments are allowed for any functions aside from `main` which is special |
78 | /// |
79 | /// ## Usage |
80 | /// |
81 | /// ### Using the multi-thread runtime |
82 | /// |
83 | /// ```rust |
84 | /// #[tokio::main] |
85 | /// async fn main() { |
86 | /// println!("Hello world" ); |
87 | /// } |
88 | /// ``` |
89 | /// |
90 | /// Equivalent code not using `#[tokio::main]` |
91 | /// |
92 | /// ```rust |
93 | /// fn main() { |
94 | /// tokio::runtime::Builder::new_multi_thread() |
95 | /// .enable_all() |
96 | /// .build() |
97 | /// .unwrap() |
98 | /// .block_on(async { |
99 | /// println!("Hello world" ); |
100 | /// }) |
101 | /// } |
102 | /// ``` |
103 | /// |
104 | /// ### Using current thread runtime |
105 | /// |
106 | /// The basic scheduler is single-threaded. |
107 | /// |
108 | /// ```rust |
109 | /// #[tokio::main(flavor = "current_thread" )] |
110 | /// async fn main() { |
111 | /// println!("Hello world" ); |
112 | /// } |
113 | /// ``` |
114 | /// |
115 | /// Equivalent code not using `#[tokio::main]` |
116 | /// |
117 | /// ```rust |
118 | /// fn main() { |
119 | /// tokio::runtime::Builder::new_current_thread() |
120 | /// .enable_all() |
121 | /// .build() |
122 | /// .unwrap() |
123 | /// .block_on(async { |
124 | /// println!("Hello world" ); |
125 | /// }) |
126 | /// } |
127 | /// ``` |
128 | /// |
129 | /// ### Set number of worker threads |
130 | /// |
131 | /// ```rust |
132 | /// #[tokio::main(worker_threads = 2)] |
133 | /// async fn main() { |
134 | /// println!("Hello world" ); |
135 | /// } |
136 | /// ``` |
137 | /// |
138 | /// Equivalent code not using `#[tokio::main]` |
139 | /// |
140 | /// ```rust |
141 | /// fn main() { |
142 | /// tokio::runtime::Builder::new_multi_thread() |
143 | /// .worker_threads(2) |
144 | /// .enable_all() |
145 | /// .build() |
146 | /// .unwrap() |
147 | /// .block_on(async { |
148 | /// println!("Hello world" ); |
149 | /// }) |
150 | /// } |
151 | /// ``` |
152 | /// |
153 | /// ### Configure the runtime to start with time paused |
154 | /// |
155 | /// ```rust |
156 | /// #[tokio::main(flavor = "current_thread" , start_paused = true)] |
157 | /// async fn main() { |
158 | /// println!("Hello world" ); |
159 | /// } |
160 | /// ``` |
161 | /// |
162 | /// Equivalent code not using `#[tokio::main]` |
163 | /// |
164 | /// ```rust |
165 | /// fn main() { |
166 | /// tokio::runtime::Builder::new_current_thread() |
167 | /// .enable_all() |
168 | /// .start_paused(true) |
169 | /// .build() |
170 | /// .unwrap() |
171 | /// .block_on(async { |
172 | /// println!("Hello world" ); |
173 | /// }) |
174 | /// } |
175 | /// ``` |
176 | /// |
177 | /// Note that `start_paused` requires the `test-util` feature to be enabled. |
178 | /// |
179 | /// ### Rename package |
180 | /// |
181 | /// ```rust |
182 | /// use tokio as tokio1; |
183 | /// |
184 | /// #[tokio1::main(crate = "tokio1" )] |
185 | /// async fn main() { |
186 | /// println!("Hello world" ); |
187 | /// } |
188 | /// ``` |
189 | /// |
190 | /// Equivalent code not using `#[tokio::main]` |
191 | /// |
192 | /// ```rust |
193 | /// use tokio as tokio1; |
194 | /// |
195 | /// fn main() { |
196 | /// tokio1::runtime::Builder::new_multi_thread() |
197 | /// .enable_all() |
198 | /// .build() |
199 | /// .unwrap() |
200 | /// .block_on(async { |
201 | /// println!("Hello world" ); |
202 | /// }) |
203 | /// } |
204 | /// ``` |
205 | /// |
206 | /// ### Configure unhandled panic behavior |
207 | /// |
208 | /// Available options are `shutdown_runtime` and `ignore`. For more details, see |
209 | /// [`Builder::unhandled_panic`]. |
210 | /// |
211 | /// This option is only compatible with the `current_thread` runtime. |
212 | /// |
213 | /// ```no_run |
214 | /// # #![allow(unknown_lints, unexpected_cfgs)] |
215 | /// #[cfg(tokio_unstable)] |
216 | /// #[tokio::main(flavor = "current_thread" , unhandled_panic = "shutdown_runtime" )] |
217 | /// async fn main() { |
218 | /// let _ = tokio::spawn(async { |
219 | /// panic!("This panic will shutdown the runtime." ); |
220 | /// }).await; |
221 | /// } |
222 | /// # #[cfg (not(tokio_unstable))] |
223 | /// # fn main() { } |
224 | /// ``` |
225 | /// |
226 | /// Equivalent code not using `#[tokio::main]` |
227 | /// |
228 | /// ```no_run |
229 | /// # #![allow(unknown_lints, unexpected_cfgs)] |
230 | /// #[cfg(tokio_unstable)] |
231 | /// fn main() { |
232 | /// tokio::runtime::Builder::new_current_thread() |
233 | /// .enable_all() |
234 | /// .unhandled_panic(UnhandledPanic::ShutdownRuntime) |
235 | /// .build() |
236 | /// .unwrap() |
237 | /// .block_on(async { |
238 | /// let _ = tokio::spawn(async { |
239 | /// panic!("This panic will shutdown the runtime." ); |
240 | /// }).await; |
241 | /// }) |
242 | /// } |
243 | /// # #[cfg (not(tokio_unstable))] |
244 | /// # fn main() { } |
245 | /// ``` |
246 | /// |
247 | /// **Note**: This option depends on Tokio's [unstable API][unstable]. See [the |
248 | /// documentation on unstable features][unstable] for details on how to enable |
249 | /// Tokio's unstable features. |
250 | /// |
251 | /// [`Builder::unhandled_panic`]: ../tokio/runtime/struct.Builder.html#method.unhandled_panic |
252 | /// [unstable]: ../tokio/index.html#unstable-features |
253 | #[proc_macro_attribute ] |
254 | pub fn main (args: TokenStream, item: TokenStream) -> TokenStream { |
255 | entry::main(args.into(), item.into(), rt_multi_thread:true).into() |
256 | } |
257 | |
258 | /// Marks async function to be executed by selected runtime. This macro helps set up a `Runtime` |
259 | /// without requiring the user to use [Runtime](../tokio/runtime/struct.Runtime.html) or |
260 | /// [Builder](../tokio/runtime/struct.Builder.html) directly. |
261 | /// |
262 | /// ## Function arguments: |
263 | /// |
264 | /// Arguments are allowed for any functions aside from `main` which is special |
265 | /// |
266 | /// ## Usage |
267 | /// |
268 | /// ### Using default |
269 | /// |
270 | /// ```rust |
271 | /// #[tokio::main(flavor = "current_thread" )] |
272 | /// async fn main() { |
273 | /// println!("Hello world" ); |
274 | /// } |
275 | /// ``` |
276 | /// |
277 | /// Equivalent code not using `#[tokio::main]` |
278 | /// |
279 | /// ```rust |
280 | /// fn main() { |
281 | /// tokio::runtime::Builder::new_current_thread() |
282 | /// .enable_all() |
283 | /// .build() |
284 | /// .unwrap() |
285 | /// .block_on(async { |
286 | /// println!("Hello world" ); |
287 | /// }) |
288 | /// } |
289 | /// ``` |
290 | /// |
291 | /// ### Rename package |
292 | /// |
293 | /// ```rust |
294 | /// use tokio as tokio1; |
295 | /// |
296 | /// #[tokio1::main(crate = "tokio1" )] |
297 | /// async fn main() { |
298 | /// println!("Hello world" ); |
299 | /// } |
300 | /// ``` |
301 | /// |
302 | /// Equivalent code not using `#[tokio::main]` |
303 | /// |
304 | /// ```rust |
305 | /// use tokio as tokio1; |
306 | /// |
307 | /// fn main() { |
308 | /// tokio1::runtime::Builder::new_multi_thread() |
309 | /// .enable_all() |
310 | /// .build() |
311 | /// .unwrap() |
312 | /// .block_on(async { |
313 | /// println!("Hello world" ); |
314 | /// }) |
315 | /// } |
316 | /// ``` |
317 | #[proc_macro_attribute ] |
318 | pub fn main_rt (args: TokenStream, item: TokenStream) -> TokenStream { |
319 | entry::main(args.into(), item.into(), rt_multi_thread:false).into() |
320 | } |
321 | |
322 | /// Marks async function to be executed by runtime, suitable to test environment. |
323 | /// This macro helps set up a `Runtime` without requiring the user to use |
324 | /// [Runtime](../tokio/runtime/struct.Runtime.html) or |
325 | /// [Builder](../tokio/runtime/struct.Builder.html) directly. |
326 | /// |
327 | /// Note: This macro is designed to be simplistic and targets applications that |
328 | /// do not require a complex setup. If the provided functionality is not |
329 | /// sufficient, you may be interested in using |
330 | /// [Builder](../tokio/runtime/struct.Builder.html), which provides a more |
331 | /// powerful interface. |
332 | /// |
333 | /// # Multi-threaded runtime |
334 | /// |
335 | /// To use the multi-threaded runtime, the macro can be configured using |
336 | /// |
337 | /// ```no_run |
338 | /// #[tokio::test(flavor = "multi_thread" , worker_threads = 1)] |
339 | /// async fn my_test() { |
340 | /// assert!(true); |
341 | /// } |
342 | /// ``` |
343 | /// |
344 | /// The `worker_threads` option configures the number of worker threads, and |
345 | /// defaults to the number of cpus on the system. |
346 | /// |
347 | /// Note: The multi-threaded runtime requires the `rt-multi-thread` feature |
348 | /// flag. |
349 | /// |
350 | /// # Current thread runtime |
351 | /// |
352 | /// The default test runtime is single-threaded. Each test gets a |
353 | /// separate current-thread runtime. |
354 | /// |
355 | /// ```no_run |
356 | /// #[tokio::test] |
357 | /// async fn my_test() { |
358 | /// assert!(true); |
359 | /// } |
360 | /// ``` |
361 | /// |
362 | /// ## Usage |
363 | /// |
364 | /// ### Using the multi-thread runtime |
365 | /// |
366 | /// ```no_run |
367 | /// #[tokio::test(flavor = "multi_thread" )] |
368 | /// async fn my_test() { |
369 | /// assert!(true); |
370 | /// } |
371 | /// ``` |
372 | /// |
373 | /// Equivalent code not using `#[tokio::test]` |
374 | /// |
375 | /// ```no_run |
376 | /// #[test] |
377 | /// fn my_test() { |
378 | /// tokio::runtime::Builder::new_multi_thread() |
379 | /// .enable_all() |
380 | /// .build() |
381 | /// .unwrap() |
382 | /// .block_on(async { |
383 | /// assert!(true); |
384 | /// }) |
385 | /// } |
386 | /// ``` |
387 | /// |
388 | /// ### Using current thread runtime |
389 | /// |
390 | /// ```no_run |
391 | /// #[tokio::test] |
392 | /// async fn my_test() { |
393 | /// assert!(true); |
394 | /// } |
395 | /// ``` |
396 | /// |
397 | /// Equivalent code not using `#[tokio::test]` |
398 | /// |
399 | /// ```no_run |
400 | /// #[test] |
401 | /// fn my_test() { |
402 | /// tokio::runtime::Builder::new_current_thread() |
403 | /// .enable_all() |
404 | /// .build() |
405 | /// .unwrap() |
406 | /// .block_on(async { |
407 | /// assert!(true); |
408 | /// }) |
409 | /// } |
410 | /// ``` |
411 | /// |
412 | /// ### Set number of worker threads |
413 | /// |
414 | /// ```no_run |
415 | /// #[tokio::test(flavor = "multi_thread" , worker_threads = 2)] |
416 | /// async fn my_test() { |
417 | /// assert!(true); |
418 | /// } |
419 | /// ``` |
420 | /// |
421 | /// Equivalent code not using `#[tokio::test]` |
422 | /// |
423 | /// ```no_run |
424 | /// #[test] |
425 | /// fn my_test() { |
426 | /// tokio::runtime::Builder::new_multi_thread() |
427 | /// .worker_threads(2) |
428 | /// .enable_all() |
429 | /// .build() |
430 | /// .unwrap() |
431 | /// .block_on(async { |
432 | /// assert!(true); |
433 | /// }) |
434 | /// } |
435 | /// ``` |
436 | /// |
437 | /// ### Configure the runtime to start with time paused |
438 | /// |
439 | /// ```no_run |
440 | /// #[tokio::test(start_paused = true)] |
441 | /// async fn my_test() { |
442 | /// assert!(true); |
443 | /// } |
444 | /// ``` |
445 | /// |
446 | /// Equivalent code not using `#[tokio::test]` |
447 | /// |
448 | /// ```no_run |
449 | /// #[test] |
450 | /// fn my_test() { |
451 | /// tokio::runtime::Builder::new_current_thread() |
452 | /// .enable_all() |
453 | /// .start_paused(true) |
454 | /// .build() |
455 | /// .unwrap() |
456 | /// .block_on(async { |
457 | /// assert!(true); |
458 | /// }) |
459 | /// } |
460 | /// ``` |
461 | /// |
462 | /// Note that `start_paused` requires the `test-util` feature to be enabled. |
463 | /// |
464 | /// ### Rename package |
465 | /// |
466 | /// ```rust |
467 | /// use tokio as tokio1; |
468 | /// |
469 | /// #[tokio1::test(crate = "tokio1" )] |
470 | /// async fn my_test() { |
471 | /// println!("Hello world" ); |
472 | /// } |
473 | /// ``` |
474 | /// |
475 | /// ### Configure unhandled panic behavior |
476 | /// |
477 | /// Available options are `shutdown_runtime` and `ignore`. For more details, see |
478 | /// [`Builder::unhandled_panic`]. |
479 | /// |
480 | /// This option is only compatible with the `current_thread` runtime. |
481 | /// |
482 | /// ```no_run |
483 | /// # #![allow(unknown_lints, unexpected_cfgs)] |
484 | /// #[cfg(tokio_unstable)] |
485 | /// #[tokio::test(flavor = "current_thread" , unhandled_panic = "shutdown_runtime" )] |
486 | /// async fn my_test() { |
487 | /// let _ = tokio::spawn(async { |
488 | /// panic!("This panic will shutdown the runtime." ); |
489 | /// }).await; |
490 | /// } |
491 | /// # #[cfg (not(tokio_unstable))] |
492 | /// # fn main() { } |
493 | /// ``` |
494 | /// |
495 | /// Equivalent code not using `#[tokio::test]` |
496 | /// |
497 | /// ```no_run |
498 | /// # #![allow(unknown_lints, unexpected_cfgs)] |
499 | /// #[cfg(tokio_unstable)] |
500 | /// #[test] |
501 | /// fn my_test() { |
502 | /// tokio::runtime::Builder::new_current_thread() |
503 | /// .enable_all() |
504 | /// .unhandled_panic(UnhandledPanic::ShutdownRuntime) |
505 | /// .build() |
506 | /// .unwrap() |
507 | /// .block_on(async { |
508 | /// let _ = tokio::spawn(async { |
509 | /// panic!("This panic will shutdown the runtime." ); |
510 | /// }).await; |
511 | /// }) |
512 | /// } |
513 | /// # #[cfg (not(tokio_unstable))] |
514 | /// # fn main() { } |
515 | /// ``` |
516 | /// |
517 | /// **Note**: This option depends on Tokio's [unstable API][unstable]. See [the |
518 | /// documentation on unstable features][unstable] for details on how to enable |
519 | /// Tokio's unstable features. |
520 | /// |
521 | /// [`Builder::unhandled_panic`]: ../tokio/runtime/struct.Builder.html#method.unhandled_panic |
522 | /// [unstable]: ../tokio/index.html#unstable-features |
523 | #[proc_macro_attribute ] |
524 | pub fn test (args: TokenStream, item: TokenStream) -> TokenStream { |
525 | entry::test(args.into(), item.into(), rt_multi_thread:true).into() |
526 | } |
527 | |
528 | /// Marks async function to be executed by runtime, suitable to test environment |
529 | /// |
530 | /// ## Usage |
531 | /// |
532 | /// ```no_run |
533 | /// #[tokio::test] |
534 | /// async fn my_test() { |
535 | /// assert!(true); |
536 | /// } |
537 | /// ``` |
538 | #[proc_macro_attribute ] |
539 | pub fn test_rt (args: TokenStream, item: TokenStream) -> TokenStream { |
540 | entry::test(args.into(), item.into(), rt_multi_thread:false).into() |
541 | } |
542 | |
543 | /// Always fails with the error message below. |
544 | /// ```text |
545 | /// The #[tokio::main] macro requires rt or rt-multi-thread. |
546 | /// ``` |
547 | #[proc_macro_attribute ] |
548 | pub fn main_fail (_args: TokenStream, _item: TokenStream) -> TokenStream { |
549 | synTokenStream::Error::new( |
550 | proc_macro2::Span::call_site(), |
551 | message:"The #[tokio::main] macro requires rt or rt-multi-thread." , |
552 | ) |
553 | .to_compile_error() |
554 | .into() |
555 | } |
556 | |
557 | /// Always fails with the error message below. |
558 | /// ```text |
559 | /// The #[tokio::test] macro requires rt or rt-multi-thread. |
560 | /// ``` |
561 | #[proc_macro_attribute ] |
562 | pub fn test_fail (_args: TokenStream, _item: TokenStream) -> TokenStream { |
563 | synTokenStream::Error::new( |
564 | proc_macro2::Span::call_site(), |
565 | message:"The #[tokio::test] macro requires rt or rt-multi-thread." , |
566 | ) |
567 | .to_compile_error() |
568 | .into() |
569 | } |
570 | |
571 | /// Implementation detail of the `select!` macro. This macro is **not** intended |
572 | /// to be used as part of the public API and is permitted to change. |
573 | #[proc_macro ] |
574 | #[doc (hidden)] |
575 | pub fn select_priv_declare_output_enum(input: TokenStream) -> TokenStream { |
576 | select::declare_output_enum(input) |
577 | } |
578 | |
579 | /// Implementation detail of the `select!` macro. This macro is **not** intended |
580 | /// to be used as part of the public API and is permitted to change. |
581 | #[proc_macro ] |
582 | #[doc (hidden)] |
583 | pub fn select_priv_clean_pattern(input: TokenStream) -> TokenStream { |
584 | select::clean_pattern_macro(input) |
585 | } |
586 | |