summaryrefslogtreecommitdiff
path: root/exercises/091_async8.zig
blob: 10921c3dbcde024f417e1181fa57490650bd8c59 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
//
// Tasks often need to communicate! Io provides Queue for this —
// a bounded, thread-safe channel for passing data between tasks:
//
//     var backing: [16]u32 = undefined;
//     var queue: std.Io.Queue(u32) = .init(&backing);
//
//     // Producer task:
//     try queue.putOne(io, value);    // blocks if queue is full
//
//     // Consumer task:
//     const val = try queue.getOne(io);  // blocks if queue is empty
//
// When the producer is done, it calls queue.close(io) to signal
// that no more data is coming. After that, getOne() will return
// error.Closed once the queue is drained.
//
// This is the classic producer/consumer pattern — one task
// generates work, another processes it, and the queue handles
// all the synchronization automatically.
//
// Fix this program: the producer sends numbers 1..10, the
// consumer sums them up. The expected sum is 55.
//
const std = @import("std");
const print = std.debug.print;

pub fn main(init: std.process.Init) !void {
    const io = init.io;

    var backing: [4]u32 = undefined;
    var queue: std.Io.Queue(u32) = .init(&backing);

    var group: std.Io.Group = .init;

    group.async(io, producer, .{ io, &queue });
    group.async(io, consumer, .{ io, &queue });

    try group.await(io);
}

fn producer(io: std.Io, queue: *std.Io.Queue(u32)) void {
    // Send numbers 1 through 10 into the queue.
    for (1..11) |i| {
        // What Queue method sends a single element, blocking if full?
        queue.???(io, @intCast(i)) catch return;
    }
    // Signal that we're done sending.
    queue.close(io);
}

fn consumer(io: std.Io, queue: *std.Io.Queue(u32)) void {
    var sum: u32 = 0;
    while (true) {
        const value = queue.getOne(io) catch |err| switch (err) {
            error.Closed => break,
            error.Canceled => return,
        };
        sum += value;
    }
    print("Sum of 1..10 = {}\n", .{sum});
}