Skip to content

Instantly share code, notes, and snippets.

@matklad
Forked from andrewrk/example.zig
Last active July 10, 2025 20:16
Show Gist options
  • Save matklad/6715e9fbef96ec33e02dc4b4b838714e to your computer and use it in GitHub Desktop.
Save matklad/6715e9fbef96ec33e02dc4b4b838714e to your computer and use it in GitHub Desktop.
async await demo
// No futures
//
// Soundtrack: https://www.youtube.com/watch?v=rFH4jCW_LzM&list=RDrFH4jCW_LzM
//
const std = @import("std");
const assert = std.debug.assert;
const Allocator = std.mem.Allocator;
const Io = std.Io;
pub fn main() !void {
var debug_allocator: std.heap.DebugAllocator(.{}) = .init;
const gpa = debug_allocator.allocator();
//const gpa = std.heap.smp_allocator;
var thread_pool: std.Io.ThreadPool = undefined;
try thread_pool.init(.{
.allocator = gpa,
.n_jobs = std.Thread.getCpuCount() catch 1,
});
defer thread_pool.deinit();
const io = thread_pool.io();
//var event_loop: std.Io.EventLoop = undefined;
//try event_loop.init(gpa);
//defer event_loop.deinit();
//const io = event_loop.io();
var queue: Io.Queue(i32) = .init(&.{});
const total, _, const select_result, const producer_result, const consumer_sum = io.join(.{
exampleSum, .{io},
processTextFile, .{io},
selectExample, .{ io, IO.Dir.cwd() },
producerRun, .{ io, &queue },
consumerRun, .{ io, &queue },
});
producer_result catch {};
std.log.info("total: {d}", .{total});
std.log.info("consumer sum = {d}", .{consumer_sum});
try select_result;
}
fn exampleSum(io: Io) void {
const first_half, const second_half = io.join(.{
calcSum, .{ 0, 100 },
calcSum, .{ 100, 200 },
});
return first_half + second_half;
}
fn producerRun(io: Io, queue: *Io.Queue(i32)) !void {
for (0..100) |i| {
try queue.putOne(io, @intCast(i * 2 + 1));
}
try queue.putOne(io, 999);
}
fn consumerRun(io: Io, queue: *Io.Queue(i32)) i32 {
var sum: i32 = 0;
while (true) {
const n = queue.getOne(io) catch return undefined;
if (n == 999) return sum;
sum += n;
}
}
fn calcSum(start: usize, end: usize) usize {
var sum: usize = 0;
for (start..end) |i| {
sum += i;
}
std.log.debug("calcSum returning {d}", .{sum});
return sum;
}
fn processTextFile(io: Io) !void {
var buffer: [5000]u8 = undefined;
const read_result, const out_file_result = io.join(.{
readRotFile, .{ io, "example.txt", &buffer },
Io.Dir.createFile, .{ .cwd(), io, "output.txt", .{} },
});
const out_file = try out_file_result;
defer out_file.close(io);
const n = try in_file.readAll(io, &buffer);
const contents = try read_result;
try out_file.writeAll(io, contents);
}
fn readRotFile(io: Io, file_name: []const u8, buffer: *[]u8) ![]const u8 {
var in_file = try Io.Dir.cwd().openFile(io, file_name, .{});
defer in_file.close(io);
const n = try in_file.readAll(io, buffer);
const contents = buffer[0..n];
for (contents) |*elem| elem.* = elem.* +% 1;
return contents;
}
fn selectExample(io: Io, dir: Io.Dir) !void {
switch (io.select(.{ // Select "desugars" to join that cancels IO after any operation completes.
.a = .{ Io.Dir.writeFile, .{ dir, io, .{ .sub_path = "a.txt", .data = "a contents" } } },
.b = .{ Io.Dir.writeFile, .{ dir, io, .{ .sub_path = "b.txt", .data = "b contents" } } },
.timeout = .{ Io.sleepDuration, .{ io, .ms(100) } },
})) {
.a => |res| {
std.log.info("a future won the race", .{});
try res;
},
.b => |res| {
std.log.info("b future won the race", .{});
try res;
},
.timeout => {
return error.Timeout;
},
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment