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