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

One Queue, Concurrent Execution

One queue does not imply one running job. It is like one line feeding several cashiers:

waiting: [C, D, E]       running: {A, B}
                         limit: 2

The dispatcher owns the MPSC receiver and a JoinSet. It receives a new job only when running.len() < concurrency_limit, then spawns it. Completion order is independent of FIFO admission order.

The queue and limit bound different resources:

  • queue capacity bounds work accepted but not started;
  • concurrency bounds futures currently performing I/O;
  • retained, completed JobHandle results are a third memory category and are not globally bounded by either setting.

The implementation uses Sender::reserve().await before constructing the oneshot wrapper. This is backpressure: a full queue suspends the submitting future without blocking an OS thread. After obtaining the permit, submission rechecks shutdown state and either commits the job or returns SubmitError.

CPU-heavy work does not become cooperative merely because it is inside an async block. Such jobs should cross into spawn_blocking or Rayon; otherwise they can monopolize Tokio worker threads despite the runner’s count limit.