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