# Coroutines and command execution

Source: https://libtmux.org/en/kotlin/latest/topics/execution/

> Choose bounded coroutine work and preserve uncertainty after cancellation.

A suspend function does not select control mode. Ordinary Kotlin operations use
the configured command transport; opening a persistent control client is an
explicit choice.

## Suspending and captured operations

| Operation | Execution boundary |
| --- | --- |
| Captured name, ID, size, or local selection | A local value; no tmux request. |
| A suspending read or mutation | Command work through [`ExecutionPolicy.commands`](<https://libtmux.org/en/kotlin/latest/reference/io-github-libtmux-kotlin-executionpolicy-commands/>). |
| The background pump for [`Server.liveState`](<https://libtmux.org/en/kotlin/latest/reference/io-github-libtmux-kotlin-server-livestate/>) | Blocking reads through [`ExecutionPolicy.streamReads`](<https://libtmux.org/en/kotlin/latest/reference/io-github-libtmux-kotlin-executionpolicy-streamreads/>). |
| [`ControlClient.output`](<https://libtmux.org/en/kotlin/latest/reference/io-github-libtmux-kotlin-controlclient-output/>) and [`ControlClient.events`](<https://libtmux.org/en/kotlin/latest/reference/io-github-libtmux-kotlin-controlclient-events/>) | Collected through subscription polling and readiness callbacks. |

The command pool is sized from the server configuration's command-admission
bound. A coroutine call still ultimately invokes blocking Java I/O; the wrapper
uses an interruptible boundary so the caller's coroutine does not block an
arbitrary application thread.

Bound the work you submit as well as the transport's admission. Starting an
unbounded number of coroutines can create a large waiting population even when
only a few commands run at once. Independent reads can run concurrently; a
sequence whose second operation depends on the first must retain that ordering.

## Cancellation ends waiting, not history

Cancellation interrupts the wrapper's wait. It cannot undo a command already
sent to tmux. A timeout therefore does not prove a mutation had no effect.
Preserve the underlying failure and any dispatch information before deciding
whether another attempt is safe.

Likewise, sending terminal input is distinct from waiting for a shell command or
application to finish. Use an operation with the required completion contract,
or an application-level readiness check. Echoing the supplied text alone is not
that evidence.

Use the [command and control programs](https://libtmux.org/en/kotlin/latest/concepts/transports/) to compare
client scopes. The [coroutines guide](https://libtmux.org/en/kotlin/latest/guides/coroutines/) explains the two
execution pools and the nonblocking subscription path; the
[API reference](https://libtmux.org/en/kotlin/latest/reference/) gives each operation's contract.
