The Reactor

One Reactor instance is a closed world: a thread, a ring, and every structure that thread touches. This page walks the class itself.

What it owns

Startup

Run() executes on the reactor's own thread, in a deliberate order: record the thread id (every fast-path check compares against it), create the ring - DEFER_TASKRUN requires that setup and enter happen on the same thread - open the SO_REUSEPORT listeners - one per Port/ExtraPorts entry, accepts route by listener fd - register the buffer ring (or initialize the per-connection ring machinery in incremental mode), create the eventfd, run OnStart so the application opens its ring-native clients here, then arm the multishot accept and the wake poll and fall into the loop. Client opens started in OnStart may be async: their submissions sit staged in the SQ and complete once the loop begins.

Dispatch, kind by kind

Each CQE's user_data unpacks to a kind, a generation, and an fd (or slot):

Producing SQEs

SQE production is reactor-thread-only - SINGLE_ISSUER is a promise to the kernel. GetSqeOrFlush claims a slot and, if the SQ is full mid-batch, flushes it with a no-wait enter and retries: submission never blocks on completions. Off-reactor callers never touch this path; their work arrives through the queues and becomes SQEs here.

Recycling

Recycle always runs on the reactor (it touches the buf_ring and the pool): wake any awaiters via MarkClosed, submit an ASYNC_CANCEL for the connection's multishot recv - tagged with the pre-bump generation so it matches the armed SQE - return leftover buffers (shared mode) or unregister the per-connection ring (incremental), close the fd, Clear() the connection (which bumps the generation first, invalidating every stale token and queued reference), then push to the pool or free if the pool is full.