Insert space for additional async exercises

This commit is contained in:
Chris Boesch
2026-04-03 13:35:56 +02:00
parent ffde357f30
commit e0259f43a7
47 changed files with 156 additions and 106 deletions

View File

@@ -42,7 +42,7 @@ pub fn main(init: std.process.Init) !void {
try group.await(io);
print("Counter: {} (expected: 400)\n", .{state.counter});
print("Counter: {}\n", .{state.counter});
}
fn increment(io: std.Io, state: *SharedState, times: u32) void {

View File

@@ -1,35 +1,62 @@
//
// You have doubtless noticed that 'suspend' requires a block
// expression like so:
// Tasks often need to communicate! Io provides Queue for this —
// a bounded, thread-safe channel for passing data between tasks:
//
// suspend {}
// var backing: [16]u32 = undefined;
// var queue: std.Io.Queue(u32) = .init(&backing);
//
// The suspend block executes when a function suspends. To get
// sense for when this happens, please make the following
// program print the string
// // Producer task:
// try queue.putOne(io, value); // blocks if queue is full
//
// "ABCDEF"
// // Consumer task:
// const val = try queue.getOne(io); // blocks if queue is empty
//
const print = @import("std").debug.print;
// When the producer is done, it calls queue.close(io) to signal
// that no more data is coming. After that, getOne() will return
// error.Closed once the queue is drained.
//
// This is the classic producer/consumer pattern — one task
// generates work, another processes it, and the queue handles
// all the synchronization automatically.
//
// Fix this program: the producer sends numbers 1..10, the
// consumer sums them up. The expected sum is 55.
//
const std = @import("std");
const print = std.debug.print;
pub fn main() void {
print("A", .{});
pub fn main(init: std.process.Init) !void {
const io = init.io;
var frame = async suspendable();
var backing: [4]u32 = undefined;
var queue: std.Io.Queue(u32) = .init(&backing);
print("X", .{});
var group: std.Io.Group = .init;
resume frame;
group.async(io, producer, .{ io, &queue });
group.async(io, consumer, .{ io, &queue });
print("F", .{});
try group.await(io);
}
fn suspendable() void {
print("X", .{});
suspend {
print("X", .{});
fn producer(io: std.Io, queue: *std.Io.Queue(u32)) void {
// Send numbers 1 through 10 into the queue.
for (1..11) |i| {
// What Queue method sends a single element, blocking if full?
queue.???(io, @intCast(i)) catch return;
}
print("X", .{});
// Signal that we're done sending.
queue.close(io);
}
fn consumer(io: std.Io, queue: *std.Io.Queue(u32)) void {
var sum: u32 = 0;
while (true) {
const value = queue.getOne(io) catch |err| switch (err) {
error.Closed => break,
error.Canceled => return,
};
sum += value;
}
print("Sum of 1..10 = {}\n", .{sum});
}