Skip to content

ZIO - Async I/O framework for Zig

ZIO is an async I/O framework for Zig that provides:

  • Runtime for executing stackful coroutines (fibers, green threads) on one or more CPU threads
  • Asynchronous I/O layer that makes it look like operations are blocking for easy state management, but using event-driven OS APIs under the hood
  • Synchronization primitives that cooperate with this runtime
  • Integration with standard library interfaces, like std.Io.Reader and std.Io.Writer

It's similar to goroutines in Go, but with the pros and cons of being implemented in a language with manual memory management and without compiler support.

Features

  • Support for Linux (io_uring, epoll), Windows (iocp), macOS (kqueue), most BSDs (kqueue), and many other systems (poll)
  • User-mode coroutine context switching for x86_64, aarch64, arm, thumb, riscv32, riscv64, loongarch64 and powerpc64 architectures
  • Growable stacks for the coroutines implemented by auto-extending virtual memory reservations
  • Multi-threaded coroutine scheduler
  • Fully asynchronous network I/O on all systems
  • Asynchronous file I/O on Linux and Windows, simulated using auxiliary thread pool on other systems
  • Cancelation support for all operations
  • Structured concurrency using task groups
  • Synchronization primitives, including more advanced ones, like channels

Ecosystem

The following libraries use ZIO for networking and concurrency:

Quick Example

Basic TCP echo server:

const std = @import("std");
const zio = @import("zio");

fn handleClient(stream: zio.net.Stream) !void {
    defer stream.close();

    std.log.info("Client connected from {f}", .{stream.socket.address});

    var read_buffer: [1024]u8 = undefined;
    var reader = stream.reader(&read_buffer);

    var write_buffer: [1024]u8 = undefined;
    var writer = stream.writer(&write_buffer);

    while (true) {
        // Read a line from the client
        const line = reader.interface.takeDelimiterInclusive('\n') catch |err| switch (err) {
            error.EndOfStream => break,
            error.ReadFailed => |e| return reader.err orelse e,
            else => |e| return e,
        };
        std.log.info("Received: {s}", .{line});

        // Delay the response a little bit
        try zio.sleep(.fromMilliseconds(1000));

        // Echo the line back
        try writer.interface.writeAll(line);
        try writer.interface.flush();
    }

    std.log.info("Client disconnected", .{});
}

pub fn main() !void {
    const rt = try zio.Runtime.init(std.heap.smp_allocator, .{});
    defer rt.deinit();

    const addr = try zio.net.IpAddress.parseIp4("127.0.0.1", 8080);

    const server = try addr.listen(.{});
    defer server.close();

    std.log.info("TCP echo server listening on {f}", .{server.socket.address});
    std.log.info("Press Ctrl+C to stop the server", .{});

    var group: zio.Group = .init;
    defer group.cancel();

    while (true) {
        const stream = try server.accept();
        errdefer stream.close();

        try group.spawn(handleClient, .{stream});
    }
}

See the Tutorial to get started, or check out the examples in the repository.

Installation

See the Getting Started guide for installation instructions.

License

This project is licensed under the MIT license.