| ... | @@ -604,82 +604,3 @@ test "Condition - broadcasting - wake all threads" { | ... | @@ -604,82 +604,3 @@ test "Condition - broadcasting - wake all threads" { |
| 604 | } | 604 | } |
| 605 | } | 605 | } |
| 606 | } | 606 | } |
| 607 | | | |
| 608 | test "Condition - signal wakes one" { | | |
| 609 | // This test requires spawning threads | | |
| 610 | if (builtin.single_threaded) { | | |
| 611 | return error.SkipZigTest; | | |
| 612 | } | | |
| 613 | | | |
| 614 | if (builtin.os.tag == .windows) { | | |
| 615 | // https://github.com/ziglang/zig/issues/13660 | | |
| 616 | return error.SkipZigTest; | | |
| 617 | } | | |
| 618 | | | |
| 619 | var num_runs: usize = 1; | | |
| 620 | const num_threads = 3; | | |
| 621 | const timeoutDelay = 10 * std.time.ns_per_ms; | | |
| 622 | | | |
| 623 | while (num_runs > 0) : (num_runs -= 1) { | | |
| 624 | | | |
| 625 | // Start multiple runner threads, wait for them to start and send the signal | | |
| 626 | // then. Expect that one thread wake up and all other times out. | | |
| 627 | // | | |
| 628 | // Test depends on delay in timedWait! If too small all threads can timeout | | |
| 629 | // before any one gets wake up. | | |
| 630 | | | |
| 631 | const Runner = struct { | | |
| 632 | mutex: Mutex = .{}, | | |
| 633 | cond: Condition = .{}, | | |
| 634 | completed: Condition = .{}, | | |
| 635 | count: usize = 0, | | |
| 636 | threads: [num_threads]std.Thread = undefined, | | |
| 637 | wakeups: usize = 0, | | |
| 638 | timeouts: usize = 0, | | |
| 639 | | | |
| 640 | fn run(self: *@This()) void { | | |
| 641 | self.mutex.lock(); | | |
| 642 | defer self.mutex.unlock(); | | |
| 643 | | | |
| 644 | // The last started thread tells the main test thread it's completed. | | |
| 645 | self.count += 1; | | |
| 646 | if (self.count == num_threads) { | | |
| 647 | self.completed.signal(); | | |
| 648 | } | | |
| 649 | | | |
| 650 | self.cond.timedWait(&self.mutex, timeoutDelay) catch { | | |
| 651 | self.timeouts += 1; | | |
| 652 | return; | | |
| 653 | }; | | |
| 654 | self.wakeups += 1; | | |
| 655 | } | | |
| 656 | }; | | |
| 657 | | | |
| 658 | // Start threads | | |
| 659 | var runner = Runner{}; | | |
| 660 | for (runner.threads) |*t| { | | |
| 661 | t.* = try std.Thread.spawn(.{}, Runner.run, .{&runner}); | | |
| 662 | } | | |
| 663 | | | |
| 664 | { | | |
| 665 | runner.mutex.lock(); | | |
| 666 | defer runner.mutex.unlock(); | | |
| 667 | | | |
| 668 | // Wait for all the threads to spawn. | | |
| 669 | // timedWait() to detect any potential deadlocks. | | |
| 670 | while (runner.count != num_threads) { | | |
| 671 | try runner.completed.timedWait(&runner.mutex, 1 * std.time.ns_per_s); | | |
| 672 | } | | |
| 673 | // Signal one thread, the others should get timeout. | | |
| 674 | runner.cond.signal(); | | |
| 675 | } | | |
| 676 | | | |
| 677 | for (runner.threads) |t| { | | |
| 678 | t.join(); | | |
| 679 | } | | |
| 680 | | | |
| 681 | // Expect that only one got singal | | |
| 682 | try std.testing.expectEqual(runner.wakeups, 1); | | |
| 683 | try std.testing.expectEqual(runner.timeouts, num_threads - 1); | | |
| 684 | } | | |
| 685 | } | | |