From c304284773227f70d1d0e8747aa9b18b01f82538 Mon Sep 17 00:00:00 2001 From: Christian Mazakas Date: Thu, 20 Apr 2023 12:57:00 -0700 Subject: [PATCH] Update tests to use condition variables for work synchronization instead of sleeps --- test/cfoa/constructor_tests.cpp | 45 +++++++++++++++++++++++++++------ test/cfoa/helpers.hpp | 21 +++++++++++++-- 2 files changed, 56 insertions(+), 10 deletions(-) diff --git a/test/cfoa/constructor_tests.cpp b/test/cfoa/constructor_tests.cpp index 86760863..457d27e3 100644 --- a/test/cfoa/constructor_tests.cpp +++ b/test/cfoa/constructor_tests.cpp @@ -297,11 +297,20 @@ namespace { boost::unordered_flat_map(values.begin(), values.end()); raii::reset_counts(); + std::mutex m; + std::condition_variable cv; + bool ready = false; + { map_type x(0, hasher(1), key_equal(2), allocator_type{}); - auto f = [&x, &values] { - std::this_thread::sleep_for(std::chrono::milliseconds(75)); + auto f = [&x, &values, &m, &cv, &ready] { + { + std::lock_guard guard(m); + ready = true; + } + cv.notify_all(); + for (auto const& val : values) { x.insert(val); } @@ -311,9 +320,15 @@ namespace { std::thread t2(f); thread_runner( - values, [&x, &reference_map, &values, rg]( + values, [&x, &reference_map, &values, rg, &m, &cv, &ready]( boost::span > s) { (void)s; + + { + std::unique_lock lk(m); + cv.wait(lk, [&] { return ready; }); + } + map_type y(x); BOOST_TEST_LE(y.size(), values.size()); @@ -483,12 +498,12 @@ namespace { BOOST_TEST_EQ(y.hash_function(), hasher(1)); BOOST_TEST_EQ(y.key_eq(), key_equal(2)); } else { - BOOST_TEST_EQ(y.size(), 0); + BOOST_TEST_EQ(y.size(), 0u); BOOST_TEST_EQ(y.hash_function(), hasher()); BOOST_TEST_EQ(y.key_eq(), key_equal()); } - BOOST_TEST_EQ(x.size(), 0); + BOOST_TEST_EQ(x.size(), 0u); BOOST_TEST_EQ(x.hash_function(), hasher()); BOOST_TEST_EQ(x.key_eq(), key_equal()); @@ -511,11 +526,20 @@ namespace { boost::unordered_flat_map(values.begin(), values.end()); raii::reset_counts(); + std::mutex m; + std::condition_variable cv; + bool ready = false; + { map_type x(0, hasher(1), key_equal(2), allocator_type{}); - auto f = [&x, &values] { - std::this_thread::sleep_for(std::chrono::milliseconds(25)); + auto f = [&x, &values, &m, &cv, &ready] { + { + std::lock_guard guard(m); + ready = true; + } + cv.notify_all(); + for (auto const& val : values) { x.insert(val); } @@ -527,10 +551,15 @@ namespace { std::thread t2(f); thread_runner( - values, [&x, &reference_map, &num_transfers, rg]( + values, [&x, &reference_map, &num_transfers, rg, &m, &ready, &cv]( boost::span > s) { (void)s; + { + std::unique_lock lk(m); + cv.wait(lk, [&] { return ready; }); + } + map_type y(std::move(x)); if (!y.empty()) { diff --git a/test/cfoa/helpers.hpp b/test/cfoa/helpers.hpp index 02f22d86..a830c032 100644 --- a/test/cfoa/helpers.hpp +++ b/test/cfoa/helpers.hpp @@ -9,8 +9,10 @@ #include #include +#include #include #include +#include #include #include @@ -272,16 +274,31 @@ std::vector > split( template void thread_runner(std::vector& values, F f) { + std::mutex m; + std::condition_variable cv; + bool ready = false; + std::vector threads; auto subslices = split(values, num_threads); for (std::size_t i = 0; i < num_threads; ++i) { - threads.emplace_back([&f, &subslices, i] { - std::this_thread::sleep_for(std::chrono::milliseconds(100)); + threads.emplace_back([&f, &subslices, i, &m, &cv, &ready] { + { + std::unique_lock lk(m); + cv.wait(lk, [&] { return ready; }); + } + auto s = subslices[i]; f(s); }); } + + { + std::lock_guard guard(m); + ready = true; + } + cv.notify_all(); + for (auto& t : threads) { t.join(); }