From fb8aa40b2253cf48fb93964a1f0020e862b8b17b Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Fri, 5 Dec 2025 14:41:08 -0800 Subject: [PATCH] `GH_000685_condition_variable_any`: Revert test changes for LWG-4301 --- .../GH_000685_condition_variable_any/test.cpp | 134 ------------------ 1 file changed, 134 deletions(-) diff --git a/tests/std/tests/GH_000685_condition_variable_any/test.cpp b/tests/std/tests/GH_000685_condition_variable_any/test.cpp index 1edf99b2c3b..03ebd7023b8 100644 --- a/tests/std/tests/GH_000685_condition_variable_any/test.cpp +++ b/tests/std/tests/GH_000685_condition_variable_any/test.cpp @@ -2,21 +2,13 @@ // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // Test GH-685 "wait_for in condition_variable_any should unlock and lock" -// Test LWG-4301 "condition_variable{_any}::wait_{for, until} should take timeout by value" -#include #include #include #include -#include #include -#include #include -#if _HAS_CXX20 -#include -#endif // _HAS_CXX20 - using namespace std; using namespace std::chrono; @@ -87,135 +79,9 @@ namespace { assert(m.num_locks() == 4); #endif // _HAS_CXX20 } - - // Minimal example inspired by LWG-4301, modified due to missing std::latch before C++20 - // and generalized to test all overloads of condition_variable{_any}::wait_{for, until}. - // Idea: Make the main thread wait for a CV with a short timeout and modify it from another thread in the meantime. - // If the main thread wait times out after a short time, the modification did not influence the ongoing wait. - template - void test_timeout_immutable(const int test_number, const int retries_remaining = 5) { - printf("\ntest %d\n", test_number); - - mutex m; - CV cv; - unique_lock main_lock(m); // Prevent other thread from modifying timeout too early - - // Start with very short timeout and let other_thread change it to very large while main thread is waiting - constexpr auto short_timeout = 1s; - constexpr auto long_timeout = 10s; - - atomic_flag waiting_for_other_thread{}; - waiting_for_other_thread.test_and_set(); - - const auto wait_start = steady_clock::now(); - auto timeout_duration = short_timeout; - auto timeout = wait_start + timeout_duration; - - const auto set_timeout = [&](const auto new_timeout) { - timeout_duration = new_timeout; - timeout = steady_clock::now() + new_timeout; - }; - - thread other_thread([&] { - printf( - "thread start after %lld ms\n", duration_cast(steady_clock::now() - wait_start).count()); - waiting_for_other_thread.clear(); - // Immediately blocks since the main thread owns the mutex m. - lock_guard other_lock(m); - puts("thread lock"); - - // If the timeout provided to condition_variable{_any}::wait_{for, until} was mutable, - // we will get timeout in the main thread after much longer time - set_timeout(long_timeout); - puts("thread end"); - }); - - while (waiting_for_other_thread.test_and_set()) { - this_thread::yield(); // freeze the main thread from proceeding until other thread is started - } - printf("main resumed after %lld ms\n", duration_cast(steady_clock::now() - wait_start).count()); - set_timeout(short_timeout); - - puts("main waiting"); - const bool cv_wait_timed_out = [&] { - switch (test_number) { - case 0: - return cv.wait_until(main_lock, timeout) == cv_status::timeout; - - case 1: - return cv.wait_until(main_lock, timeout, [] { return false; }) == false; - - case 2: - return cv.wait_for(main_lock, timeout_duration) == cv_status::timeout; - - case 3: - return cv.wait_for(main_lock, timeout_duration, [] { return false; }) == false; - -#if _HAS_CXX20 // because of stop_token - case 4: - if constexpr (is_same_v) { - stop_source source; - return cv.wait_until(main_lock, source.get_token(), timeout, [] { return false; }) == false; - } else { - assert(false); // test not supported for std::condition_variable - return false; - } - - case 5: - if constexpr (is_same_v) { - stop_source source; - return cv.wait_for(main_lock, source.get_token(), timeout_duration, [] { return false; }) == false; - } else { - assert(false); // test not supported for std::condition_variable - return false; - } -#endif // _HAS_CXX20 - - default: - assert(false); - return false; - } - }(); - - const auto elapsed = steady_clock::now() - wait_start; - - if (!cv_wait_timed_out) { - if (retries_remaining > 0) { - printf("unexpected wakeup after %lld ms, retry %d...\n", duration_cast(elapsed).count(), - retries_remaining); - test_timeout_immutable(test_number, retries_remaining - 1); // recurse to try the test again - } else { - puts("Too many unexpected wakeups"); - assert(false); - } - } else { - assert(elapsed < long_timeout / 2); - printf("wait end after %lld ms\n", duration_cast(elapsed).count()); - } - - // Make sure the child thread has indeed finished (so the next join does not block) - assert(timeout_duration == long_timeout); - other_thread.join(); - } } // unnamed namespace int main() { test_condition_variable_any(); test_condition_variable_any_already_timed_out(); - - puts("condition_variable"); - test_timeout_immutable(0); - test_timeout_immutable(1); - test_timeout_immutable(2); - test_timeout_immutable(3); - - puts("condition_variable_any"); - test_timeout_immutable(0); - test_timeout_immutable(1); - test_timeout_immutable(2); - test_timeout_immutable(3); -#if _HAS_CXX20 - test_timeout_immutable(4); - test_timeout_immutable(5); -#endif // _HAS_CXX20 }