tokio_shared_rt_macro/
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#[proc_macro_attribute]
205#[cfg(not(test))] // Work around for rust-lang/rust#62127
206pub fn main(args: TokenStream, item: TokenStream) -> TokenStream {
207    entry::main(args.into(), item.into(), true).into()
208}
209
210/// Marks async function to be executed by selected runtime. This macro helps set up a `Runtime`
211/// without requiring the user to use [Runtime](../tokio/runtime/struct.Runtime.html) or
212/// [Builder](../tokio/runtime/struct.Builder.html) directly.
213///
214/// ## Function arguments:
215///
216/// Arguments are allowed for any functions aside from `main` which is special
217///
218/// ## Usage
219///
220/// ### Using default
221///
222/// ```rust
223/// #[tokio::main(flavor = "current_thread")]
224/// async fn main() {
225///     println!("Hello world");
226/// }
227/// ```
228///
229/// Equivalent code not using `#[tokio::main]`
230///
231/// ```rust
232/// fn main() {
233///     tokio::runtime::Builder::new_current_thread()
234///         .enable_all()
235///         .build()
236///         .unwrap()
237///         .block_on(async {
238///             println!("Hello world");
239///         })
240/// }
241/// ```
242///
243/// ### Rename package
244///
245/// ```rust
246/// use tokio as tokio1;
247///
248/// #[tokio1::main(crate = "tokio1")]
249/// async fn main() {
250///     println!("Hello world");
251/// }
252/// ```
253///
254/// Equivalent code not using `#[tokio::main]`
255///
256/// ```rust
257/// use tokio as tokio1;
258///
259/// fn main() {
260///     tokio1::runtime::Builder::new_multi_thread()
261///         .enable_all()
262///         .build()
263///         .unwrap()
264///         .block_on(async {
265///             println!("Hello world");
266///         })
267/// }
268/// ```
269#[proc_macro_attribute]
270#[cfg(not(test))] // Work around for rust-lang/rust#62127
271pub fn main_rt(args: TokenStream, item: TokenStream) -> TokenStream {
272    entry::main(args.into(), item.into(), false).into()
273}
274
275/// Marks async function to be executed by runtime, suitable to test environment.
276/// This macro helps set up a `Runtime` without requiring the user to use
277/// [Runtime](../tokio/runtime/struct.Runtime.html) or
278/// [Builder](../tokio/runtime/struct.Builder.html) directly.
279///
280/// Note: This macro is designed to be simplistic and targets applications that
281/// do not require a complex setup. If the provided functionality is not
282/// sufficient, you may be interested in using
283/// [Builder](../tokio/runtime/struct.Builder.html), which provides a more
284/// powerful interface.
285///
286/// # Multi-threaded runtime
287///
288/// To use the multi-threaded runtime, the macro can be configured using
289///
290/// ```no_run
291/// #[tokio::test(flavor = "multi_thread", worker_threads = 1)]
292/// async fn my_test() {
293///     assert!(true);
294/// }
295/// ```
296///
297/// The `worker_threads` option configures the number of worker threads, and
298/// defaults to the number of cpus on the system.
299///
300/// Note: The multi-threaded runtime requires the `rt-multi-thread` feature
301/// flag.
302///
303/// # Current thread runtime
304///
305/// The default test runtime is single-threaded. Each test gets a
306/// separate current-thread runtime.
307///
308/// ```no_run
309/// #[tokio::test]
310/// async fn my_test() {
311///     assert!(true);
312/// }
313/// ```
314///
315/// ## Usage
316///
317/// ### Using the multi-thread runtime
318///
319/// ```no_run
320/// #[tokio::test(flavor = "multi_thread")]
321/// async fn my_test() {
322///     assert!(true);
323/// }
324/// ```
325///
326/// Equivalent code not using `#[tokio::test]`
327///
328/// ```no_run
329/// #[test]
330/// fn my_test() {
331///     tokio::runtime::Builder::new_multi_thread()
332///         .enable_all()
333///         .build()
334///         .unwrap()
335///         .block_on(async {
336///             assert!(true);
337///         })
338/// }
339/// ```
340///
341/// ### Using current thread runtime
342///
343/// ```no_run
344/// #[tokio::test]
345/// async fn my_test() {
346///     assert!(true);
347/// }
348/// ```
349///
350/// Equivalent code not using `#[tokio::test]`
351///
352/// ```no_run
353/// #[test]
354/// fn my_test() {
355///     tokio::runtime::Builder::new_current_thread()
356///         .enable_all()
357///         .build()
358///         .unwrap()
359///         .block_on(async {
360///             assert!(true);
361///         })
362/// }
363/// ```
364///
365/// ### Set number of worker threads
366///
367/// ```no_run
368/// #[tokio::test(flavor ="multi_thread", worker_threads = 2)]
369/// async fn my_test() {
370///     assert!(true);
371/// }
372/// ```
373///
374/// Equivalent code not using `#[tokio::test]`
375///
376/// ```no_run
377/// #[test]
378/// fn my_test() {
379///     tokio::runtime::Builder::new_multi_thread()
380///         .worker_threads(2)
381///         .enable_all()
382///         .build()
383///         .unwrap()
384///         .block_on(async {
385///             assert!(true);
386///         })
387/// }
388/// ```
389///
390/// ### Configure the runtime to start with time paused
391///
392/// ```no_run
393/// #[tokio::test(start_paused = true)]
394/// async fn my_test() {
395///     assert!(true);
396/// }
397/// ```
398///
399/// Equivalent code not using `#[tokio::test]`
400///
401/// ```no_run
402/// #[test]
403/// fn my_test() {
404///     tokio::runtime::Builder::new_current_thread()
405///         .enable_all()
406///         .start_paused(true)
407///         .build()
408///         .unwrap()
409///         .block_on(async {
410///             assert!(true);
411///         })
412/// }
413/// ```
414///
415/// Note that `start_paused` requires the `test-util` feature to be enabled.
416///
417/// ### Rename package
418///
419/// ```rust
420/// use tokio as tokio1;
421///
422/// #[tokio1::test(crate = "tokio1")]
423/// async fn my_test() {
424///     println!("Hello world");
425/// }
426/// ```
427#[proc_macro_attribute]
428pub fn test(args: TokenStream, item: TokenStream) -> TokenStream {
429    entry::test(args.into(), item.into(), true).into()
430}
431
432/// Marks async function to be executed by runtime, suitable to test environment
433///
434/// ## Usage
435///
436/// ```no_run
437/// #[tokio::test]
438/// async fn my_test() {
439///     assert!(true);
440/// }
441/// ```
442#[proc_macro_attribute]
443pub fn test_rt(args: TokenStream, item: TokenStream) -> TokenStream {
444    entry::test(args.into(), item.into(), false).into()
445}
446
447/// Always fails with the error message below.
448/// ```text
449/// The #[tokio::main] macro requires rt or rt-multi-thread.
450/// ```
451#[proc_macro_attribute]
452pub fn main_fail(_args: TokenStream, _item: TokenStream) -> TokenStream {
453    syn::Error::new(
454        proc_macro2::Span::call_site(),
455        "The #[tokio::main] macro requires rt or rt-multi-thread.",
456    )
457    .to_compile_error()
458    .into()
459}
460
461/// Always fails with the error message below.
462/// ```text
463/// The #[tokio::test] macro requires rt or rt-multi-thread.
464/// ```
465#[proc_macro_attribute]
466pub fn test_fail(_args: TokenStream, _item: TokenStream) -> TokenStream {
467    syn::Error::new(
468        proc_macro2::Span::call_site(),
469        "The #[tokio::test] macro requires rt or rt-multi-thread.",
470    )
471    .to_compile_error()
472    .into()
473}
474
475/// Implementation detail of the `select!` macro. This macro is **not** intended
476/// to be used as part of the public API and is permitted to change.
477#[proc_macro]
478#[doc(hidden)]
479pub fn select_priv_declare_output_enum(input: TokenStream) -> TokenStream {
480    select::declare_output_enum(input)
481}
482
483/// Implementation detail of the `select!` macro. This macro is **not** intended
484/// to be used as part of the public API and is permitted to change.
485#[proc_macro]
486#[doc(hidden)]
487pub fn select_priv_clean_pattern(input: TokenStream) -> TokenStream {
488    select::clean_pattern_macro(input)
489}