The Event Loop

A track of P33 · Asyncio & Coroutines.

Build the event loop from generators, then drive the real one: async/await, gather and cancellation - and why one cooperative loop outscales a pool of threads for I/O-bound work.

A junior engineer sprinkles async and await across a codebase, sees no speed-up, and concludes asyncio is snake oil. A senior one knows the loop is a single cooperative scheduler, spots the one blocking call starving it, and fixes it in a line. The difference is a mental model — and the fastest way to build it is to write the event loop yourself.

That is where this track starts. Before any asyncio, you build a round-robin scheduler over generators: keep a queue of tasks, give each one a single next() turn, drop the ones that finish. That is an event loop — cooperative multitasking, where work voluntarily yields control so nothing blocks anything else. It is the yield→coroutine bridge from P29, made concrete.

Then you meet the real thing on the kernel (real asyncio needs a real Python loop, which the browser can't provide). asyncio.gather runs many coroutines concurrently and returns their results in the order you asked; asyncio.wait_for puts a deadline on one and cancels it cleanly when the time is up. async/await stop being incantations and become what you already built — suspend points and a scheduler — which is exactly why one loop can hold ten thousand mostly-waiting connections that a thread pool never could.

Generators suspendyield is a pause buttonA loop takes turnsround-robin schedulerasync/awaitthe same idea, real syntaxgather & wait_forconcurrency + timeouts (kernel)
Build the loop from generators, then drive the real one.