diff options
| author | Chris Boesch <chrboesch@noreply.codeberg.org> | 2026-04-03 19:32:53 +0200 |
|---|---|---|
| committer | Chris Boesch <chrboesch@noreply.codeberg.org> | 2026-04-03 19:32:53 +0200 |
| commit | 5307b2a338a92130bc498fb1dc7d21a9fd1b0db4 (patch) | |
| tree | 51279ca4fbd7bd90294dd563640c12a8c25c79c6 /exercises/091_async7.zig | |
| parent | 3056a2b5442f2f1ec58db3f3493109064ad2a2a5 (diff) | |
| parent | f6a6798c8b6b813bd2ceee81db276e05327a76e0 (diff) | |
Merge pull request 'revival of the async-io functions' (#383) from asyncIo into main
Reviewed-on: https://codeberg.org/ziglings/exercises/pulls/383
Diffstat (limited to 'exercises/091_async7.zig')
| -rw-r--r-- | exercises/091_async7.zig | 57 |
1 files changed, 57 insertions, 0 deletions
diff --git a/exercises/091_async7.zig b/exercises/091_async7.zig new file mode 100644 index 0000000..bfe6ffd --- /dev/null +++ b/exercises/091_async7.zig @@ -0,0 +1,57 @@ +// +// When multiple async tasks access shared data, you need +// synchronization! Io provides a Mutex for this: +// +// var mutex: std.Io.Mutex = .init; +// +// // In a task: +// try mutex.lock(io); // blocks until lock is acquired +// defer mutex.unlock(); +// // ... critical section: safe to modify shared data ... +// +// Without the mutex, concurrent tasks could read and write the +// same memory simultaneously, causing a data race — the result +// would be unpredictable. +// +// mutex.lock() is a cancellation point — it can return +// error.Canceled. There's also tryLock() which returns +// immediately (true if acquired, false if not). +// +// Fix this program so the counter is correctly synchronized. +// Without the fix, the final count would be unpredictable. +// With it, four tasks incrementing 100 times each = 400. +// +const std = @import("std"); +const print = std.debug.print; + +const SharedState = struct { + counter: u32 = 0, + mutex: std.Io.Mutex = .init, +}; + +pub fn main(init: std.process.Init) !void { + const io = init.io; + var state = SharedState{}; + + var group: std.Io.Group = .init; + + group.async(io, increment, .{ io, &state, 100 }); + group.async(io, increment, .{ io, &state, 100 }); + group.async(io, increment, .{ io, &state, 100 }); + group.async(io, increment, .{ io, &state, 100 }); + + try group.await(io); + + print("Counter: {}\n", .{state.counter}); +} + +fn increment(io: std.Io, state: *SharedState, times: u32) void { + for (0..times) |_| { + // Acquire the lock before modifying shared state. + // What Mutex method blocks until the lock is acquired? + state.mutex.??? catch return; + defer state.mutex.unlock(); // <-- what's missing here? + + state.counter += 1; + } +} |
