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
JobHandleresults 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.