| 
   | 
const std = @import("std.zig");
const builtin = @import("builtin");
const testing = std.testing;
 | 
| once() | 
pub fn once(comptime f: fn () void) Once(f) {
    return Once(f){};
}
 | 
| Once() An object that executes the function  | 
pub fn Once(comptime f: fn () void) type {
    return struct {
        done: bool = false,
        mutex: std.Thread.Mutex = std.Thread.Mutex{},
 | 
| call() Call the function  | 
        pub fn call(self: *@This()) void {
            if (@atomicLoad(bool, &self.done, .Acquire))
                return;
            return self.callSlow();
        }
        fn callSlow(self: *@This()) void {
            @setCold(true);
            self.mutex.lock();
            defer self.mutex.unlock();
            // The first thread to acquire the mutex gets to run the initializer
            if (!self.done) {
                f();
                @atomicStore(bool, &self.done, true, .Release);
            }
        }
    };
}
var global_number: i32 = 0;
var global_once = once(incr);
fn incr() void {
    global_number += 1;
}
 | 
| Test:Once executes its function just once | 
test "Once executes its function just once" {
    if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
    if (builtin.single_threaded) {
        global_once.call();
        global_once.call();
    } else {
        var threads: [10]std.Thread = undefined;
        defer for (threads) |handle| handle.join();
        for (&threads) |*handle| {
            handle.* = try std.Thread.spawn(.{}, struct {
                fn thread_fn(x: u8) void {
                    _ = x;
                    global_once.call();
                }
            }.thread_fn, .{0});
        }
    }
    try testing.expectEqual(@as(i32, 1), global_number);
}
 | 
| Generated by zstd-browse2 on 2023-11-04 14:12:35 -0400. |