Pular para o conteúdo

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.

01-sleep.zolo
Playground
// 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.

02-every-and-cancel.zolo
Playground
// 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?

Buscar no Zolo

9 resultados

enespt-br