From 09bae6a70e51fc1313297bc98c67c252e8c32d3e Mon Sep 17 00:00:00 2001 From: Chris Boesch Date: Mon, 6 Apr 2026 19:30:56 +0200 Subject: [PATCH] improvements for async-io --- build.zig | 6 ++--- exercises/093_async9.zig | 42 ++++++++++++++++++++------------ patches/patches/093_async9.patch | 14 +++++------ 3 files changed, 37 insertions(+), 25 deletions(-) diff --git a/build.zig b/build.zig index 3cddb61..dcafe14 100644 --- a/build.zig +++ b/build.zig @@ -1180,9 +1180,9 @@ const exercises = [_]Exercise{ .{ .main_file = "093_async9.zig", .output = - \\Main thread continues... - \\Computing on a separate thread! - \\Main thread done waiting. + \\Computing concurrently! + \\Main continues... + \\Main done waiting. \\Result: 123 , // pay attention to the comma }, diff --git a/exercises/093_async9.zig b/exercises/093_async9.zig index ad30dcf..4a41544 100644 --- a/exercises/093_async9.zig +++ b/exercises/093_async9.zig @@ -5,22 +5,29 @@ // The difference: // // io.async(): -// * The function MAY run on another thread, or it may run -// immediately on the current thread (synchronously). -// * Never fails — if no thread is available, it just runs -// the function right away. +// * The function MAY run on a separate unit of concurrency, +// or it may run immediately on the caller (synchronously). +// * Never fails — if no concurrency is available, it just +// runs the function right away. // * More portable, works with all Io backends. // // io.concurrent(): -// * GUARANTEES a separate unit of concurrency (a real thread -// in the Threaded backend). +// * GUARANTEES a separate unit of concurrency. // * Can fail with error.ConcurrencyUnavailable if resources // are exhausted or the backend doesn't support it. -// * Use when you NEED true parallelism. +// * Use when you NEED the task to run independently of the +// caller. +// +// What is a "unit of concurrency"? That depends on the backend! +// The Threaded backend uses OS threads. But the Evented backends +// (Uring, Kqueue, Dispatch) use M:N green threads / fibers, +// which can provide concurrency even on a SINGLE OS thread. +// Your code doesn't need to know the difference. // // Because concurrent() can fail, you must handle the error: // // var future = try io.concurrent(myFn, .{args}); +// defer _ = future.cancel(io); // const result = future.await(io); // // Notice the 'try' — that's the key difference in usage! @@ -33,25 +40,30 @@ const print = std.debug.print; pub fn main(init: std.process.Init) !void { const io = init.io; - // Launch with a guaranteed separate thread. - // Which Io method guarantees true concurrency? + // Launch with a guaranteed separate unit of concurrency. + // Which Io method guarantees this? // (Hint: unlike io.async, this one can fail!) var future = try io.???(compute, .{io}); + defer _ = future.cancel(io); - print("Main thread continues...\n", .{}); - - // Wait 100 millisecond so the output order is deterministic. + // Note: All breaks in this excercise (using sleep) + // are only necessary for a deterministic result. io.sleep(std.Io.Duration.fromMilliseconds(100), .awake) catch {}; - print("Main thread done waiting.\n", .{}); + print("Main continues...\n", .{}); + + // Wait 1 second for the output order. + io.sleep(std.Io.Duration.fromMilliseconds(200), .awake) catch {}; + + print("Main done waiting.\n", .{}); const result = future.await(io); print("Result: {}\n", .{result}); } fn compute(io: std.Io) u32 { - print("Computing on a separate thread!\n", .{}); + print("Computing concurrently!\n", .{}); // Simulate some work. - io.sleep(std.Io.Duration.fromMilliseconds(200), .awake) catch return 0; + io.sleep(std.Io.Duration.fromMilliseconds(400), .awake) catch return 0; return 123; } diff --git a/patches/patches/093_async9.patch b/patches/patches/093_async9.patch index f759921..ebdfce2 100644 --- a/patches/patches/093_async9.patch +++ b/patches/patches/093_async9.patch @@ -1,11 +1,11 @@ ---- exercises/093_async9.zig 2026-04-03 13:44:50.526780809 +0200 -+++ answers/093_async9.zig 2026-04-03 13:44:54.957870294 +0200 -@@ -36,7 +36,7 @@ - // Launch with a guaranteed separate thread. - // Which Io method guarantees true concurrency? +--- exercises/093_async9.zig 2026-04-06 19:26:11.388025362 +0200 ++++ answers/093_async9.zig 2026-04-06 19:18:36.242931688 +0200 +@@ -43,7 +43,7 @@ + // Launch with a guaranteed separate unit of concurrency. + // Which Io method guarantees this? // (Hint: unlike io.async, this one can fail!) - var future = try io.???(compute, .{io}); + var future = try io.concurrent(compute, .{io}); + defer _ = future.cancel(io); - print("Main thread continues...\n", .{}); - + // Note: All breaks in this excercise (using sleep)