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.Readerandstd.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,loongarch64andpowerpc64architectures - 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.