summaryrefslogtreecommitdiff
path: root/exercises/089_async5.zig
diff options
context:
space:
mode:
Diffstat (limited to 'exercises/089_async5.zig')
-rw-r--r--exercises/089_async5.zig67
1 files changed, 67 insertions, 0 deletions
diff --git a/exercises/089_async5.zig b/exercises/089_async5.zig
new file mode 100644
index 0000000..0c00c1f
--- /dev/null
+++ b/exercises/089_async5.zig
@@ -0,0 +1,67 @@
+//
+// 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. BLOCKS until the task actually finishes
+// 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, // error handle
+// };
+// return 42;
+// }
+//
+// 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.
+//
+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});
+ 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 {};
+
+ print("Canceling slow task...\n", .{});
+
+ // We don't want to wait 10 seconds!
+ // Which Future method requests cancellation AND returns the result?
+ const result = future.???(io);
+
+ 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;
+}