revival of the async-io functions

This commit is contained in:
Chris Boesch
2026-04-01 23:44:24 +02:00
parent fcfb0e80a0
commit e22748d488
4 changed files with 65 additions and 38 deletions

View File

@@ -193,7 +193,7 @@ Zig Core Language
* [x] Sentinel termination * [x] Sentinel termination
* [x] Quoted identifiers @"" * [x] Quoted identifiers @""
* [x] Anonymous structs/tuples/lists * [x] Anonymous structs/tuples/lists
* [ ] Async I/O * [x] Async I/O
* [X] Interfaces * [X] Interfaces
* [X] Bit manipulation * [X] Bit manipulation
* [X] Working with C * [X] Working with C

View File

@@ -1140,9 +1140,12 @@ const exercises = [_]Exercise{
}, },
.{ .{
.main_file = "088_async5.zig", .main_file = "088_async5.zig",
.output = "Example Title.", .output =
.skip = true, \\Starting long computation...
.skip_hint = "async has not been implemented in the current compiler version.", \\Canceling slow task...
\\Task was canceled, cleaning up.
\\Task returned: 0
, // pay attention to the comma
}, },
.{ .{
.main_file = "089_async6.zig", .main_file = "089_async6.zig",

View File

@@ -1,48 +1,61 @@
// //
// Sure, we can solve our async value problem with a global // One of the most important features of the new Io system is
// variable. But this hardly seems like an ideal solution. // structured cancellation!
// //
// So how do we REALLY get return values from async functions? // 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
// //
// The 'await' keyword waits for an async function to complete // A "cancellation point" is any Io function that can return
// and then captures its return value. // error.Canceled - most commonly io.sleep():
// //
// fn foo() u32 { // fn myTask(io: std.Io) u32 {
// return 5; // io.sleep(...) catch |err| switch (err) {
// error.Canceled => return 0, // handle gracefully
// };
// return 42;
// } // }
// //
// var foo_frame = async foo(); // invoke and get frame // This is fundamentally different from killing a thread -
// var value = await foo_frame; // await result using frame // the task gets a chance to clean up and return a value!
// //
// The above example is just a silly way to call foo() and get 5 // Fix this program: the slow task would take 10 seconds,
// back. But if foo() did something more interesting such as wait // but we cancel it after 1 second. The task should detect
// for a network response to get that 5, our code would pause // the cancellation and return early.
// until the value was ready.
// //
// As you can see, async/await basically splits a function call const std = @import("std");
// into two parts: const print = std.debug.print;
//
// 1. Invoke the function ('async')
// 2. Getting the return value ('await')
//
// Also notice that a 'suspend' keyword does NOT need to exist in
// a function to be called in an async context.
//
// Please use 'await' to get the string returned by
// getPageTitle().
//
const print = @import("std").debug.print;
pub fn main() void { pub fn main(init: std.process.Init) !void {
var myframe = async getPageTitle("http://example.com"); const io = init.io;
var value = ??? var future = io.async(slowTask, .{io});
print("{s}\n", .{value}); // 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 getPageTitle(url: []const u8) []const u8 { fn slowTask(io: std.Io) u32 {
// Please PRETEND this is actually making a network request. print("Starting long computation...\n", .{});
_ = url;
return "Example Title."; // 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;
} }

View File

@@ -0,0 +1,11 @@
--- exercises/088_async5.zig 2026-04-01 23:40:40.505855238 +0200
+++ answers/088_async5.zig 2026-04-01 23:40:10.176236971 +0200
@@ -40,7 +40,7 @@
// We don't want to wait 10 seconds!
// Which Future method requests cancellation AND returns the result?
- const result = ???;
+ const result = future.cancel(io);
print("Task returned: {}\n", .{result});
}