From 5e474ea5d1483cdca15c3b29295f0886950e4d94 Mon Sep 17 00:00:00 2001 From: Chris Boesch Date: Sun, 5 Apr 2026 16:13:42 +0200 Subject: [PATCH] improvements for async-io --- exercises/087_async3.zig | 23 +++++++++++------------ patches/patches/087_async3.patch | 19 ++++++------------- 2 files changed, 17 insertions(+), 25 deletions(-) diff --git a/exercises/087_async3.zig b/exercises/087_async3.zig index 07221e9..d10052c 100644 --- a/exercises/087_async3.zig +++ b/exercises/087_async3.zig @@ -5,20 +5,17 @@ // them all. The Io backend may run them concurrently: // // var f1 = io.async(taskA, .{}); +// defer _ = f1.cancel(io); // var f2 = io.async(taskB, .{}); -// -// // Both tasks may be running now! +// defer _ = f2.cancel(io); // 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. +// Notice the defer pattern: each async call is immediately +// followed by a defer cancel. This ensures cleanup even if +// we return early or hit an error before reaching await. +// Since await/cancel are idempotent, the defer is harmless +// if we've already awaited. // // Fix this program to launch both tasks and collect their results. // @@ -29,12 +26,14 @@ 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_a = io.async(slowAdd, .{ 1, 2 }); + defer _ = future_a.cancel(io); var future_b = ???(slowMul, .{ 6, 7 }); + defer _ = future_b.cancel(io); // 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 }); diff --git a/patches/patches/087_async3.patch b/patches/patches/087_async3.patch index 8365e7a..91ba9af 100644 --- a/patches/patches/087_async3.patch +++ b/patches/patches/087_async3.patch @@ -1,18 +1,11 @@ ---- exercises/087_async3.zig 2026-04-01 22:51:05.540094851 +0200 -+++ answers/087_async3.zig 2026-04-01 22:50:44.579669189 +0200 -@@ -29,12 +29,12 @@ - const io = init.io; - +--- exercises/087_async3.zig 2026-04-05 16:12:48.317265515 +0200 ++++ answers/087_async3.zig 2026-04-05 16:12:52.269343030 +0200 +@@ -28,7 +28,7 @@ // Launch both tasks asynchronously. -- var future_a = io.async(slowAdd, .{ 10, 20 }); + var future_a = io.async(slowAdd, .{ 1, 2 }); + defer _ = future_a.cancel(io); - var future_b = ???(slowMul, .{ 6, 7 }); -+ var future_a = io.async(slowAdd, .{ 1, 2 }); + var future_b = io.async(slowMul, .{ 6, 7 }); + defer _ = future_b.cancel(io); // 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 });