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)] |
18 | extern crate proc_macro; |
19 | |
20 | mod entry; |
21 | mod select; |
22 | |
23 | use 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 |
206 | pub 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 |
271 | pub 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 ] |
428 | pub 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 ] |
443 | pub 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 ] |
452 | pub 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 ] |
466 | pub 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)] |
479 | pub 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)] |
487 | pub fn select_priv_clean_pattern(input: TokenStream) -> TokenStream { |
488 | select::clean_pattern_macro(input) |
489 | } |
490 | |