# Part VI: Concurrency

**In this part:**

- [Async/Await](#asyncawait) - Async functions, async walkers, async for
- [Concurrent Expressions](#concurrent-expressions) - flow/wait for parallel tasks

---

Jac supports Python-style `async/await` for concurrent I/O operations, plus a unique `flow/wait` syntax for launching and collecting parallel tasks. Use async when you need non-blocking I/O (like HTTP requests), and `flow` when you want to run multiple independent operations concurrently.

## Async/Await

!!! note
    Async functions must be `await`ed in an async context. In `with entry` blocks, use `await` directly or wrap calls in an async ability.

The `async/await` syntax works like Python's -- `async` marks a function as a coroutine, and `await` suspends execution until the awaited operation completes. Walkers can also be async, enabling non-blocking graph traversal with I/O at each node.

### 1 Async Functions

```jac
async def fetch_data(url: str) -> dict {
    response = await http_get(url);
    return await response.json();
}

async def process_multiple(urls: list[str]) -> list[dict] {
    results = [];
    for url in urls {
        data = await fetch_data(url);
        results.append(data);
    }
    return results;
}
```

### 2 Async Walkers

```jac
async walker DataFetcher {
    has url: str;

    async can fetch with Root entry {
        data = await http_get(self.url);
        report data;
    }
}
```

Use `async walker` for non-blocking I/O during traversal.

### 3 Async For Loops

```jac
async def process_stream(stream: AsyncIterator) -> None {
    async for item in stream {
        print(item);
    }
}
```

---

## Concurrent Expressions

The `flow/wait` pattern provides explicit concurrency control. `flow` launches a task and immediately returns a future (without blocking), while `wait` retrieves the result (blocking if necessary). This is more explicit than async/await -- you decide exactly when to start parallel work and when to synchronize.

### 1 flow Keyword

The `flow` keyword launches a function call as a background task and returns a future immediately. Use it when you have independent operations that can run in parallel.

```jac
def expensive_computation -> int {
    return 42;
}

def do_something_else -> int {
    return 1;
}

with entry {
    future = flow expensive_computation();

    # Do other work while computation runs
    other_result = do_something_else();

    # Wait for result when needed
    result = wait future;
}
```

### 2 Parallel Operations

```jac
def fetch_users -> list {
    return [];
}

def fetch_orders -> list {
    return [];
}

def fetch_inventory -> list {
    return [];
}

def process_local_data {
    # Process local data here
}

with entry {
    # Launch multiple operations in parallel
    future1 = flow fetch_users();
    future2 = flow fetch_orders();
    future3 = flow fetch_inventory();

    # Continue with other work
    process_local_data();

    # Collect all results
    users = wait future1;
    orders = wait future2;
    inventory = wait future3;
}
```

### 3 flow vs async

| Feature | async/await | flow/wait |
|---------|-------------|-----------|
| Model | Event loop (cooperative) | Thread pool (parallel) |
| Best for | I/O-bound, many concurrent | CPU-bound, few concurrent |
| Blocking | Non-blocking | Can block threads |

---

## Learn More

**Related Reference:**

- [Part I: Foundation](foundation.md) - Control flow basics
- [Part V: AI Integration](../plugins/byllm.md) - Async LLM calls
