summaryrefslogtreecommitdiff
path: root/exercises
diff options
context:
space:
mode:
authorChris Boesch <chrboesch@noreply.codeberg.org>2026-04-02 10:28:40 +0200
committerChris Boesch <chrboesch@noreply.codeberg.org>2026-04-02 10:28:40 +0200
commit3b22bfd898a5ca93df9e07a3f1816f3b0b08137b (patch)
tree6cc1e4dd80d3fb0897b0ab5d7ecb700234df89ff /exercises
parente22748d48899d93c6af2684b33688c91c239596c (diff)
revival of the async-io functions
Diffstat (limited to 'exercises')
-rw-r--r--exercises/089_async6.zig95
1 files changed, 56 insertions, 39 deletions
diff --git a/exercises/089_async6.zig b/exercises/089_async6.zig
index 8bf50e9..eab03c9 100644
--- a/exercises/089_async6.zig
+++ b/exercises/089_async6.zig
@@ -1,54 +1,71 @@
//
-// The power and purpose of async/await becomes more apparent
-// when we do multiple things concurrently. Foo and Bar do not
-// depend on each other and can happen at the same time, but End
-// requires that they both be finished.
+// Sometimes you want to race multiple tasks and act on whichever
+// finishes first. That's what Select is for!
//
-// +---------+
-// | Start |
-// +---------+
-// / \
-// / \
-// +---------+ +---------+
-// | Foo | | Bar |
-// +---------+ +---------+
-// \ /
-// \ /
-// +---------+
-// | End |
-// +---------+
+// Select is like a Group, but lets you receive individual results
+// as tasks complete — one at a time:
//
-// We can express this in Zig like so:
+// const Race = std.Io.Select(union(enum) {
+// fast: u32,
+// slow: u32,
+// });
//
-// fn foo() u32 { ... }
-// fn bar() u32 { ... }
+// var buffer: [2]Race.Union = undefined;
+// var sel = Race.init(io, &buffer);
//
-// // Start
+// sel.async(.fast, fastFn, .{io});
+// sel.async(.slow, slowFn, .{io});
//
-// var foo_frame = async foo();
-// var bar_frame = async bar();
+// const winner = try sel.await(); // returns first completed
+// switch (winner) {
+// .fast => |val| ...,
+// .slow => |val| ...,
+// }
+// sel.cancelDiscard(); // cancel remaining, discard results
//
-// var foo_value = await foo_frame;
-// var bar_value = await bar_frame;
+// The buffer must be large enough for all tasks that might
+// complete before you call cancelDiscard().
//
-// // End
+// Fix this program to receive the winner of the race.
//
-// Please await TWO page titles!
-//
-const print = @import("std").debug.print;
+const std = @import("std");
+const print = std.debug.print;
+
+const RaceResult = std.Io.Select(union(enum) {
+ hare: []const u8,
+ tortoise: []const u8,
+});
+
+pub fn main(init: std.process.Init) !void {
+ const io = init.io;
+
+ var buffer: [2]RaceResult.Union = undefined;
+ var sel = RaceResult.init(io, &buffer);
-pub fn main() void {
- var com_frame = async getPageTitle("http://example.com");
- var org_frame = async getPageTitle("http://example.org");
+ sel.async(.hare, runHare, .{io});
+ sel.async(.tortoise, runTortoise, .{io});
- var com_title = com_frame;
- var org_title = org_frame;
+ // Wait for the first finisher.
+ // What Select method returns the first completed result?
+ const winner = ???;
+
+ switch (winner) {
+ .hare => |msg| print("Hare: {s}\n", .{msg}),
+ .tortoise => |msg| print("Tortoise: {s}\n", .{msg}),
+ }
+
+ // Clean up the loser — we don't need their result.
+ sel.cancelDiscard();
+}
- print(".com: {s}, .org: {s}.\n", .{ com_title, org_title });
+fn runHare(io: std.Io) []const u8 {
+ // The hare is fast — only 1 second!
+ io.sleep(std.Io.Duration.fromSeconds(1), .awake) catch return "I got canceled!";
+ return "I'm fast!";
}
-fn getPageTitle(url: []const u8) []const u8 {
- // Please PRETEND this is actually making a network request.
- _ = url;
- return "Example Title";
+fn runTortoise(io: std.Io) []const u8 {
+ // The tortoise is slow — 10 seconds.
+ io.sleep(std.Io.Duration.fromSeconds(10), .awake) catch return "I got canceled!";
+ return "Slow and steady...";
}