ℹ️ Select 'Choose Exercise', or randomize 'Next Random Exercise' in selected language.

Choose Exercise:
Timer 00:00
WPM --
Score --
Acc --
Correct chars --

Zig Async Orchestration with Channels

Zig

Goal -- WPM

Ready
Exercise Algorithm Area
1const std = @import("std");
2
3const Allocator = std.mem.Allocator;
4
5// Producer task
6async fn producer(channel: std.async.Channel(i32), count: usize) void {
7std.debug.print("Producer started.\n", .{});
8for (0..count) |i|
9{
10std.debug.print("Producer sending: {d}\n", .{i});
11channel.send(i) catch {
12std.debug.print("Producer failed to send, channel closed?\n", .{});
13return;
14};
15// Simulate some work
16std.time.sleep(100 * 1000);
17}
18std.debug.print("Producer finished sending. Closing channel.\n", .{});
19channel.close();
20}
21
22// Consumer task
23async fn consumer(channel: std.async.Channel(i32)) void {
24std.debug.print("Consumer started.\n", .{});
25while (channel.receive()) |value|
26{
27std.debug.print("Consumer received: {d}\n", .{value});
28// Simulate some work
29std.time.sleep(150 * 1000);
30}
31std.debug.print("Consumer finished (channel closed).\n", .{});
32}
33
34pub fn main() !void {
35var gpa = std.heap.GeneralPurposeAllocator(.{}){};
36defer _ = gpa.deinit();
37const allocator = gpa.allocator();
38
39// Create a channel with a buffer size of 5
40var channel = std.async.Channel(i32).init(allocator, 5);
41defer channel.deinit();
42
43const num_items_to_produce = 10;
44
45// Spawn producer and consumer tasks
46const producer_task = std.async.spawn(producer, .{ channel.get_sender(), num_items_to_produce });
47const consumer_task = std.async.spawn(consumer, .{ channel.get_receiver() });
48
49// Wait for tasks to complete
50std.async.wait(producer_task);
51std.async.wait(consumer_task);
52
53std.debug.print("All tasks finished.\n", .{});
54}
Algorithm description viewbox

Zig Async Orchestration with Channels

Algorithm description:

This Zig program demonstrates asynchronous programming using channels for inter-task communication. A `producer` task generates numbers and sends them through a channel, while a `consumer` task receives and prints these numbers. The channel acts as a synchronized queue, ensuring that data is passed safely between the asynchronous tasks. This pattern is fundamental for building concurrent applications, handling I/O operations, and managing distributed systems.

Algorithm explanation:

The `producer` function is an `async` task that sends `count` integers through a `std.async.Channel`. It iterates, sends each number using `channel.send()`, and simulates work with `std.time.sleep()`. If `send` fails (e.g., channel is full and not being read from, or closed), it prints an error and exits. After sending all numbers, it closes the channel using `channel.close()`. The `consumer` function is another `async` task that continuously receives values from the channel using `channel.receive()`. The `while (channel.receive()) |value|` loop automatically terminates when the channel is closed and empty. It prints received values and simulates work. The `main` function initializes an allocator, creates a buffered channel, spawns the `producer` and `consumer` tasks using `std.async.spawn`, and then waits for both tasks to complete using `std.async.wait`. The channel's buffer size prevents the producer from blocking indefinitely if the consumer is slower, and `channel.close()` signals the end of data. Time complexity is dependent on the number of items and sleep durations, but channel operations are typically O(1) amortized. Space complexity is O(B) for the channel buffer, where B is the buffer size.

Pseudocode:

Define producer(channel, count):
  print "Producer started."
  for i from 0 to count-1:
    print "Producer sending: i"
    send i to channel
    if send fails, print error and return
    sleep for a short duration
  print "Producer finished. Closing channel."
  close channel

Define consumer(channel):
  print "Consumer started."
  loop:
    receive value from channel
    if receive succeeds:
      print "Consumer received: value"
      sleep for a short duration
    else (channel closed and empty):
      break loop
  print "Consumer finished."

main():
  initialize allocator
  create a buffered channel (e.g., size 5)
  spawn producer task with channel sender and count
  spawn consumer task with channel receiver
  wait for producer task to finish
  wait for consumer task to finish
  print "All tasks finished."