From c2c34f96a3a6cb19df91448c88bf5874fd65ae5a Mon Sep 17 00:00:00 2001 From: Christian Mazakas Date: Tue, 9 May 2023 13:33:50 -0700 Subject: [PATCH] Improve robustness of merge_tests to schedule merges without spurious wakeups and in a wider stride of insertions --- test/cfoa/merge_tests.cpp | 65 ++++++++++++++++++++++++++------------- 1 file changed, 44 insertions(+), 21 deletions(-) diff --git a/test/cfoa/merge_tests.cpp b/test/cfoa/merge_tests.cpp index 9b6bbb0e..2691c09d 100644 --- a/test/cfoa/merge_tests.cpp +++ b/test/cfoa/merge_tests.cpp @@ -106,26 +106,38 @@ namespace { std::condition_variable cv; std::atomic_bool done1{false}, done2{false}; std::atomic num_merges{0}; + std::atomic call_count{0}; + bool ready = false; auto const old_mc = +raii::move_constructor; BOOST_TEST_EQ(old_mc, 0u); - t1 = std::thread([&x1, &vals1, &l, &done1, &cv] { + t1 = std::thread([&x1, &vals1, &l, &done1, &cv, &ready, &m] { l.arrive_and_wait(); for (std::size_t idx = 0; idx < vals1.size(); ++idx) { auto const& val = vals1[idx]; x1.insert(val); - if (idx % 100 == 0) { + + if (idx % (vals1.size() / 128) == 0) { + { + std::unique_lock lk(m); + ready = true; + } cv.notify_all(); std::this_thread::yield(); } } done1 = true; + { + std::unique_lock lk(m); + ready = true; + } + cv.notify_all(); }); - t2 = std::thread([&x2, &vals2, &l, &done2] { + t2 = std::thread([&x2, &vals2, &l, &done2, &cv, &m, &ready] { l.arrive_and_wait(); for (std::size_t idx = 0; idx < vals2.size(); ++idx) { @@ -137,27 +149,37 @@ namespace { } done2 = true; - }); - - t3 = std::thread([&x1, &x2, &m, &cv, &done1, &done2, &num_merges] { - while (x1.empty() && x2.empty()) { + { + std::unique_lock lk(m); + ready = true; } - - do { - { - std::unique_lock lk(m); - cv.wait(lk, [] { return true; }); - } - num_merges += x1.merge(x2); - std::this_thread::yield(); - num_merges += x2.merge(x1); - - } while (!done1 || !done2); - - BOOST_TEST(done1); - BOOST_TEST(done2); + cv.notify_all(); }); + t3 = std::thread( + [&x1, &x2, &m, &cv, &done1, &done2, &num_merges, &call_count, &ready] { + while (x1.empty() && x2.empty()) { + } + + do { + { + std::unique_lock lk(m); + cv.wait(lk, [&ready] { return ready; }); + ready = false; + } + + num_merges += x1.merge(x2); + std::this_thread::yield(); + num_merges += x2.merge(x1); + + call_count += 1; + + } while (!done1 || !done2); + + BOOST_TEST(done1); + BOOST_TEST(done2); + }); + t1.join(); t2.join(); t3.join(); @@ -166,6 +188,7 @@ namespace { // num merges is 0 most commonly in the cast of the limited_range // generator as both maps will contains keys from 0 to 99 BOOST_TEST_EQ(+raii::move_constructor, 2 * num_merges); + BOOST_TEST_GE(call_count, 1u); } x1.merge(x2);