Skip to main content

tokio_macros/
lib.rs

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