1 #![doc(html_root_url = "https://docs.rs/tokio-macros/1.1.0")]
2 #![allow(clippy::needless_doctest_main)]
3 #![warn(
4     missing_debug_implementations,
5     missing_docs,
6     rust_2018_idioms,
7     unreachable_pub
8 )]
9 #![cfg_attr(docsrs, deny(broken_intra_doc_links))]
10 #![doc(test(
11     no_crate_inject,
12     attr(deny(warnings, rust_2018_idioms), allow(dead_code, unused_variables))
13 ))]
14 
15 //! Macros for use with Tokio
16 
17 // This `extern` is required for older `rustc` versions but newer `rustc`
18 // versions warn about the unused `extern crate`.
19 #[allow(unused_extern_crates)]
20 extern crate proc_macro;
21 
22 mod entry;
23 mod select;
24 
25 use proc_macro::TokenStream;
26 
27 /// Marks async function to be executed by the selected runtime. This macro
28 /// helps set up a `Runtime` without requiring the user to use
29 /// [Runtime](../tokio/runtime/struct.Runtime.html) or
30 /// [Builder](../tokio/runtime/struct.Builder.html) directly.
31 ///
32 /// Note: This macro is designed to be simplistic and targets applications that
33 /// do not require a complex setup. If the provided functionality is not
34 /// sufficient, you may be interested in using
35 /// [Builder](../tokio/runtime/struct.Builder.html), which provides a more
36 /// powerful interface.
37 ///
38 /// Note: This macro can be used on any function and not just the `main`
39 /// function. Using it on a non-main function makes the function behave as if it
40 /// was synchronous by starting a new runtime each time it is called. If the
41 /// function is called often, it is preferable to create the runtime using the
42 /// runtime builder so the runtime can be reused across calls.
43 ///
44 /// # Multi-threaded runtime
45 ///
46 /// To use the multi-threaded runtime, the macro can be configured using
47 ///
48 /// ```
49 /// #[tokio::main(flavor = "multi_thread", worker_threads = 10)]
50 /// # async fn main() {}
51 /// ```
52 ///
53 /// The `worker_threads` option configures the number of worker threads, and
54 /// defaults to the number of cpus on the system. This is the default flavor.
55 ///
56 /// Note: The multi-threaded runtime requires the `rt-multi-thread` feature
57 /// flag.
58 ///
59 /// # Current thread runtime
60 ///
61 /// To use the single-threaded runtime known as the `current_thread` runtime,
62 /// the macro can be configured using
63 ///
64 /// ```
65 /// #[tokio::main(flavor = "current_thread")]
66 /// # async fn main() {}
67 /// ```
68 ///
69 /// ## Function arguments:
70 ///
71 /// Arguments are allowed for any functions aside from `main` which is special
72 ///
73 /// ## Usage
74 ///
75 /// ### Using the multi-thread runtime
76 ///
77 /// ```rust
78 /// #[tokio::main]
79 /// async fn main() {
80 ///     println!("Hello world");
81 /// }
82 /// ```
83 ///
84 /// Equivalent code not using `#[tokio::main]`
85 ///
86 /// ```rust
87 /// fn main() {
88 ///     tokio::runtime::Builder::new_multi_thread()
89 ///         .enable_all()
90 ///         .build()
91 ///         .unwrap()
92 ///         .block_on(async {
93 ///             println!("Hello world");
94 ///         })
95 /// }
96 /// ```
97 ///
98 /// ### Using current thread runtime
99 ///
100 /// The basic scheduler is single-threaded.
101 ///
102 /// ```rust
103 /// #[tokio::main(flavor = "current_thread")]
104 /// async fn main() {
105 ///     println!("Hello world");
106 /// }
107 /// ```
108 ///
109 /// Equivalent code not using `#[tokio::main]`
110 ///
111 /// ```rust
112 /// fn main() {
113 ///     tokio::runtime::Builder::new_current_thread()
114 ///         .enable_all()
115 ///         .build()
116 ///         .unwrap()
117 ///         .block_on(async {
118 ///             println!("Hello world");
119 ///         })
120 /// }
121 /// ```
122 ///
123 /// ### Set number of worker threads
124 ///
125 /// ```rust
126 /// #[tokio::main(worker_threads = 2)]
127 /// async fn main() {
128 ///     println!("Hello world");
129 /// }
130 /// ```
131 ///
132 /// Equivalent code not using `#[tokio::main]`
133 ///
134 /// ```rust
135 /// fn main() {
136 ///     tokio::runtime::Builder::new_multi_thread()
137 ///         .worker_threads(2)
138 ///         .enable_all()
139 ///         .build()
140 ///         .unwrap()
141 ///         .block_on(async {
142 ///             println!("Hello world");
143 ///         })
144 /// }
145 /// ```
146 ///
147 /// ### Configure the runtime to start with time paused
148 ///
149 /// ```rust
150 /// #[tokio::main(flavor = "current_thread", start_paused = true)]
151 /// async fn main() {
152 ///     println!("Hello world");
153 /// }
154 /// ```
155 ///
156 /// Equivalent code not using `#[tokio::main]`
157 ///
158 /// ```rust
159 /// fn main() {
160 ///     tokio::runtime::Builder::new_current_thread()
161 ///         .enable_all()
162 ///         .start_paused(true)
163 ///         .build()
164 ///         .unwrap()
165 ///         .block_on(async {
166 ///             println!("Hello world");
167 ///         })
168 /// }
169 /// ```
170 ///
171 /// ### NOTE:
172 ///
173 /// If you rename the Tokio crate in your dependencies this macro will not work.
174 /// If you must rename the current version of Tokio because you're also using an
175 /// older version of Tokio, you _must_ make the current version of Tokio
176 /// available as `tokio` in the module where this macro is expanded.
177 #[proc_macro_attribute]
178 #[cfg(not(test))] // Work around for rust-lang/rust#62127
main(args: TokenStream, item: TokenStream) -> TokenStream179 pub fn main(args: TokenStream, item: TokenStream) -> TokenStream {
180     entry::main(args, item, true)
181 }
182 
183 /// Marks async function to be executed by selected runtime. This macro helps set up a `Runtime`
184 /// without requiring the user to use [Runtime](../tokio/runtime/struct.Runtime.html) or
185 /// [Builder](../tokio/runtime/struct.builder.html) directly.
186 ///
187 /// ## Function arguments:
188 ///
189 /// Arguments are allowed for any functions aside from `main` which is special
190 ///
191 /// ## Usage
192 ///
193 /// ### Using default
194 ///
195 /// ```rust
196 /// #[tokio::main(flavor = "current_thread")]
197 /// async fn main() {
198 ///     println!("Hello world");
199 /// }
200 /// ```
201 ///
202 /// Equivalent code not using `#[tokio::main]`
203 ///
204 /// ```rust
205 /// fn main() {
206 ///     tokio::runtime::Builder::new_current_thread()
207 ///         .enable_all()
208 ///         .build()
209 ///         .unwrap()
210 ///         .block_on(async {
211 ///             println!("Hello world");
212 ///         })
213 /// }
214 /// ```
215 ///
216 /// ### NOTE:
217 ///
218 /// If you rename the Tokio crate in your dependencies this macro will not work.
219 /// If you must rename the current version of Tokio because you're also using an
220 /// older version of Tokio, you _must_ make the current version of Tokio
221 /// available as `tokio` in the module where this macro is expanded.
222 #[proc_macro_attribute]
223 #[cfg(not(test))] // Work around for rust-lang/rust#62127
main_rt(args: TokenStream, item: TokenStream) -> TokenStream224 pub fn main_rt(args: TokenStream, item: TokenStream) -> TokenStream {
225     entry::main(args, item, false)
226 }
227 
228 /// Marks async function to be executed by runtime, suitable to test environment
229 ///
230 /// ## Usage
231 ///
232 /// ### Multi-thread runtime
233 ///
234 /// ```no_run
235 /// #[tokio::test(flavor = "multi_thread", worker_threads = 1)]
236 /// async fn my_test() {
237 ///     assert!(true);
238 /// }
239 /// ```
240 ///
241 /// ### Using default
242 ///
243 /// The default test runtime is single-threaded.
244 ///
245 /// ```no_run
246 /// #[tokio::test]
247 /// async fn my_test() {
248 ///     assert!(true);
249 /// }
250 /// ```
251 ///
252 /// ### Configure the runtime to start with time paused
253 ///
254 /// ```no_run
255 /// #[tokio::test(start_paused = true)]
256 /// async fn my_test() {
257 ///     assert!(true);
258 /// }
259 /// ```
260 ///
261 /// ### NOTE:
262 ///
263 /// If you rename the Tokio crate in your dependencies this macro will not work.
264 /// If you must rename the current version of Tokio because you're also using an
265 /// older version of Tokio, you _must_ make the current version of Tokio
266 /// available as `tokio` in the module where this macro is expanded.
267 #[proc_macro_attribute]
test(args: TokenStream, item: TokenStream) -> TokenStream268 pub fn test(args: TokenStream, item: TokenStream) -> TokenStream {
269     entry::test(args, item, true)
270 }
271 
272 /// Marks async function to be executed by runtime, suitable to test environment
273 ///
274 /// ## Usage
275 ///
276 /// ```no_run
277 /// #[tokio::test]
278 /// async fn my_test() {
279 ///     assert!(true);
280 /// }
281 /// ```
282 ///
283 /// ### NOTE:
284 ///
285 /// If you rename the Tokio crate in your dependencies this macro will not work.
286 /// If you must rename the current version of Tokio because you're also using an
287 /// older version of Tokio, you _must_ make the current version of Tokio
288 /// available as `tokio` in the module where this macro is expanded.
289 #[proc_macro_attribute]
test_rt(args: TokenStream, item: TokenStream) -> TokenStream290 pub fn test_rt(args: TokenStream, item: TokenStream) -> TokenStream {
291     entry::test(args, item, false)
292 }
293 
294 /// Always fails with the error message below.
295 /// ```text
296 /// The #[tokio::main] macro requires rt or rt-multi-thread.
297 /// ```
298 #[proc_macro_attribute]
main_fail(_args: TokenStream, _item: TokenStream) -> TokenStream299 pub fn main_fail(_args: TokenStream, _item: TokenStream) -> TokenStream {
300     syn::Error::new(
301         proc_macro2::Span::call_site(),
302         "The #[tokio::main] macro requires rt or rt-multi-thread.",
303     )
304     .to_compile_error()
305     .into()
306 }
307 
308 /// Always fails with the error message below.
309 /// ```text
310 /// The #[tokio::test] macro requires rt or rt-multi-thread.
311 /// ```
312 #[proc_macro_attribute]
test_fail(_args: TokenStream, _item: TokenStream) -> TokenStream313 pub fn test_fail(_args: TokenStream, _item: TokenStream) -> TokenStream {
314     syn::Error::new(
315         proc_macro2::Span::call_site(),
316         "The #[tokio::test] macro requires rt or rt-multi-thread.",
317     )
318     .to_compile_error()
319     .into()
320 }
321 
322 /// Implementation detail of the `select!` macro. This macro is **not** intended
323 /// to be used as part of the public API and is permitted to change.
324 #[proc_macro]
325 #[doc(hidden)]
select_priv_declare_output_enum(input: TokenStream) -> TokenStream326 pub fn select_priv_declare_output_enum(input: TokenStream) -> TokenStream {
327     select::declare_output_enum(input)
328 }
329