lib/simd/src/thread/wait.zig
daab053ee43316e1809a84551d573ddd1e5bf3d2
1 const std = @import("std");
2 const sys = @import("sys");
3
4 pub const WaitWord = std.atomic.Value(u32);
5
6 pub fn nanoSleep(nanoseconds: u64) bool {
7 if (!sys.time.supportsAwakeClock()) return false;
8 sys.time.sleepNanoseconds(nanoseconds);
9 return true;
10 }
11
12 pub fn blockUntilDifferent(
13 previous: u32,
14 word: *const WaitWord,
15 ) u32 {
16 return sys.thread.blockUntilDifferent(previous, word);
17 }
18
19 pub fn wakeAll(word: *WaitWord) void {
20 sys.thread.wakeAll(word);
21 }
22
23 const WakeContext = struct {
24 word: *WaitWord,
25 observed: *u32,
26
27 fn wait(self: WakeContext) void {
28 self.observed.* = blockUntilDifferent(7, self.word);
29 }
30 };
31
32 test "Highway wait word blocks until storage changes and wakes" {
33 if (!sys.thread.threadsSupported()) return error.SkipZigTest;
34 var word = WaitWord.init(7);
35 var observed: u32 = 0;
36 const handle = try sys.thread.spawn(WakeContext.wait, .{
37 WakeContext{ .word = &word, .observed = &observed },
38 });
39 _ = nanoSleep(std.time.ns_per_ms);
40 word.store(11, .release);
41 wakeAll(&word);
42 handle.join();
43 try std.testing.expectEqual(@as(u32, 11), observed);
44 try std.testing.expectEqual(@as(u32, 11), blockUntilDifferent(7, &word));
45 }