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