---
title: "std.event em Zig — Referência e Exemplos"
url: "https://ziglang.com.br/stdlib/std.event-em-zig-refer%C3%AAncia-e-exemplos/"
markdown_url: "https://ziglang.com.br/stdlib/std.event-em-zig-refer%C3%AAncia-e-exemplos.MD"
description: "Guia completo do event loop e I/O assíncrono em Zig em português. Modelo de concorrência, I/O não-bloqueante e exemplos práticos."
date: "2026-02-21"
author: "Zig Brasil"
---

# std.event em Zig — Referência e Exemplos

Guia completo do event loop e I/O assíncrono em Zig em português. Modelo de concorrência, I/O não-bloqueante e exemplos práticos.


# Event Loop e I/O Assíncrono em Zig

O Zig historicamente explorou um modelo de programação assíncrona baseado em *async frames* e um event loop integrado à biblioteca padrão. Na versão atual (0.13.x / 0.14.x), o suporte a async/await está temporariamente removido enquanto é redesenhado. Este documento descreve os mecanismos atuais para I/O não-bloqueante e concorrência baseada em eventos no Zig, além das abordagens recomendadas.

## Visão Geral

```zig
const std = @import("std");
```

### Estado Atual do Async no Zig

O Zig teve suporte a `async`/`await`/`suspend`/`resume` em versões anteriores (0.10 e anteriores), mas essa funcionalidade foi temporariamente removida para um redesign completo. As abordagens recomendadas atualmente são:

1. **Threads** — Para paralelismo real (`std.Thread`, `std.Thread.Pool`)
2. **I/O Polling** — Via `std.posix.poll` ou `std.io.poll`
3. **Bibliotecas externas** — Como `libxev` ou `io_uring` wrappers

## Mecanismos Disponíveis

### std.io.poll

```zig
// Polling de múltiplos file descriptors
pub fn poll(fds: []std.posix.pollfd, timeout: i32) !usize
```

### std.posix (APIs de sistema)

```zig
// epoll (Linux)
pub fn epoll_create1(flags: u32) !i32
pub fn epoll_ctl(epfd: i32, op: u32, fd: i32, event: *epoll_event) !void
pub fn epoll_wait(epfd: i32, events: []epoll_event, timeout: i32) !usize

// Pipe para comunicação entre threads
pub fn pipe() ![2]i32
pub fn pipe2(flags: u32) ![2]i32
```

## Exemplo 1: I/O Não-Bloqueante com Threads

A abordagem mais comum atualmente é usar threads para operações de I/O:

```zig
const std = @import("std");
const net = std.net;

const Contexto = struct {
    stream: net.Stream,
    id: usize,
};

fn handleCliente(ctx: Contexto) void {
    defer ctx.stream.close();

    var buf: [1024]u8 = undefined;
    const reader = ctx.stream.reader();
    const writer = ctx.stream.writer();

    while (true) {
        const n = reader.read(&buf) catch break;
        if (n == 0) break;

        writer.writeAll(buf[0..n]) catch break;
    }

    std.debug.print("Cliente {d} desconectou\n", .{ctx.id});
}

pub fn main() !void {
    const addr = try net.Address.parseIp4("127.0.0.1", 9000);
    var server = try addr.listen(.{ .reuse_address = true });
    defer server.deinit();

    std.debug.print("Servidor em :9000 (thread por cliente)\n", .{});

    var id: usize = 0;
    while (true) {
        const conn = server.accept() catch continue;
        id += 1;

        std.debug.print("Novo cliente {d}\n", .{id});

        // Uma thread por cliente
        const thread = std.Thread.spawn(.{}, handleCliente, .{
            Contexto{ .stream = conn.stream, .id = id },
        }) catch continue;
        thread.detach();
    }
}
```

## Exemplo 2: Timer e Eventos com Thread Pool

```zig
const std = @import("std");

const Evento = struct {
    nome: []const u8,
    delay_ms: u64,
    callback: *const fn ([]const u8) void,
};

fn executarEvento(evento: Evento) void {
    std.time.sleep(evento.delay_ms * std.time.ns_per_ms);
    evento.callback(evento.nome);
}

fn onEvento(nome: []const u8) void {
    const ts = std.time.milliTimestamp();
    std.debug.print("[{d}] Evento: {s}\n", .{ ts, nome });
}

pub fn main() !void {
    var gpa = std.heap.GeneralPurposeAllocator(.{}){};
    defer _ = gpa.deinit();
    const allocator = gpa.allocator();

    var pool: std.Thread.Pool = undefined;
    try pool.init(.{ .allocator = allocator, .n_jobs = 4 });
    defer pool.deinit();

    const eventos = [_]Evento{
        .{ .nome = "heartbeat", .delay_ms = 100, .callback = onEvento },
        .{ .nome = "timeout_check", .delay_ms = 200, .callback = onEvento },
        .{ .nome = "flush_logs", .delay_ms = 50, .callback = onEvento },
        .{ .nome = "gc_cycle", .delay_ms = 150, .callback = onEvento },
        .{ .nome = "metrics_push", .delay_ms = 75, .callback = onEvento },
    };

    const inicio = std.time.milliTimestamp();

    for (eventos) |evento| {
        pool.spawn(executarEvento, .{evento});
    }

    pool.waitForIdle();

    const fim = std.time.milliTimestamp();
    std.debug.print("\nTodos os eventos processados em {d}ms\n", .{fim - inicio});
}
```

## Exemplo 3: Padrão Reactor Simples

```zig
const std = @import("std");

const Reactor = struct {
    const Handler = *const fn (usize) void;

    handlers: std.AutoHashMap(usize, Handler),
    pendentes: std.ArrayList(usize),
    allocator: std.mem.Allocator,

    pub fn init(allocator: std.mem.Allocator) Reactor {
        return .{
            .handlers = std.AutoHashMap(usize, Handler).init(allocator),
            .pendentes = std.ArrayList(usize).init(allocator),
            .allocator = allocator,
        };
    }

    pub fn deinit(self: *Reactor) void {
        self.handlers.deinit();
        self.pendentes.deinit();
    }

    pub fn registrar(self: *Reactor, id: usize, handler: Handler) !void {
        try self.handlers.put(id, handler);
    }

    pub fn emitir(self: *Reactor, id: usize) !void {
        try self.pendentes.append(id);
    }

    pub fn processar(self: *Reactor) void {
        for (self.pendentes.items) |id| {
            if (self.handlers.get(id)) |handler| {
                handler(id);
            }
        }
        self.pendentes.clearRetainingCapacity();
    }
};

fn onConexao(id: usize) void {
    std.debug.print("  -> Handler de conexão (id={d})\n", .{id});
}

fn onDados(id: usize) void {
    std.debug.print("  -> Handler de dados (id={d})\n", .{id});
}

fn onDesconexao(id: usize) void {
    std.debug.print("  -> Handler de desconexão (id={d})\n", .{id});
}

pub fn main() !void {
    var gpa = std.heap.GeneralPurposeAllocator(.{}){};
    defer _ = gpa.deinit();

    var reactor = Reactor.init(gpa.allocator());
    defer reactor.deinit();

    // Registra handlers
    try reactor.registrar(1, onConexao);
    try reactor.registrar(2, onDados);
    try reactor.registrar(3, onDesconexao);

    // Simula loop de eventos
    const stdout = std.io.getStdOut().writer();
    for (0..3) |ciclo| {
        try stdout.print("Ciclo {d}:\n", .{ciclo});

        // Simula eventos
        try reactor.emitir(1);
        try reactor.emitir(2);
        if (ciclo == 2) try reactor.emitir(3);

        reactor.processar();
    }
}
```

## Futuro do Async em Zig

O redesign do async no Zig tem como objetivos:

- **Sem coloração de funções**: Funções sync e async devem ser intercambiáveis
- **Integração com I/O**: O event loop será integrado ao sistema de I/O
- **Zero-cost**: Overhead zero quando async não é usado
- **Cancelamento**: Suporte robusto a cancelamento de operações

Enquanto o redesign não é finalizado, use `std.Thread` e `std.Thread.Pool` para concorrência.

## Módulos Relacionados

- [std.Thread](/stdlib/std-thread/) — Threads nativas
- [std.Thread.Pool](/stdlib/std-thread-pool/) — Pool de threads
- [std.Thread.Mutex](/stdlib/std-thread-mutex/) — Sincronização
- [std.net](/stdlib/std-net/) — Networking
- [std.io](/stdlib/std-io/) — Entrada e saída

## Tutoriais e Receitas Relacionados

- [Tutorial: Concorrência em Zig](/tutoriais/concorrencia/)
- [Receita: Servidor Concorrente](/receitas/servidor-concorrente/)
