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}