Skip to main content

run_event_loop

Function run_event_loop 

Source
pub fn run_event_loop() -> Result<(), String>
Expand description

Drive the event loop to quiescence.

Liveness is Node’s handle count: the loop runs while a microtask is pending, an open handle is registered (a listening server, a live socket, an in-flight async op), or a referenced timer is still pending. That last term is what makes setInterval(fn, 1000) hold the process open forever, as it does in Node — the interval re-arms itself, so a ref’d timer is always pending and the loop never reaches its exit condition.

Two clock regimes, selected per iteration:

  • Virtual clock (no open handles and no repeating timer): the original deterministic path — fire the earliest (delay, seq) timer immediately, no real waiting. Parity output and test speed for ordinary setTimeout scripts are unchanged.

  • Real clock (an open handle, or any pending interval): fire every timer whose wall-clock deadline has passed, then BLOCK on the I/O channel (recv_timeout bounded by the next deadline, or unbounded recv if no timers) and run the received IoTask on the main thread. The host keeps its own Sender, so recv never disconnects while the process should stay alive.

    A repeating timer must take this path: virtual time never advances, so an interval on the virtual clock would re-fire at the same instant forever, spinning a core and starving every longer-delay timer behind it.

Errors thrown by a task/timer/I/O dispatch abort the loop (uncaught → surfaced).