{"id":16208637,"url":"https://github.com/cloudef/zig-aio","last_synced_at":"2025-05-16T13:03:28.791Z","repository":{"id":244614541,"uuid":"815758807","full_name":"Cloudef/zig-aio","owner":"Cloudef","description":"io_uring like asynchronous API and coroutine powered IO tasks for zig","archived":false,"fork":false,"pushed_at":"2025-04-29T11:53:37.000Z","size":6340,"stargazers_count":324,"open_issues_count":19,"forks_count":14,"subscribers_count":6,"default_branch":"master","last_synced_at":"2025-05-15T23:06:04.143Z","etag":null,"topics":["aio","async","asynchronous","coroutines","io","io-uring","zig"],"latest_commit_sha":null,"homepage":"https://cloudef.github.io/zig-aio/","language":"Zig","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Cloudef.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null},"funding":{"github":["Cloudef"]}},"created_at":"2024-06-16T04:10:30.000Z","updated_at":"2025-05-14T20:32:53.000Z","dependencies_parsed_at":null,"dependency_job_id":"7f6ceca8-e4a3-4bde-8aa2-d059f18d92c0","html_url":"https://github.com/Cloudef/zig-aio","commit_stats":{"total_commits":247,"total_committers":7,"mean_commits":"35.285714285714285","dds":"0.10121457489878538","last_synced_commit":"f4437ff35326a45362ebbbc71d9839e8eaab7894"},"previous_names":["cloudef/zig-aio"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Cloudef%2Fzig-aio","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Cloudef%2Fzig-aio/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Cloudef%2Fzig-aio/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Cloudef%2Fzig-aio/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Cloudef","download_url":"https://codeload.github.com/Cloudef/zig-aio/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254535826,"owners_count":22087398,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["aio","async","asynchronous","coroutines","io","io-uring","zig"],"created_at":"2024-10-10T10:25:03.171Z","updated_at":"2025-05-16T13:03:28.784Z","avatar_url":"https://github.com/Cloudef.png","language":"Zig","readme":"# zig-aio\n\nzig-aio provides io_uring like asynchronous API and coroutine powered IO tasks for zig\n\n* [Documentation](https://cloudef.github.io/zig-aio)\n\n---\n\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n\nProject is tested on zig version 0.15.0-dev.386+2e35fdd03\n\n## Support matrix\n\n| OS      | AIO             | CORO            |\n|---------|-----------------|-----------------|\n| Linux   | io_uring, posix | x86_64, aarch64 |\n| Windows | iocp            | x86_64, aarch64 |\n| Darwin  | posix           | x86_64, aarch64 |\n| *BSD    | posix           | x86_64, aarch64 |\n| WASI    | posix           | ❌              |\n\n* io_uring AIO backend is a light wrapper, where most of the code is error mapping\n* WASI may eventually get coro support [Stack Switching Proposal](https://github.com/WebAssembly/stack-switching/blob/main/proposals/stack-switching/Explainer.md)\n\n## Example\n\n```zig\nconst builtin = @import(\"builtin\");\nconst std = @import(\"std\");\nconst aio = @import(\"aio\");\nconst coro = @import(\"coro\");\nconst log = std.log.scoped(.coro_aio);\n\npub const std_options: std.Options = .{\n    .log_level = .debug,\n};\n\nfn server(startup: *coro.ResetEvent) !void {\n    var socket: std.posix.socket_t = undefined;\n    try coro.io.single(.socket, .{\n        .domain = std.posix.AF.INET,\n        .flags = std.posix.SOCK.STREAM | std.posix.SOCK.CLOEXEC,\n        .protocol = std.posix.IPPROTO.TCP,\n        .out_socket = \u0026socket,\n    });\n\n    const address = std.net.Address.initIp4(.{ 0, 0, 0, 0 }, 1327);\n    try std.posix.setsockopt(socket, std.posix.SOL.SOCKET, std.posix.SO.REUSEADDR, \u0026std.mem.toBytes(@as(c_int, 1)));\n    if (@hasDecl(std.posix.SO, \"REUSEPORT\")) {\n        try std.posix.setsockopt(socket, std.posix.SOL.SOCKET, std.posix.SO.REUSEPORT, \u0026std.mem.toBytes(@as(c_int, 1)));\n    }\n    try std.posix.bind(socket, \u0026address.any, address.getOsSockLen());\n    try std.posix.listen(socket, 128);\n\n    startup.set();\n\n    var client_sock: std.posix.socket_t = undefined;\n    try coro.io.single(.accept, .{ .socket = socket, .out_socket = \u0026client_sock });\n\n    var buf: [1024]u8 = undefined;\n    var len: usize = 0;\n    try coro.io.multi(.{\n        aio.op(.send, .{ .socket = client_sock, .buffer = \"hey \" }, .soft),\n        aio.op(.send, .{ .socket = client_sock, .buffer = \"I'm doing multiple IO ops at once \" }, .soft),\n        aio.op(.send, .{ .socket = client_sock, .buffer = \"how cool is that?\" }, .soft),\n        aio.op(.recv, .{ .socket = client_sock, .buffer = \u0026buf, .out_read = \u0026len }, .unlinked),\n    });\n\n    log.warn(\"got reply from client: {s}\", .{buf[0..len]});\n    try coro.io.multi(.{\n        aio.op(.send, .{ .socket = client_sock, .buffer = \"ok bye\" }, .soft),\n        aio.op(.close_socket, .{ .socket = client_sock }, .soft),\n        aio.op(.close_socket, .{ .socket = socket }, .unlinked),\n    });\n}\n\nfn client(startup: *coro.ResetEvent) !void {\n    var socket: std.posix.socket_t = undefined;\n    try coro.io.single(.socket, .{\n        .domain = std.posix.AF.INET,\n        .flags = std.posix.SOCK.STREAM | std.posix.SOCK.CLOEXEC,\n        .protocol = std.posix.IPPROTO.TCP,\n        .out_socket = \u0026socket,\n    });\n\n    try startup.wait();\n\n    const address = std.net.Address.initIp4(.{ 127, 0, 0, 1 }, 1327);\n    try coro.io.single(.connect, .{\n        .socket = socket,\n        .addr = \u0026address.any,\n        .addrlen = address.getOsSockLen(),\n    });\n\n    while (true) {\n        var buf: [1024]u8 = undefined;\n        var len: usize = 0;\n        try coro.io.single(.recv, .{ .socket = socket, .buffer = \u0026buf, .out_read = \u0026len });\n        log.warn(\"got reply from server: {s}\", .{buf[0..len]});\n        if (std.mem.indexOf(u8, buf[0..len], \"how cool is that?\")) |_| break;\n    }\n\n    try coro.io.single(.send, .{ .socket = socket, .buffer = \"dude, I don't care\" });\n\n    var buf: [1024]u8 = undefined;\n    var len: usize = 0;\n    try coro.io.single(.recv, .{ .socket = socket, .buffer = \u0026buf, .out_read = \u0026len });\n    log.warn(\"got final words from server: {s}\", .{buf[0..len]});\n}\n\npub fn main() !void {\n    if (builtin.target.os.tag == .wasi) return error.UnsupportedPlatform;\n    // var mem: [4096 * 1024]u8 = undefined;\n    // var fba = std.heap.FixedBufferAllocator.init(\u0026mem);\n    var gpa: std.heap.GeneralPurposeAllocator(.{}) = .{};\n    defer _ = gpa.deinit();\n    var scheduler = try coro.Scheduler.init(gpa.allocator(), .{});\n    defer scheduler.deinit();\n    var startup: coro.ResetEvent = .{};\n    _ = try scheduler.spawn(client, .{\u0026startup}, .{});\n    _ = try scheduler.spawn(server, .{\u0026startup}, .{});\n    try scheduler.run(.wait);\n}\n```\n\n## Syscall overhead\n\n`strace -c` output from the `examples/coro.zig` without `std.log` output and with `std.heap.FixedBufferAllocator`.\nThis is using the `io_uring` backend. `posix` backend emulates `io_uring` like interface by using a traditional\nreadiness event loop, thus it will have larger syscall overhead. Posix backend may still be faster than io_uring\ndepending on usage.\n\n```\n% time     seconds  usecs/call     calls    errors syscall\n------ ----------- ----------- --------- --------- ------------------\n  0.00    0.000000           0         2           close\n  0.00    0.000000           0         4           mmap\n  0.00    0.000000           0         4           munmap\n  0.00    0.000000           0         5           rt_sigaction\n  0.00    0.000000           0         1           bind\n  0.00    0.000000           0         1           listen\n  0.00    0.000000           0         2           setsockopt\n  0.00    0.000000           0         1           execve\n  0.00    0.000000           0         1           arch_prctl\n  0.00    0.000000           0         1           gettid\n  0.00    0.000000           0         2           prlimit64\n  0.00    0.000000           0         2           io_uring_setup\n  0.00    0.000000           0         6           io_uring_enter\n  0.00    0.000000           0         1           io_uring_register\n------ ----------- ----------- --------- --------- ------------------\n100.00    0.000000           0        33           total\n```\n","funding_links":["https://github.com/sponsors/Cloudef"],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcloudef%2Fzig-aio","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcloudef%2Fzig-aio","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcloudef%2Fzig-aio/lists"}