From db1fef8b864f1af6f9d2b8a7871e72d77747304d Mon Sep 17 00:00:00 2001 From: Chris Boesch Date: Wed, 1 Apr 2026 22:52:04 +0200 Subject: [PATCH] revival of the async-io functions --- build.zig | 11 +++--- exercises/086_async3.zig | 61 +++++++++++++++++++++----------- patches/patches/086_async3.patch | 18 ++++++++++ 3 files changed, 64 insertions(+), 26 deletions(-) create mode 100644 patches/patches/086_async3.patch diff --git a/build.zig b/build.zig index fa0dcac..d2ee3aa 100644 --- a/build.zig +++ b/build.zig @@ -1116,9 +1116,6 @@ const exercises = [_]Exercise{ .main_file = "084_async.zig", .output = "Current time: s since epoch", .timestamp = true, - // .hint = "Read the facts. Use the facts.", - // .skip = true, - // .skip_hint = "async has not been implemented in the current compiler version.", }, .{ .main_file = "085_async2.zig", @@ -1126,9 +1123,11 @@ const exercises = [_]Exercise{ }, .{ .main_file = "086_async3.zig", - .output = "5 4 3 2 1", - .skip = true, - .skip_hint = "async has not been implemented in the current compiler version.", + .output = + \\1 + 2 = 3 + \\6 * 7 = 42 + \\Total: 45 + , // pay attention to the comma }, .{ .main_file = "087_async4.zig", diff --git a/exercises/086_async3.zig b/exercises/086_async3.zig index c8f1113..07221e9 100644 --- a/exercises/086_async3.zig +++ b/exercises/086_async3.zig @@ -1,29 +1,50 @@ // -// Because they can suspend and resume, async Zig functions are -// an example of a more general programming concept called -// "coroutines". One of the neat things about Zig async functions -// is that they retain their state as they are suspended and -// resumed. +// The real power of async shows when you launch MULTIPLE tasks! // -// See if you can make this program print "5 4 3 2 1". +// With io.async(), you can start several operations, then await +// them all. The Io backend may run them concurrently: // -const print = @import("std").debug.print; +// var f1 = io.async(taskA, .{}); +// var f2 = io.async(taskB, .{}); +// +// // Both tasks may be running now! +// const a = f1.await(io); +// const b = f2.await(io); +// +// There's also io.concurrent() which provides a STRONGER guarantee: +// it ensures the function gets its own unit of concurrency (e.g. a +// real OS thread). But it can fail with error.ConcurrencyUnavailable +// if resources are exhausted. +// +// io.async() is more portable: if no thread is available, it simply +// runs the function synchronously. This makes it the right default +// for most code. +// +// Fix this program to launch both tasks and collect their results. +// +const std = @import("std"); +const print = std.debug.print; -pub fn main() void { - const n = 5; - var foo_frame = async foo(n); +pub fn main(init: std.process.Init) !void { + const io = init.io; - ??? + // Launch both tasks asynchronously. + var future_a = io.async(slowAdd, .{ 10, 20 }); + var future_b = ???(slowMul, .{ 6, 7 }); - print("\n", .{}); + // Await both results. + const sum = future_a.await(io); + const product = future_b.???(io); + + print("{} + {} = {}\n", .{ 1, 2, sum }); + print("{} * {} = {}\n", .{ 6, 7, product }); + print("Total: {}\n", .{sum + product}); } -fn foo(countdown: u32) void { - var current = countdown; - - while (current > 0) { - print("{} ", .{current}); - current -= 1; - suspend {} - } +fn slowAdd(a: u32, b: u32) u32 { + return a + b; +} + +fn slowMul(a: u32, b: u32) u32 { + return a * b; } diff --git a/patches/patches/086_async3.patch b/patches/patches/086_async3.patch new file mode 100644 index 0000000..3a3c2c4 --- /dev/null +++ b/patches/patches/086_async3.patch @@ -0,0 +1,18 @@ +--- exercises/086_async3.zig 2026-04-01 22:51:05.540094851 +0200 ++++ answers/086_async3.zig 2026-04-01 22:50:44.579669189 +0200 +@@ -29,12 +29,12 @@ + const io = init.io; + + // Launch both tasks asynchronously. +- var future_a = io.async(slowAdd, .{ 10, 20 }); +- var future_b = ???(slowMul, .{ 6, 7 }); ++ var future_a = io.async(slowAdd, .{ 1, 2 }); ++ var future_b = io.async(slowMul, .{ 6, 7 }); + + // Await both results. + const sum = future_a.await(io); +- const product = future_b.???(io); ++ const product = future_b.await(io); + + print("{} + {} = {}\n", .{ 1, 2, sum }); + print("{} * {} = {}\n", .{ 6, 7, product });