> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/tokio-rs/tokio/llms.txt
> Use this file to discover all available pages before exploring further.

# tokio-macros

> Procedural macros for Tokio including

`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 main `tokio` crate, so you typically don't need to add `tokio-macros` directly:

```toml Cargo.toml theme={null}
[dependencies]
tokio = { version = "1", features = ["macros", "rt-multi-thread"] }
```

<Note>
  The `macros` feature flag is required to use `#[tokio::main]` and `#[tokio::test]`.
</Note>

## 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

```rust theme={null}
#[tokio::main]
async fn main() {
    println!("Hello world");
}
```

This expands to:

```rust theme={null}
fn main() {
    tokio::runtime::Builder::new_multi_thread()
        .enable_all()
        .build()
        .unwrap()
        .block_on(async {
            println!("Hello world");
        })
}
```

<Tip>
  The macro handles runtime setup automatically, making async code more ergonomic.
</Tip>

## Runtime Flavors

### Multi-threaded Runtime (Default)

The default flavor uses multiple threads:

```rust theme={null}
#[tokio::main]
async fn main() {
    // Runs on multi-threaded runtime
    println!("Hello from multiple threads!");
}
```

### Configure Worker Threads

```rust theme={null}
#[tokio::main(worker_threads = 4)]
async fn main() {
    println!("Running on 4 worker threads");
}
```

<Note>
  By default, the number of worker threads equals the number of CPU cores.
</Note>

### Current Thread Runtime

Use a single-threaded runtime:

```rust theme={null}
#[tokio::main(flavor = "current_thread")]
async fn main() {
    println!("Running on a single thread");
}
```

This expands to:

```rust theme={null}
fn main() {
    tokio::runtime::Builder::new_current_thread()
        .enable_all()
        .build()
        .unwrap()
        .block_on(async {
            println!("Running on a single thread");
        })
}
```

### Multi-threaded with Explicit Flavor

```rust theme={null}
#[tokio::main(flavor = "multi_thread", worker_threads = 8)]
async fn main() {
    println!("Explicitly multi-threaded with 8 workers");
}
```

## Advanced Configuration

### Start with Time Paused

<Info>
  Requires the `test-util` feature flag.
</Info>

```rust theme={null}
#[tokio::main(flavor = "current_thread", start_paused = true)]
async fn main() {
    // Time starts paused - useful for testing
    tokio::time::advance(tokio::time::Duration::from_secs(1)).await;
}
```

### Custom Crate Name

If you've renamed the `tokio` crate:

```rust theme={null}
use tokio as tokio1;

#[tokio1::main(crate = "tokio1")]
async fn main() {
    println!("Hello world");
}
```

## The #\[tokio::test] Macro

The `#[tokio::test]` macro enables writing async tests without manual runtime setup.

### Basic Test

```rust theme={null}
#[tokio::test]
async fn my_test() {
    let result = async_operation().await;
    assert_eq!(result, expected_value);
}
```

This expands to:

```rust theme={null}
#[test]
fn my_test() {
    tokio::runtime::Builder::new_current_thread()
        .enable_all()
        .build()
        .unwrap()
        .block_on(async {
            let result = async_operation().await;
            assert_eq!(result, expected_value);
        })
}
```

### Multi-threaded Tests

```rust theme={null}
#[tokio::test(flavor = "multi_thread")]
async fn concurrent_test() {
    let handle1 = tokio::spawn(async { 1 });
    let handle2 = tokio::spawn(async { 2 });

    let result1 = handle1.await.unwrap();
    let result2 = handle2.await.unwrap();

    assert_eq!(result1 + result2, 3);
}
```

### Configure Test Workers

```rust theme={null}
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn parallel_test() {
    // Test runs with 2 worker threads
    assert!(true);
}
```

### Tests with Paused Time

<Info>
  Requires the `test-util` feature.
</Info>

```rust theme={null}
#[tokio::test(start_paused = true)]
async fn time_based_test() {
    let start = tokio::time::Instant::now();

    // Advance time by 1 second instantly
    tokio::time::advance(tokio::time::Duration::from_secs(1)).await;

    let elapsed = start.elapsed();
    assert!(elapsed >= tokio::time::Duration::from_secs(1));
}
```

<Tip>
  Starting tests with paused time is extremely useful for testing time-dependent code without actual delays.
</Tip>

## Complete Examples

### Simple HTTP Server

```rust theme={null}
use tokio::net::TcpListener;
use tokio::io::{AsyncReadExt, AsyncWriteExt};

#[tokio::main]
async fn main() -> std::io::Result<()> {
    let listener = TcpListener::bind("127.0.0.1:8080").await?;
    println!("Server running on port 8080");

    loop {
        let (mut socket, addr) = listener.accept().await?;
        println!("New connection from: {}", addr);

        tokio::spawn(async move {
            let mut buf = [0; 1024];
            loop {
                let n = socket.read(&mut buf).await.unwrap();
                if n == 0 {
                    return;
                }
                socket.write_all(&buf[0..n]).await.unwrap();
            }
        });
    }
}
```

### Testing Async Functions

```rust theme={null}
use tokio::time::{sleep, Duration};

async fn fetch_data() -> Result<String, ()> {
    sleep(Duration::from_millis(100)).await;
    Ok("data".to_string())
}

#[tokio::test]
async fn test_fetch_data() {
    let result = fetch_data().await;
    assert!(result.is_ok());
    assert_eq!(result.unwrap(), "data");
}

#[tokio::test(start_paused = true)]
async fn test_fetch_data_no_delay() {
    // With paused time, no actual delay occurs
    let result = fetch_data().await;
    assert!(result.is_ok());
}

#[tokio::test(flavor = "multi_thread", worker_threads = 4)]
async fn test_concurrent_fetches() {
    let handles: Vec<_> = (0..10)
        .map(|_| tokio::spawn(fetch_data()))
        .collect();

    for handle in handles {
        assert!(handle.await.unwrap().is_ok());
    }
}
```

### Current Thread for Deterministic Tests

```rust theme={null}
#[tokio::test(flavor = "current_thread")]
async fn deterministic_test() {
    // Single-threaded ensures deterministic execution order
    let mut counter = 0;

    let task1 = async {
        counter += 1;
        counter
    };

    let task2 = async {
        counter += 2;
        counter
    };

    let result1 = task1.await;
    let result2 = task2.await;

    assert_eq!(result1, 1);
    assert_eq!(result2, 3);
}
```

## Comparison Table

<ResponseField name="Macro" type="Purpose">
  | Macro            | Purpose             | Default Runtime |
  | ---------------- | ------------------- | --------------- |
  | `#[tokio::main]` | Async main function | Multi-threaded  |
  | `#[tokio::test]` | Async test function | Current-thread  |
</ResponseField>

## Runtime Flavors Comparison

<AccordionGroup>
  <Accordion title="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
  </Accordion>

  <Accordion title="Current-thread Runtime">
    * **Best for**: Tests, single-threaded apps, WASM
    * **Features**: Lightweight, deterministic execution
    * **Trade-off**: Cannot utilize multiple cores
  </Accordion>
</AccordionGroup>

## When to Use Each Macro

<CardGroup cols={2}>
  <Card title="Use #[tokio::main]" icon="play">
    * Application entry points
    * Production services
    * When you need full runtime control
  </Card>

  <Card title="Use #[tokio::test]" icon="flask">
    * Unit tests for async code
    * Integration tests
    * When testing time-based logic
  </Card>
</CardGroup>

## Common Patterns

### Error Handling

```rust theme={null}
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let result = risky_operation().await?;
    println!("Success: {}", result);
    Ok(())
}
```

### Non-main Async Functions

You can use `#[tokio::main]` on non-main functions, but this creates a new runtime each time:

```rust theme={null}
#[tokio::main]
async fn process_data() {
    // This spawns a new runtime every call
    // Consider passing a runtime handle instead
}
```

<Warning>
  Using `#[tokio::main]` on frequently-called functions is inefficient. Consider using `Runtime::block_on` or passing runtime handles instead.
</Warning>

## Requirements

<Steps>
  <Step title="Enable macros feature">
    Add `macros` to your Tokio features in `Cargo.toml`
  </Step>

  <Step title="Choose runtime flavor">
    Use `rt-multi-thread` for multi-threaded or `rt` for current-thread
  </Step>

  <Step title="Add test-util for testing">
    Include `test-util` feature for `start_paused` and time control
  </Step>
</Steps>

## Utility Macros

The `macros` 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.

```rust theme={null}
use tokio::join;

async fn fetch_user() -> String {
    // async work
    "user".to_string()
}

async fn fetch_posts() -> Vec<String> {
    // async work
    vec!["post1".to_string(), "post2".to_string()]
}

#[tokio::main]
async fn main() {
    let (user, posts) = join!(
        fetch_user(),
        fetch_posts()
    );
    
    println!("User: {}, Posts: {:?}", user, posts);
}
```

<Note>
  `join!` runs all futures concurrently on the same task and waits for **all** to complete, even if some return errors.
</Note>

#### Fairness Control

By default, `join!` rotates which future is polled first. Use `biased;` for deterministic order:

```rust theme={null}
let (a, b, c) = tokio::join!(
    biased;
    future_a(),
    future_b(),
    future_c()
);
```

<Tip>
  Use `join!` when you need results from multiple independent operations and all must complete.
</Tip>

### The try\_join! Macro

Similar to `join!`, but returns early on the first `Err`:

```rust theme={null}
use tokio::try_join;

async fn fetch_user() -> Result<String, Box<dyn std::error::Error>> {
    Ok("user".to_string())
}

async fn fetch_settings() -> Result<String, Box<dyn std::error::Error>> {
    Ok("settings".to_string())
}

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let (user, settings) = try_join!(
        fetch_user(),
        fetch_settings()
    )?;
    
    println!("User: {}, Settings: {}", user, settings);
    Ok(())
}
```

<Note>
  All futures in `try_join!` must return `Result` with the **same** error type.
</Note>

#### When to Use try\_join!

```rust theme={null}
// Good: All operations must succeed
let (user, profile, settings) = try_join!(
    db.fetch_user(),
    db.fetch_profile(),
    db.fetch_settings()
)?;

// Bad: Different error handling needed
// Use join! and handle errors individually instead
```

### The select! Macro

Waits on multiple concurrent branches, returning when the **first** branch completes:

```rust theme={null}
use tokio::select;
use tokio::sync::mpsc;

#[tokio::main]
async fn main() {
    let (tx, mut rx) = mpsc::channel::<i32>(100);
    
    loop {
        select! {
            Some(value) = rx.recv() => {
                println!("Got: {}", value);
            }
            _ = tokio::signal::ctrl_c() => {
                println!("Shutting down");
                break;
            }
        }
    }
}
```

<Note>
  `select!` cancels the remaining branches when the first one completes. Ensure operations are cancellation-safe.
</Note>

#### Pattern Matching

```rust theme={null}
select! {
    // Pattern match on result
    Ok(n) = reader.read(&mut buf) => {
        println!("Read {} bytes", n);
    }
    // Bind to variable
    msg = rx.recv() => {
        if let Some(m) = msg {
            process(m);
        }
    }
    // Multiple patterns
    result = operation() => match result {
        Ok(val) => handle_success(val),
        Err(e) => handle_error(e),
    }
}
```

#### Conditional Branches

```rust theme={null}
let mut do_shutdown = false;

loop {
    select! {
        msg = rx.recv(), if !do_shutdown => {
            // Only poll rx when not shutting down
            process(msg);
        }
        _ = shutdown_rx.recv() => {
            do_shutdown = true;
        }
    }
}
```

#### Biased Polling

```rust theme={null}
select! {
    biased;
    
    // Shutdown is checked first every time
    _ = shutdown_signal.recv() => {
        return;
    }
    // Then check for messages
    msg = message_rx.recv() => {
        process(msg);
    }
}
```

<Warning>
  Biased polling can cause starvation. Place high-priority operations first, but ensure fairness for all branches.
</Warning>

#### The else Branch

```rust theme={null}
select! {
    msg = rx.recv() => {
        println!("Received: {:?}", msg);
    }
    else => {
        // All branches disabled, execute fallback
        println!("No messages available");
    }
}
```

<Info>
  Without an `else` branch, `select!` panics if all branches are disabled.
</Info>

#### Cancellation Safety

Some operations are cancellation-safe, others are not:

**Cancellation-safe operations:**

* `tokio::sync::mpsc::Receiver::recv`
* `tokio::sync::broadcast::Receiver::recv`
* `tokio::sync::watch::Receiver::changed`
* `tokio::net::TcpListener::accept`
* `tokio::io::AsyncReadExt::read` (on `TcpStream`)

**NOT cancellation-safe:**

* `tokio::io::AsyncWriteExt::write_all`
* `tokio::io::AsyncReadExt::read_exact`

```rust theme={null}
use tokio::io::{AsyncReadExt, AsyncWriteExt};

// ❌ Bad: write_all may partially write
select! {
    _ = socket.write_all(&buf) => { }
    _ = shutdown.recv() => { }
}

// ✅ Good: Complete the write, then check shutdown
let write_fut = socket.write_all(&buf);
tokio::pin!(write_fut);

loop {
    select! {
        result = &mut write_fut => {
            result?;
            break;
        }
        _ = shutdown.recv() => {
            // Wait for write to complete before shutdown
            write_fut.await?;
            break;
        }
    }
}
```

### Comparison: join! vs try\_join! vs select!

| Macro       | Waits for    | Returns on              | Use Case                                      |
| ----------- | ------------ | ----------------------- | --------------------------------------------- |
| `join!`     | All futures  | All complete            | Independent operations, all results needed    |
| `try_join!` | All futures  | First `Err` or all `Ok` | Operations that must all succeed              |
| `select!`   | First future | First complete          | Racing operations, timeouts, shutdown signals |

### Complete Example: Using All Three

```rust theme={null}
use tokio::{join, try_join, select};
use tokio::time::{sleep, Duration, timeout};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // join! - Wait for all independent operations
    let (users, posts, comments) = join!(
        fetch_users(),
        fetch_posts(),
        fetch_comments()
    );
    
    // try_join! - All must succeed
    let (profile, settings) = try_join!(
        save_profile(&users),
        save_settings(&posts)
    )?;
    
    // select! - First to complete wins
    select! {
        result = process_data() => {
            println!("Processing completed: {:?}", result);
        }
        _ = sleep(Duration::from_secs(10)) => {
            println!("Processing timed out");
        }
    }
    
    Ok(())
}

async fn fetch_users() -> Vec<String> { vec![] }
async fn fetch_posts() -> Vec<String> { vec![] }
async fn fetch_comments() -> Vec<String> { vec![] }
async fn save_profile(users: &[String]) -> Result<(), Box<dyn std::error::Error>> { Ok(()) }
async fn save_settings(posts: &[String]) -> Result<(), Box<dyn std::error::Error>> { Ok(()) }
async fn process_data() -> Result<(), Box<dyn std::error::Error>> { Ok(()) }
```

## Resources

<CardGroup cols={2}>
  <Card title="API Documentation" icon="book" href="https://docs.rs/tokio-macros">
    Complete API reference on docs.rs
  </Card>

  <Card title="Tokio Runtime" icon="gear" href="https://docs.rs/tokio/latest/tokio/runtime/">
    Learn more about runtime configuration
  </Card>

  <Card title="GitHub Repository" icon="github" href="https://github.com/tokio-rs/tokio/tree/master/tokio-macros">
    View source code
  </Card>

  <Card title="Testing Guide" icon="vial" href="https://tokio.rs/tokio/topics/testing">
    Best practices for testing async code
  </Card>
</CardGroup>
