# Asynchronous Mode

By default the client runs in **synchronous mode**: each `run()` call
blocks until `!done` is received.  Asynchronous mode allows multiple
concurrent in-flight requests over the same connection.

---

## How it works

Calling `async_start()` launches a **daemon thread** that continuously
reads sentences from the socket.  Each outgoing request is tagged
(`r1`, `r2`, …) and the thread routes replies back to the correct caller
using that tag.

---

## Enabling async mode

```python
import routeros

with routeros.dial("192.168.1.1:8728", "admin", "") as c:
    c.async_start()          # start the background reader thread

    reply = c.run("/ip/address/print")
    print(reply.re)
```

`async_start()` must be called **at most once**.  Calling it a second time
raises `AlreadyAsyncError`.

---

## Concurrent requests

```python
import threading
import routeros

with routeros.dial("192.168.1.1:8728", "admin", "") as c:
    c.async_start()

    results = {}

    def fetch(command):
        results[command] = c.run(command)

    threads = [
        threading.Thread(target=fetch, args=("/ip/address/print",)),
        threading.Thread(target=fetch, args=("/interface/print",)),
        threading.Thread(target=fetch, args=("/system/resource/print",)),
    ]
    for t in threads:
        t.start()
    for t in threads:
        t.join()

    for cmd, reply in results.items():
        print(f"{cmd}: {len(reply.re)} rows")
```

---

## Listeners auto-enable async mode

`listen()` calls `async_start()` internally if async mode is not yet active:

```python
with routeros.dial("192.168.1.1:8728", "admin", "") as c:
    # No need to call c.async_start() first:
    listener = c.listen("/ip/firewall/address-list/listen")
    for sentence in listener:
        print(sentence.map)
```

---

## Thread safety

- `run()` is safe to call from multiple threads after `async_start()`.
- `listen()` is safe to call from any thread.
- `close()` is safe to call at any time; it unblocks all pending `run()` calls.

---

## Synchronous vs asynchronous comparison

| Feature | Sync (default) | Async |
|---|---|---|
| In-flight requests | 1 | Unlimited |
| Listener support | No (needs async) | Yes |
| Background thread | No | Yes (1 daemon thread) |
| Overhead | None | Minimal |
