diff --git a/libcxx/test/std/thread/thread.condition/notify_all_at_thread_exit_lwg3343.pass.cpp b/libcxx/test/std/thread/thread.condition/notify_all_at_thread_exit_lwg3343.pass.cpp --- a/libcxx/test/std/thread/thread.condition/notify_all_at_thread_exit_lwg3343.pass.cpp +++ b/libcxx/test/std/thread/thread.condition/notify_all_at_thread_exit_lwg3343.pass.cpp @@ -8,8 +8,6 @@ // // UNSUPPORTED: no-threads -// ALLOW_RETRIES: 3 - // notify_all_at_thread_exit(...) requires move semantics to transfer the unique_lock. // UNSUPPORTED: c++03 @@ -43,26 +41,35 @@ X x; std::mutex m; int threads_active = N; - - for (int i = 0; i < N; ++i) { + { + // Take the mutex to make sure the threads are waiting their processing + // until the main thread is waiting for the condition variable. Otherwise + // it might happen all threads have stopped before waiting on the + // condition variable. By holding the mutex we pause the threads until we + // are waiting for the condition variable. + std::unique_lock lk(m); + for (int i = 0; i < N; ++i) { std::thread t = support::make_test_thread([&] { - // Signal thread completion - std::unique_lock lk(m); - --threads_active; - std::notify_all_at_thread_exit(x.cv_, std::move(lk)); - std::this_thread::sleep_for(std::chrono::milliseconds(1)); + // Signal thread completion + std::unique_lock lk(m); + --threads_active; + std::notify_all_at_thread_exit(x.cv_, std::move(lk)); + std::this_thread::sleep_for(std::chrono::milliseconds(1)); }); t.detach(); - } + } + // Validate the threads are still waiting to acquire their mutex. + assert(threads_active == 3); - // Wait until all threads complete, i.e. until they've all - // decremented `threads_active` and then unlocked `m` at thread exit. - // It is possible that this `wait` may spuriously wake up, - // but it won't be able to continue until the last thread - // unlocks `m`. - { - std::unique_lock lk(m); - x.cv_.wait(lk, [&]() { return threads_active == 0; }); + // Wait until all threads complete, i.e. until they've all + // decremented `threads_active` and then unlocked `m` at thread exit. + // It is possible that this `wait` may spuriously wake up, + // but it won't be able to continue until the last thread + // unlocks `m`. + x.cv_.wait(lk, [&]() { return threads_active == 0; }); + + // Did the condition variable properly validate its condition. + assert(threads_active == 0); } // Destroy the condition_variable and shred the bytes.