my ziglings
0

Configure Feed

Select the types of activity you want to include in your feed.

Merge branch 'main' into 95-bug4

Chris Boesch (Apr 14, 2026, 12:43 PM +0200) f10c3d4e b8a639e7

+80 -39
+1 -6
build.zig
··· 1179 1179 }, 1180 1180 .{ 1181 1181 .main_file = "093_async9.zig", 1182 - .output = 1183 - \\Computing concurrently! 1184 - \\Main continues... 1185 - \\Main done waiting. 1186 - \\Result: 123 1187 - , // pay attention to the comma 1182 + .output = "Worker 1 found signal start over threshold at index 12!", 1188 1183 }, 1189 1184 .{ 1190 1185 .main_file = "094_async10.zig",
+55 -21
exercises/093_async9.zig
··· 30 30 // defer _ = future.cancel(io); 31 31 // const result = future.await(io); 32 32 // 33 - // Notice the 'try' — that's the key difference in usage! 33 + // Let's try a slightly simplified example from signal processing: 34 + // Suppose we're looking for the beginning of a signal above the noise 35 + // level. To do this, we compare each entry from beginning to end with 36 + // the threshold.To speed things up a bit, we split the signal into 37 + // two halves and have two parallel workers search for them. 38 + // Who finds the beginning first "wins" and thus ends the other one. 34 39 // 35 - // Fix this program to launch the computation concurrently. 40 + // As I said, this is a simplified explanation, 41 + // but in practice it's done more or less like this. 36 42 // 37 43 const std = @import("std"); 44 + const Io = std.Io; 38 45 const print = std.debug.print; 46 + 47 + const SearchResult = struct { 48 + worker_id: u8, 49 + index: usize, 50 + }; 39 51 40 52 pub fn main(init: std.process.Init) !void { 41 53 const io = init.io; 42 54 43 - // Launch with a guaranteed separate unit of concurrency. 44 - // Which Io method guarantees this? 45 - // (Hint: unlike io.async, this one can fail!) 46 - var future = try io.???(compute, .{io}); 47 - defer _ = future.cancel(io); 55 + const data = [_]u32{ 10, 23, 45, 67, 12, 69, 3, 54, 69, 42, 68, 56, 71, 79, 79, 75, 70, 77 }; 56 + const threshold = 70; 57 + const mid = data.len / 2; 48 58 49 - // Note: All breaks in this exercise (using sleep) 50 - // are only necessary for a deterministic result. 51 - io.sleep(std.Io.Duration.fromMilliseconds(100), .awake) catch {}; 59 + // A queue with space for one result. 60 + var buf: [1]SearchResult = undefined; 61 + var queue = Io.Queue(SearchResult).init(&buf); 52 62 53 - print("Main continues...\n", .{}); 63 + // Launch two workers, each searching half the array. 64 + var f1 = ???(searchRange, .{ data[0..mid], target, 0, 0, &queue, io }); 65 + defer _ = f1.cancel(io); 54 66 55 - // Wait 1 second for the output order. 56 - io.sleep(std.Io.Duration.fromMilliseconds(200), .awake) catch {}; 67 + var f2 = ???(searchRange, .{ data[mid..], target, mid, 1, &queue, io }); 68 + defer _ = f2.cancel(io); 57 69 58 - print("Main done waiting.\n", .{}); 70 + // Wait for the first result. 71 + const result = try queue.getOne(io); 59 72 60 - const result = future.await(io); 61 - print("Result: {}\n", .{result}); 73 + print("Worker {} found signal start over threshold at index {}!\n", .{ result.worker_id, result.index }); 62 74 } 63 75 64 - fn compute(io: std.Io) u32 { 65 - print("Computing concurrently!\n", .{}); 66 - // Simulate some work. 67 - io.sleep(std.Io.Duration.fromMilliseconds(400), .awake) catch return 0; 68 - return 123; 76 + fn searchThreshold( 77 + io: Io, 78 + slice: []const u32, 79 + threshold: u32, 80 + base_offset: usize, 81 + worker_id: u8, 82 + queue: *Io.Queue(SearchResult), 83 + ) void { 84 + for (slice, 0..) |val, i| { 85 + // This pause is necessary so that the process can be canceled 86 + // if another one has already finished. Without this pause, 87 + // all workers would continue until the end. 88 + io.sleep(Io.Duration.fromMilliseconds(1), .awake) catch return; 89 + 90 + // To test this, you can view the work of the workers 91 + // and then comment out the pause. 92 + // print("id: {} - val: {}\n", .{ worker_id, val }); 93 + 94 + if (val >= threshold) { 95 + queue.putOne(io, .{ 96 + .worker_id = worker_id, 97 + .index = base_offset + i, 98 + }) catch return; 99 + return; 100 + } 101 + } 69 102 } 103 +
+3
exercises/108_threading2.zig
··· 105 105 // 106 106 // And you should remove the formatting restriction in "print", 107 107 // otherwise you will not be able to see the additional digits. 108 + // 109 + // If count = 10_000_000_000_000 you should see the following: 110 + // 3.141592653589
+19 -10
patches/patches/093_async9.patch
··· 1 - --- exercises/093_async9.zig 2026-04-13 17:55:35.567204530 +0200 2 - +++ answers/093_async9.zig 2026-04-13 18:05:05.636355044 +0200 3 - @@ -43,7 +43,7 @@ 4 - // Launch with a guaranteed separate unit of concurrency. 5 - // Which Io method guarantees this? 6 - // (Hint: unlike io.async, this one can fail!) 7 - - var future = try io.???(compute, .{io}); 8 - + var future = try io.concurrent(compute, .{io}); 9 - defer _ = future.cancel(io); 1 + --- exercises/093_async9.zig 2026-04-14 09:50:05.694073287 +0200 2 + +++ answers/093_async9.zig 2026-04-14 09:49:58.604934765 +0200 3 + @@ -61,10 +61,10 @@ 4 + var queue = Io.Queue(SearchResult).init(&buf); 10 5 11 - // Note: All breaks in this exercise (using sleep) 6 + // Launch two workers, each searching half the array. 7 + - var f1 = ???(searchRange, .{ data[0..mid], target, 0, 0, &queue, io }); 8 + + var f1 = try io.concurrent(searchThreshold, .{ io, data[0..mid], threshold, 0, 0, &queue }); 9 + defer _ = f1.cancel(io); 10 + 11 + - var f2 = ???(searchRange, .{ data[mid..], target, mid, 1, &queue, io }); 12 + + var f2 = try io.concurrent(searchThreshold, .{ io, data[mid..], threshold, mid, 1, &queue }); 13 + defer _ = f2.cancel(io); 14 + 15 + // Wait for the first result. 16 + @@ -100,4 +100,3 @@ 17 + } 18 + } 19 + } 20 + -
+2 -2
patches/patches/108_threading2.patch
··· 1 - --- exercises/108_threading2.zig 2025-08-15 15:17:57.839348063 +0200 2 - +++ answers/108_threading2.zig 2026-04-02 10:51:15.811831656 +0200 1 + --- exercises/108_threading2.zig 2026-04-14 06:44:18.848246237 +0200 2 + +++ answers/108_threading2.zig 2026-04-14 08:15:30.894485037 +0200 3 3 @@ -81,8 +81,8 @@ 4 4 defer handle1.join(); 5 5