| #![allow(clippy::needless_doctest_main)] |
| #![warn( |
| missing_debug_implementations, |
| missing_docs, |
| rust_2018_idioms, |
| unreachable_pub |
| )] |
| #![doc(test( |
| no_crate_inject, |
| attr(deny(warnings, rust_2018_idioms), allow(dead_code, unused_variables)) |
| ))] |
| |
| //! Macros for use with Tokio |
| |
| // This `extern` is required for older `rustc` versions but newer `rustc` |
| // versions warn about the unused `extern crate`. |
| #[allow(unused_extern_crates)] |
| extern crate proc_macro; |
| |
| mod entry; |
| mod select; |
| |
| use proc_macro::TokenStream; |
| |
| /// Marks async function to be executed by the selected runtime. This macro |
| /// helps set up a `Runtime` without requiring the user to use |
| /// [Runtime](../tokio/runtime/struct.Runtime.html) or |
| /// [Builder](../tokio/runtime/struct.Builder.html) directly. |
| /// |
| /// Note: This macro is designed to be simplistic and targets applications that |
| /// do not require a complex setup. If the provided functionality is not |
| /// sufficient, you may be interested in using |
| /// [Builder](../tokio/runtime/struct.Builder.html), which provides a more |
| /// powerful interface. |
| /// |
| /// Note: This macro can be used on any function and not just the `main` |
| /// function. Using it on a non-main function makes the function behave as if it |
| /// was synchronous by starting a new runtime each time it is called. If the |
| /// function is called often, it is preferable to create the runtime using the |
| /// runtime builder so the runtime can be reused across calls. |
| /// |
| /// # Multi-threaded runtime |
| /// |
| /// To use the multi-threaded runtime, the macro can be configured using |
| /// |
| /// ``` |
| /// #[tokio::main(flavor = "multi_thread", worker_threads = 10)] |
| /// # async fn main() {} |
| /// ``` |
| /// |
| /// The `worker_threads` option configures the number of worker threads, and |
| /// defaults to the number of cpus on the system. This is the default flavor. |
| /// |
| /// Note: The multi-threaded runtime requires the `rt-multi-thread` feature |
| /// flag. |
| /// |
| /// # Current thread runtime |
| /// |
| /// To use the single-threaded runtime known as the `current_thread` runtime, |
| /// the macro can be configured using |
| /// |
| /// ``` |
| /// #[tokio::main(flavor = "current_thread")] |
| /// # async fn main() {} |
| /// ``` |
| /// |
| /// ## Function arguments: |
| /// |
| /// Arguments are allowed for any functions aside from `main` which is special |
| /// |
| /// ## Usage |
| /// |
| /// ### Using the multi-thread runtime |
| /// |
| /// ```rust |
| /// #[tokio::main] |
| /// async fn main() { |
| /// println!("Hello world"); |
| /// } |
| /// ``` |
| /// |
| /// Equivalent code not using `#[tokio::main]` |
| /// |
| /// ```rust |
| /// fn main() { |
| /// tokio::runtime::Builder::new_multi_thread() |
| /// .enable_all() |
| /// .build() |
| /// .unwrap() |
| /// .block_on(async { |
| /// println!("Hello world"); |
| /// }) |
| /// } |
| /// ``` |
| /// |
| /// ### Using current thread runtime |
| /// |
| /// The basic scheduler is single-threaded. |
| /// |
| /// ```rust |
| /// #[tokio::main(flavor = "current_thread")] |
| /// async fn main() { |
| /// println!("Hello world"); |
| /// } |
| /// ``` |
| /// |
| /// Equivalent code not using `#[tokio::main]` |
| /// |
| /// ```rust |
| /// fn main() { |
| /// tokio::runtime::Builder::new_current_thread() |
| /// .enable_all() |
| /// .build() |
| /// .unwrap() |
| /// .block_on(async { |
| /// println!("Hello world"); |
| /// }) |
| /// } |
| /// ``` |
| /// |
| /// ### Set number of worker threads |
| /// |
| /// ```rust |
| /// #[tokio::main(worker_threads = 2)] |
| /// async fn main() { |
| /// println!("Hello world"); |
| /// } |
| /// ``` |
| /// |
| /// Equivalent code not using `#[tokio::main]` |
| /// |
| /// ```rust |
| /// fn main() { |
| /// tokio::runtime::Builder::new_multi_thread() |
| /// .worker_threads(2) |
| /// .enable_all() |
| /// .build() |
| /// .unwrap() |
| /// .block_on(async { |
| /// println!("Hello world"); |
| /// }) |
| /// } |
| /// ``` |
| /// |
| /// ### Configure the runtime to start with time paused |
| /// |
| /// ```rust |
| /// #[tokio::main(flavor = "current_thread", start_paused = true)] |
| /// async fn main() { |
| /// println!("Hello world"); |
| /// } |
| /// ``` |
| /// |
| /// Equivalent code not using `#[tokio::main]` |
| /// |
| /// ```rust |
| /// fn main() { |
| /// tokio::runtime::Builder::new_current_thread() |
| /// .enable_all() |
| /// .start_paused(true) |
| /// .build() |
| /// .unwrap() |
| /// .block_on(async { |
| /// println!("Hello world"); |
| /// }) |
| /// } |
| /// ``` |
| /// |
| /// Note that `start_paused` requires the `test-util` feature to be enabled. |
| /// |
| /// ### Rename package |
| /// |
| /// ```rust |
| /// use tokio as tokio1; |
| /// |
| /// #[tokio1::main(crate = "tokio1")] |
| /// async fn main() { |
| /// println!("Hello world"); |
| /// } |
| /// ``` |
| /// |
| /// Equivalent code not using `#[tokio::main]` |
| /// |
| /// ```rust |
| /// use tokio as tokio1; |
| /// |
| /// fn main() { |
| /// tokio1::runtime::Builder::new_multi_thread() |
| /// .enable_all() |
| /// .build() |
| /// .unwrap() |
| /// .block_on(async { |
| /// println!("Hello world"); |
| /// }) |
| /// } |
| /// ``` |
| #[proc_macro_attribute] |
| #[cfg(not(test))] // Work around for rust-lang/rust#62127 |
| pub fn main(args: TokenStream, item: TokenStream) -> TokenStream { |
| entry::main(args, item, true) |
| } |
| |
| /// Marks async function to be executed by selected runtime. This macro helps set up a `Runtime` |
| /// without requiring the user to use [Runtime](../tokio/runtime/struct.Runtime.html) or |
| /// [Builder](../tokio/runtime/struct.builder.html) directly. |
| /// |
| /// ## Function arguments: |
| /// |
| /// Arguments are allowed for any functions aside from `main` which is special |
| /// |
| /// ## Usage |
| /// |
| /// ### Using default |
| /// |
| /// ```rust |
| /// #[tokio::main(flavor = "current_thread")] |
| /// async fn main() { |
| /// println!("Hello world"); |
| /// } |
| /// ``` |
| /// |
| /// Equivalent code not using `#[tokio::main]` |
| /// |
| /// ```rust |
| /// fn main() { |
| /// tokio::runtime::Builder::new_current_thread() |
| /// .enable_all() |
| /// .build() |
| /// .unwrap() |
| /// .block_on(async { |
| /// println!("Hello world"); |
| /// }) |
| /// } |
| /// ``` |
| /// |
| /// ### Rename package |
| /// |
| /// ```rust |
| /// use tokio as tokio1; |
| /// |
| /// #[tokio1::main(crate = "tokio1")] |
| /// async fn main() { |
| /// println!("Hello world"); |
| /// } |
| /// ``` |
| /// |
| /// Equivalent code not using `#[tokio::main]` |
| /// |
| /// ```rust |
| /// use tokio as tokio1; |
| /// |
| /// fn main() { |
| /// tokio1::runtime::Builder::new_multi_thread() |
| /// .enable_all() |
| /// .build() |
| /// .unwrap() |
| /// .block_on(async { |
| /// println!("Hello world"); |
| /// }) |
| /// } |
| /// ``` |
| #[proc_macro_attribute] |
| #[cfg(not(test))] // Work around for rust-lang/rust#62127 |
| pub fn main_rt(args: TokenStream, item: TokenStream) -> TokenStream { |
| entry::main(args, item, false) |
| } |
| |
| /// Marks async function to be executed by runtime, suitable to test environment. |
| /// This macro helps set up a `Runtime` without requiring the user to use |
| /// [Runtime](../tokio/runtime/struct.Runtime.html) or |
| /// [Builder](../tokio/runtime/struct.Builder.html) directly. |
| /// |
| /// Note: This macro is designed to be simplistic and targets applications that |
| /// do not require a complex setup. If the provided functionality is not |
| /// sufficient, you may be interested in using |
| /// [Builder](../tokio/runtime/struct.Builder.html), which provides a more |
| /// powerful interface. |
| /// |
| /// # Multi-threaded runtime |
| /// |
| /// To use the multi-threaded runtime, the macro can be configured using |
| /// |
| /// ```no_run |
| /// #[tokio::test(flavor = "multi_thread", worker_threads = 1)] |
| /// async fn my_test() { |
| /// assert!(true); |
| /// } |
| /// ``` |
| /// |
| /// The `worker_threads` option configures the number of worker threads, and |
| /// defaults to the number of cpus on the system. This is the default |
| /// flavor. |
| /// |
| /// Note: The multi-threaded runtime requires the `rt-multi-thread` feature |
| /// flag. |
| /// |
| /// # Current thread runtime |
| /// |
| /// The default test runtime is single-threaded. Each test gets a |
| /// separate current-thread runtime. |
| /// |
| /// ```no_run |
| /// #[tokio::test] |
| /// async fn my_test() { |
| /// assert!(true); |
| /// } |
| /// ``` |
| /// |
| /// ## Usage |
| /// |
| /// ### Using the multi-thread runtime |
| /// |
| /// ```no_run |
| /// #[tokio::test(flavor = "multi_thread")] |
| /// async fn my_test() { |
| /// assert!(true); |
| /// } |
| /// ``` |
| /// |
| /// Equivalent code not using `#[tokio::test]` |
| /// |
| /// ```no_run |
| /// #[test] |
| /// fn my_test() { |
| /// tokio::runtime::Builder::new_multi_thread() |
| /// .enable_all() |
| /// .build() |
| /// .unwrap() |
| /// .block_on(async { |
| /// assert!(true); |
| /// }) |
| /// } |
| /// ``` |
| /// |
| /// ### Using current thread runtime |
| /// |
| /// ```no_run |
| /// #[tokio::test] |
| /// async fn my_test() { |
| /// assert!(true); |
| /// } |
| /// ``` |
| /// |
| /// Equivalent code not using `#[tokio::test]` |
| /// |
| /// ```no_run |
| /// #[test] |
| /// fn my_test() { |
| /// tokio::runtime::Builder::new_current_thread() |
| /// .enable_all() |
| /// .build() |
| /// .unwrap() |
| /// .block_on(async { |
| /// assert!(true); |
| /// }) |
| /// } |
| /// ``` |
| /// |
| /// ### Set number of worker threads |
| /// |
| /// ```no_run |
| /// #[tokio::test(flavor ="multi_thread", worker_threads = 2)] |
| /// async fn my_test() { |
| /// assert!(true); |
| /// } |
| /// ``` |
| /// |
| /// Equivalent code not using `#[tokio::test]` |
| /// |
| /// ```no_run |
| /// #[test] |
| /// fn my_test() { |
| /// tokio::runtime::Builder::new_multi_thread() |
| /// .worker_threads(2) |
| /// .enable_all() |
| /// .build() |
| /// .unwrap() |
| /// .block_on(async { |
| /// assert!(true); |
| /// }) |
| /// } |
| /// ``` |
| /// |
| /// ### Configure the runtime to start with time paused |
| /// |
| /// ```no_run |
| /// #[tokio::test(start_paused = true)] |
| /// async fn my_test() { |
| /// assert!(true); |
| /// } |
| /// ``` |
| /// |
| /// Equivalent code not using `#[tokio::test]` |
| /// |
| /// ```no_run |
| /// #[test] |
| /// fn my_test() { |
| /// tokio::runtime::Builder::new_current_thread() |
| /// .enable_all() |
| /// .start_paused(true) |
| /// .build() |
| /// .unwrap() |
| /// .block_on(async { |
| /// assert!(true); |
| /// }) |
| /// } |
| /// ``` |
| /// |
| /// Note that `start_paused` requires the `test-util` feature to be enabled. |
| /// |
| /// ### Rename package |
| /// |
| /// ```rust |
| /// use tokio as tokio1; |
| /// |
| /// #[tokio1::test(crate = "tokio1")] |
| /// async fn my_test() { |
| /// println!("Hello world"); |
| /// } |
| /// ``` |
| #[proc_macro_attribute] |
| pub fn test(args: TokenStream, item: TokenStream) -> TokenStream { |
| entry::test(args, item, true) |
| } |
| |
| /// Marks async function to be executed by runtime, suitable to test environment |
| /// |
| /// ## Usage |
| /// |
| /// ```no_run |
| /// #[tokio::test] |
| /// async fn my_test() { |
| /// assert!(true); |
| /// } |
| /// ``` |
| #[proc_macro_attribute] |
| pub fn test_rt(args: TokenStream, item: TokenStream) -> TokenStream { |
| entry::test(args, item, false) |
| } |
| |
| /// Always fails with the error message below. |
| /// ```text |
| /// The #[tokio::main] macro requires rt or rt-multi-thread. |
| /// ``` |
| #[proc_macro_attribute] |
| pub fn main_fail(_args: TokenStream, _item: TokenStream) -> TokenStream { |
| syn::Error::new( |
| proc_macro2::Span::call_site(), |
| "The #[tokio::main] macro requires rt or rt-multi-thread.", |
| ) |
| .to_compile_error() |
| .into() |
| } |
| |
| /// Always fails with the error message below. |
| /// ```text |
| /// The #[tokio::test] macro requires rt or rt-multi-thread. |
| /// ``` |
| #[proc_macro_attribute] |
| pub fn test_fail(_args: TokenStream, _item: TokenStream) -> TokenStream { |
| syn::Error::new( |
| proc_macro2::Span::call_site(), |
| "The #[tokio::test] macro requires rt or rt-multi-thread.", |
| ) |
| .to_compile_error() |
| .into() |
| } |
| |
| /// Implementation detail of the `select!` macro. This macro is **not** intended |
| /// to be used as part of the public API and is permitted to change. |
| #[proc_macro] |
| #[doc(hidden)] |
| pub fn select_priv_declare_output_enum(input: TokenStream) -> TokenStream { |
| select::declare_output_enum(input) |
| } |
| |
| /// Implementation detail of the `select!` macro. This macro is **not** intended |
| /// to be used as part of the public API and is permitted to change. |
| #[proc_macro] |
| #[doc(hidden)] |
| pub fn select_priv_clean_pattern(input: TokenStream) -> TokenStream { |
| select::clean_pattern_macro(input) |
| } |