Commit ff18103ef6

Alex Kladov <aleksey.kladov@gmail.com>
2024-04-15 14:57:41
std: improve std.once tests
* fix UB when Thread.spawn fails, and we try to join uninitialized threads (through new `thread_count` variable). * make sure that the tests pins down synchronization guarantees: in the main thread, we can observe `1` due to synchronization from `Thread.join()`. To make sure that once uses Acq/Rel, and not just relaxed, we should also additionally check that each thread observes 1, regardless of whether it was the one to call once.
1 parent 1e5075f
Changed files (1)
lib
lib/std/once.zig
@@ -7,6 +7,7 @@ pub fn once(comptime f: fn () void) Once(f) {
 }
 
 /// An object that executes the function `f` just once.
+/// It is undefined behavior if `f` re-enters the same Once instance.
 pub fn Once(comptime f: fn () void) type {
     return struct {
         done: bool = false,
@@ -51,15 +52,18 @@ test "Once executes its function just once" {
         global_once.call();
     } else {
         var threads: [10]std.Thread = undefined;
-        defer for (threads) |handle| handle.join();
+        var thread_count: usize = 0;
+        defer for (threads[0..thread_count]) |handle| handle.join();
 
         for (&threads) |*handle| {
             handle.* = try std.Thread.spawn(.{}, struct {
                 fn thread_fn(x: u8) void {
                     _ = x;
                     global_once.call();
+                    if (global_number != 1) @panic("memory ordering bug");
                 }
             }.thread_fn, .{0});
+            thread_count += 1;
         }
     }