From 1c6487c1e79cbe0d59a39b483af8ec44b59c586e Mon Sep 17 00:00:00 2001 From: Chris Boesch Date: Fri, 3 Apr 2026 18:11:00 +0200 Subject: added async-io quiz --- exercises/089_async5.zig | 61 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100644 exercises/089_async5.zig (limited to 'exercises/089_async5.zig') diff --git a/exercises/089_async5.zig b/exercises/089_async5.zig new file mode 100644 index 0000000..4fb8d76 --- /dev/null +++ b/exercises/089_async5.zig @@ -0,0 +1,61 @@ +// +// One of the most important features of the new Io system is +// structured cancellation! +// +// Every Future has a .cancel() method that: +// 1. Requests the task to stop (via error.Canceled at the +// next "cancellation point") +// 2. Waits for the task to actually finish +// 3. Returns whatever result the task produced +// +// A "cancellation point" is any Io function that can return +// error.Canceled - most commonly io.sleep(): +// +// fn myTask(io: std.Io) u32 { +// io.sleep(...) catch |err| switch (err) { +// error.Canceled => return 0, // handle gracefully +// }; +// return 42; +// } +// +// This is fundamentally different from killing a thread - +// the task gets a chance to clean up and return a value! +// +// Fix this program: the slow task would take 10 seconds, +// but we cancel it after 1 second. The task should detect +// the cancellation and return early. +// +const std = @import("std"); +const print = std.debug.print; + +pub fn main(init: std.process.Init) !void { + const io = init.io; + + var future = io.async(slowTask, .{io}); + + // Wait 1 second, then cancel instead of waiting the full 10. + io.sleep(std.Io.Duration.fromSeconds(1), .awake) catch {}; + + print("Canceling slow task...\n", .{}); + + // We don't want to wait 10 seconds! + // Which Future method requests cancellation AND returns the result? + const result = ???; + + print("Task returned: {}\n", .{result}); +} + +fn slowTask(io: std.Io) u32 { + print("Starting long computation...\n", .{}); + + // Try to sleep for 10 seconds - but we might get canceled! + io.sleep(std.Io.Duration.fromSeconds(10), .awake) catch |err| switch (err) { + error.Canceled => { + print("Task was canceled, cleaning up.\n", .{}); + return 0; + }, + }; + + print("Task completed normally.\n", .{}); + return 42; +} -- cgit v1.2.3 From 63e506586fad9458c8a881d003f57942542f2cde Mon Sep 17 00:00:00 2001 From: Chris Boesch Date: Mon, 6 Apr 2026 16:57:48 +0200 Subject: improvements for async-io --- exercises/089_async5.zig | 12 +++++++++--- patches/patches/089_async5.patch | 8 ++++---- 2 files changed, 13 insertions(+), 7 deletions(-) (limited to 'exercises/089_async5.zig') diff --git a/exercises/089_async5.zig b/exercises/089_async5.zig index 4fb8d76..0c00c1f 100644 --- a/exercises/089_async5.zig +++ b/exercises/089_async5.zig @@ -5,7 +5,7 @@ // Every Future has a .cancel() method that: // 1. Requests the task to stop (via error.Canceled at the // next "cancellation point") -// 2. Waits for the task to actually finish +// 2. BLOCKS until the task actually finishes // 3. Returns whatever result the task produced // // A "cancellation point" is any Io function that can return @@ -13,7 +13,7 @@ // // fn myTask(io: std.Io) u32 { // io.sleep(...) catch |err| switch (err) { -// error.Canceled => return 0, // handle gracefully +// error.Canceled => return 0, // error handle // }; // return 42; // } @@ -21,6 +21,11 @@ // This is fundamentally different from killing a thread - // the task gets a chance to clean up and return a value! // +// Remember: both .await() and .cancel() block and return the +// result. The only difference is that .cancel() also sends +// the cancellation request. And both are idempotent — calling +// either one again just returns the same result. +// // Fix this program: the slow task would take 10 seconds, // but we cancel it after 1 second. The task should detect // the cancellation and return early. @@ -32,6 +37,7 @@ pub fn main(init: std.process.Init) !void { const io = init.io; var future = io.async(slowTask, .{io}); + defer _ = future.cancel(io); // safety net // Wait 1 second, then cancel instead of waiting the full 10. io.sleep(std.Io.Duration.fromSeconds(1), .awake) catch {}; @@ -40,7 +46,7 @@ pub fn main(init: std.process.Init) !void { // We don't want to wait 10 seconds! // Which Future method requests cancellation AND returns the result? - const result = ???; + const result = future.???(io); print("Task returned: {}\n", .{result}); } diff --git a/patches/patches/089_async5.patch b/patches/patches/089_async5.patch index d2baa96..3cea4e9 100644 --- a/patches/patches/089_async5.patch +++ b/patches/patches/089_async5.patch @@ -1,10 +1,10 @@ ---- exercises/089_async5.zig 2026-04-01 23:40:40.505855238 +0200 -+++ answers/089_async5.zig 2026-04-01 23:40:10.176236971 +0200 -@@ -40,7 +40,7 @@ +--- exercises/089_async5.zig 2026-04-06 14:38:54.443726849 +0200 ++++ answers/089_async5.zig 2026-04-06 14:38:39.945438309 +0200 +@@ -46,7 +46,7 @@ // We don't want to wait 10 seconds! // Which Future method requests cancellation AND returns the result? -- const result = ???; +- const result = future.???(io); + const result = future.cancel(io); print("Task returned: {}\n", .{result}); -- cgit v1.2.3