tokio-macros provides Tokio’s procedural macros that simplify setting up and testing async code. These macros eliminate boilerplate when creating async entry points and tests.
Installation
The macros are re-exported by the maintokio crate, so you typically don’t need to add tokio-macros directly:
Cargo.toml
The
macros feature flag is required to use #[tokio::main] and #[tokio::test].The #[tokio::main] Macro
The#[tokio::main] macro transforms an async main function into a synchronous one that runs on the Tokio runtime.
Basic Usage
Runtime Flavors
Multi-threaded Runtime (Default)
The default flavor uses multiple threads:Configure Worker Threads
By default, the number of worker threads equals the number of CPU cores.
Current Thread Runtime
Use a single-threaded runtime:Multi-threaded with Explicit Flavor
Advanced Configuration
Start with Time Paused
Requires the
test-util feature flag.Custom Crate Name
If you’ve renamed thetokio crate:
The #[tokio::test] Macro
The#[tokio::test] macro enables writing async tests without manual runtime setup.
Basic Test
Multi-threaded Tests
Configure Test Workers
Tests with Paused Time
Requires the
test-util feature.Complete Examples
Simple HTTP Server
Testing Async Functions
Current Thread for Deterministic Tests
Comparison Table
Purpose
Runtime Flavors Comparison
Multi-threaded Runtime
Multi-threaded Runtime
- Best for: Production applications, CPU-bound tasks
- Features: Work-stealing scheduler, scales with CPU cores
- Trade-off: More overhead than current-thread
Current-thread Runtime
Current-thread Runtime
- Best for: Tests, single-threaded apps, WASM
- Features: Lightweight, deterministic execution
- Trade-off: Cannot utilize multiple cores
When to Use Each Macro
Use #[tokio::main]
- Application entry points
- Production services
- When you need full runtime control
Use #[tokio::test]
- Unit tests for async code
- Integration tests
- When testing time-based logic
Common Patterns
Error Handling
Non-main Async Functions
You can use#[tokio::main] on non-main functions, but this creates a new runtime each time:
Requirements
1
Enable macros feature
Add
macros to your Tokio features in Cargo.toml2
Choose runtime flavor
Use
rt-multi-thread for multi-threaded or rt for current-thread3
Add test-util for testing
Include
test-util feature for start_paused and time controlUtility Macros
Themacros feature also includes essential utility macros for working with multiple concurrent operations.
The join! Macro
Waits on multiple concurrent branches, returning when all branches complete.join! runs all futures concurrently on the same task and waits for all to complete, even if some return errors.Fairness Control
By default,join! rotates which future is polled first. Use biased; for deterministic order:
The try_join! Macro
Similar tojoin!, but returns early on the first Err:
All futures in
try_join! must return Result with the same error type.When to Use try_join!
The select! Macro
Waits on multiple concurrent branches, returning when the first branch completes:select! cancels the remaining branches when the first one completes. Ensure operations are cancellation-safe.Pattern Matching
Conditional Branches
Biased Polling
The else Branch
Without an
else branch, select! panics if all branches are disabled.Cancellation Safety
Some operations are cancellation-safe, others are not: Cancellation-safe operations:tokio::sync::mpsc::Receiver::recvtokio::sync::broadcast::Receiver::recvtokio::sync::watch::Receiver::changedtokio::net::TcpListener::accepttokio::io::AsyncReadExt::read(onTcpStream)
tokio::io::AsyncWriteExt::write_alltokio::io::AsyncReadExt::read_exact
Comparison: join! vs try_join! vs select!
Complete Example: Using All Three
Resources
API Documentation
Complete API reference on docs.rs
Tokio Runtime
Learn more about runtime configuration
GitHub Repository
View source code
Testing Guide
Best practices for testing async code