File: zig.actual

package info (click to toggle)
golang-github-alecthomas-chroma 0.8.2-3
  • links: PTS, VCS
  • area: main
  • in suites: bullseye
  • size: 3,332 kB
  • sloc: python: 228; javascript: 79; makefile: 20
file content (66 lines) | stat: -rw-r--r-- 1,741 bytes parent folder | download | duplicates (6)
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
63
64
65
66
const std = @import("std.zig");
const builtin = std.builtin;
const testing = std.testing;

pub fn once(comptime f: fn () void) Once(f) {
    return Once(f){};
}

/// An object that executes the function `f` just once.
pub fn Once(comptime f: fn () void) type {
    return struct {
        done: bool = false,
        mutex: std.Mutex = std.Mutex.init(),

        /// Call the function `f`.
        /// If `call` is invoked multiple times `f` will be executed only the
        /// first time.
        /// The invocations are thread-safe.
        pub fn call(self: *@This()) void {
            if (@atomicLoad(bool, &self.done, .Acquire))
                return;

            return self.callSlow();
        }

        fn callSlow(self: *@This()) void {
            @setCold(true);

            const T = self.mutex.acquire();
            defer T.release();

            // 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" {
    if (builtin.single_threaded) {
        global_once.call();
        global_once.call();
    } else {
        var threads: [10]*std.Thread = undefined;
        defer for (threads) |handle| handle.wait();

        for (threads) |*handle| {
            handle.* = try std.Thread.spawn(@as(u8, 0), struct {
                fn thread_fn(x: u8) void {
                    global_once.call();
                }
            }.thread_fn);
        }
    }

    testing.expectEqual(@as(i32, 1), global_number);
}