Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Async, Concurrency, and Parallelism

Helix uses Tokio, but it is not architected as “put the editor in an Arc<Mutex<_>> and spawn everything.”

One foreground mutation authority

Application owns Editor, Compositor, Jobs, terminal state, signals, and configuration. Its select! loop serializes observable mutations. This removes an enormous class of races between a keystroke, an LSP reply, a save completion, and a redraw.

Background jobs return capabilities

Job contains a 'static + Send future. It may finish with a boxed FnOnce callback that accepts &mut Editor, or both &mut Editor and &mut Compositor.

foreground snapshots owned request data
        ↓
spawned future waits for I/O
        ↓
channel carries Callback, not &mut Editor
        ↓
event loop invokes callback with exclusive access

The future must own or clone everything it keeps across .await. The callback does not own the editor; it receives a temporary borrow only when the event loop is ready to apply the result.

Concurrency is not automatically parallelism

Terminal input, timers, saves, debugger traffic, jobs, and language servers can all be in progress concurrently. Tokio may poll spawned Send jobs in parallel on multiple runtime workers. Yet editing and UI callbacks are serialized. CPU parallelism is not the organizing principle here; responsiveness and ownership are.

LSP transport is an independent state machine

The transport loop selects between outbound client messages, server output, initialization, and process lifecycle. Requests issued before initialization are queued. A shutdown flag is stored before flushing shutdown bytes so the reader cannot misclassify a server request in that narrow window. This is async code implementing protocol ordering, not merely avoiding blocked threads.

Cancellation safety is local and explicit

The transport pins a notification future outside its select! loop because recreating it could lose a permit. Jobs that must complete before exit enter a FuturesUnordered; ordinary jobs are detached but report their errors through the status channel. These choices state which work may be abandoned and which work is part of a clean exit.