···55// them all. The Io backend may run them concurrently:
66//
77// var f1 = io.async(taskA, .{});
88+// defer _ = f1.cancel(io);
89// var f2 = io.async(taskB, .{});
99-//
1010-// // Both tasks may be running now!
1010+// defer _ = f2.cancel(io);
1111// const a = f1.await(io);
1212// const b = f2.await(io);
1313//
1414-// There's also io.concurrent() which provides a STRONGER guarantee:
1515-// it ensures the function gets its own unit of concurrency (e.g. a
1616-// real OS thread). But it can fail with error.ConcurrencyUnavailable
1717-// if resources are exhausted.
1818-//
1919-// io.async() is more portable: if no thread is available, it simply
2020-// runs the function synchronously. This makes it the right default
2121-// for most code.
1414+// Notice the defer pattern: each async call is immediately
1515+// followed by a defer cancel. This ensures cleanup even if
1616+// we return early or hit an error before reaching await.
1717+// Since await/cancel are idempotent, the defer is harmless
1818+// if we've already awaited.
2219//
2320// Fix this program to launch both tasks and collect their results.
2421//
···2926 const io = init.io;
30273128 // Launch both tasks asynchronously.
3232- var future_a = io.async(slowAdd, .{ 10, 20 });
2929+ var future_a = io.async(slowAdd, .{ 1, 2 });
3030+ defer _ = future_a.cancel(io);
3331 var future_b = ???(slowMul, .{ 6, 7 });
3232+ defer _ = future_b.cancel(io);
34333534 // Await both results.
3635 const sum = future_a.await(io);
3737- const product = future_b.???(io);
3636+ const product = future_b.await(io);
38373938 print("{} + {} = {}\n", .{ 1, 2, sum });
4039 print("{} * {} = {}\n", .{ 6, 7, product });