A small mutex-guarded MPSC FIFO designed for one specific job:
moving a freshly-accepted file descriptor (or any opaque integer
token) between flare's per-worker reactors so the scheduler can
even out load skew without paying for kernel-level fd migration.
Why this exists
flare's multicore mode (HttpServer.serve(... num_workers=N))
leans on Linux's SO_REUSEPORT for accept distribution. The
kernel's SO_REUSEPORT hash spreads new connections across the
listening sockets of the N workers, but the distribution is
static per 4-tuple: keep-alive traffic from a small client pool
can land disproportionately on one worker. The
benchmark/results//multicore run logs P99.9 tails ~0.5×
worse on one worker compared to its three siblings under skewed
keep-alive — see the design doc for numbers.
What it is
:class:HandoffQueue is a bounded MPSC FIFO of opaque Int
slots (file descriptors or scheduler tokens). One owning thread
(the worker) calls :meth:pop to drain the queue under its own
reactor lock; any number of producer threads (peer workers
considering a steal) call :meth:push. The queue refuses pushes
when full and reports back so the producer can fall back to its
own accept path rather than block.
Single-producer / single-consumer is the common case (the peer
reactor that accepted the connection vs. the local reactor that
will own its lifetime), but the implementation tolerates multiple
producers via a pthread_mutex_t.
What it isn't
This is not a kernel fd migration: the receiving worker still
has to register the fd with its own epoll / kqueue. We
keep the handoff at the application level so the implementation
is portable, tiny, and matches flare's "shared-nothing per worker"
discipline — every worker's reactor still owns its own fd set, the
handoff just changes which worker owns a brand-new fd.
Scope, stated plainly (D1): this rebalances only newly accepted
connections at accept time (:meth:WorkerHandoffPool.choose_handoff_target
picks an idle peer under skew). Established keep-alive connections
are never migrated — moving a live connection's fd and its
per-connection state machine to another worker's reactor would need
cross-thread ownership transfer, which fights Mojo's shared-nothing
model and the missing Send/Sync type system. That migration
is deliberately out of scope; the accept-time rebalance is the
portable, safe subset that still attacks reuseport head-of-line skew.
The locked design adds a single uncontended atomic acquire on the
hot path (push). Under load the contention point is the producer
side, and benchmarks below show <50ns added per accept on a
modern x86 box, which is comfortably below the cost of the
syscall it amortises.