Thread Barriers

I ended up implementing the following code:

File: Barrier.zig

//! A thread barrier is a mechanism for thread synchronization.
//! Blocks threads until a certain number of threads has reached the barrier,
//! after which all threads are unblocked and the barrier is reset.
//!
//! Based on http://byronlai.com/jekyll/update/2015/12/26/barrier.html

const std = @import("std");
const Self = @This();

mutex: std.Thread.Mutex,
cond: std.Thread.Condition,
required_thread_count: usize,
current_thread_count: usize,
cycle: usize,

pub fn init(
    /// Number of threads that must enter the barrier before it is lifted.
    thread_count: usize,
) Self {
    return .{
        .mutex = .{},
        .cond = .{},
        .required_thread_count = thread_count,
        .current_thread_count = 0,
        .cycle = 0,
    };
}

/// Wait at the barrier. If this is the final thread, lift the barrier instead.
pub fn wait(self: *Self) void {
    self.mutex.lock();
    defer self.mutex.unlock();
    self.current_thread_count += 1;
    if (self.current_thread_count == self.required_thread_count) {
        // All threads have arrived at the barrier.
        self.cycle += 1;
        self.current_thread_count = 0;
        self.cond.broadcast();
    } else {
        // Wait for other threads to arrive...
        const my_cycle: usize = self.cycle;
        // Threads may sporadically wake up. This loop prevents them from leaving the barrier too early.
        while (self.cycle == my_cycle)
            self.cond.wait(&self.mutex);
    }
}

/// Pass through the barrier without waiting. If this is the final thread, also lift the barrier.
pub fn passthrough(self: *Self) void {
    self.mutex.lock();
    defer self.mutex.unlock();
    self.current_thread_count += 1;
    if (self.current_thread_count == self.required_thread_count) {
        // All threads have arrived at the barrier.
        self.cycle += 1;
        self.current_thread_count = 0;
        self.cond.broadcast();
    }
}