Reactor de I/O (std::io_runtime)
Nesta página
std::io_runtime dá acesso ao reactor de I/O do Zolo — o mesmo loop de eventos
que serve conexões TCP, leituras de arquivo assíncronas e outros I/Os. Em Linux
≥ 5.19 usa io_uring; em macOS, Windows e kernels mais antigos cai no backend
fallback(thread-park). Como depende do runtime do host, não pode ser
executado no sandbox WASM; use a CLI do Zolo.
Para uma pausa simples sem outros I/Os em voo, process.sleep(ms) é mais direto.
Use io_runtime quando o programa já está dirigindo o reactor e você quer que o
timer conviva com os outros I/Os no mesmo loop.
Timer único: sleep_ms
io_runtime.sleep_ms(ms) agenda um timer de disparo único e bloqueia até ele
disparar, cedendo o controle ao reactor (sem busy spin). io_runtime.backend()
reporta qual implementação foi selecionada em tempo de execução:
Verifica o backend e mede o tempo de um sleep_ms(100) com os.clock.
// Feature: io_runtime.sleep_ms — reactor-backed timer
// Syntax: io_runtime.sleep_ms(ms: int)
// When to use: when the program is already driving the zolo-io reactor
// (TCP server, file IO, other timers) and you want the same loop turn
// to deliver this sleep alongside whatever else is in flight. For a
// pure pause with no other IO, `process.sleep` / `scheduler.sleep`
// (which use OS thread::sleep) are simpler.
use std::io_runtime
use std::os
// Confirm which backend the runtime resolved to. On Linux ≥ 5.19 you
// see "zolo-io/uring(multishot-accept+timerfd+eventfd)"; on macOS,
// Windows, and older Linux kernels you see "zolo-io/fallback(thread-park)".
print("backend: {io_runtime.backend()}")
// Schedule a one-shot timer for 100ms and block until it fires. The
// reactor handles the actual wait via timerfd (Linux) or condvar
// (fallback) — this Lua-side loop is not a busy spin.
let start = os.clock()
io_runtime.sleep_ms(100)
let elapsed_ms = (os.clock() - start) * 1000.0
print("elapsed: {elapsed_ms}ms") // expected: ~100 (±10ms wakeup overhead)
Requer a CLI/host do Zolo — abra no playground ou rode localmente.
Timers periódicos: every_ms, wait_next e cancel
io_runtime.every_ms(interval, tag) arma um timer recorrente identificado pela
tag numérica. io_runtime.wait_next() bloqueia via reactor e retorna o próximo
evento { kind, user_data }. Múltiplos timers compartilham o mesmo loop;
disparos que chegam juntos são enfileirados para não se perder. Cancele sempre
com io_runtime.cancel(handle) ao sair do escopo:
Dois timers concorrentes (50 ms e 150 ms); coleta 6 eventos e cancela ambos.
// Feature: io_runtime.every_ms + wait_next + cancel — recurring timers
// When to use: build a simple event loop with multiple periodic timers
// (heartbeat, metrics flush, watchdog) without spawning OS threads.
// The reactor batches all fires into one `io_uring_enter` syscall on
// Linux; the fallback uses a condvar park.
use std::io_runtime
// Two concurrent timers — distinguish via the optional `tag` arg which
// is echoed in each event's `user_data` field.
let fast = io_runtime.every_ms(50, 1)
let slow = io_runtime.every_ms(150, 2)
var fires = 0
var fast_count = 0
var slow_count = 0
// Pull events one at a time. wait_next() blocks via the reactor, so
// the loop is not a busy spin. Events that arrive in the same kernel
// batch are queued internally and handed back on successive calls so
// concurrent timer fires never silently disappear.
while fires < 6 {
let ev = io_runtime.wait_next()
if ev.kind == "timer" {
if ev.user_data == 1 {
fast_count += 1
}
if ev.user_data == 2 {
slow_count += 1
}
}
fires += 1
}
// Always cancel timers before leaving the scope — the reactor would
// keep them armed otherwise. Idempotent / safe to call twice.
io_runtime.cancel(fast)
io_runtime.cancel(slow)
print("fast fires: {fast_count}") // expected: ~5 (50ms × 5 < 300ms)
print("slow fires: {slow_count}") // expected: ~1-2 (150ms × 2 ≈ 300ms)
print("total events: {fires}") // expected: 6
Requer a CLI/host do Zolo — abra no playground ou rode localmente.
Desafio
Adicione um terceiro timer de 200 ms com tag 3 e ajuste o loop para coletar
10 eventos. Quantos disparos do timer lento você espera?
Veja também