diff --git a/test/cfoa/assign_tests.cpp b/test/cfoa/assign_tests.cpp index 92ba0bbf..e3f5b39f 100644 --- a/test/cfoa/assign_tests.cpp +++ b/test/cfoa/assign_tests.cpp @@ -677,7 +677,7 @@ namespace { test_matches_reference(x, reference_map); }); - BOOST_TEST_EQ(raii::destructor, 0); + BOOST_TEST_EQ(raii::destructor, 0u); BOOST_TEST_EQ(raii::copy_assignment, 0u); BOOST_TEST_EQ(raii::move_assignment, 0u); BOOST_TEST_EQ(raii::move_constructor, old_mc); @@ -738,6 +738,67 @@ namespace { } check_raii_counts(); } + + template void insert_and_assign(G gen, test::random_generator rg) + { + + std::thread t1, t2, t3; + + boost::latch start_latch(2), end_latch(2); + + auto v1 = make_random_values(1024 * 16, [&] { return gen(rg); }); + auto v2 = v1; + shuffle_values(v2); + + auto reference_map = + boost::unordered_flat_map(v1.begin(), v1.end()); + + raii::reset_counts(); + { + map_type map1(v1.size(), hasher(1), key_equal(2), allocator_type(3)); + map_type map2(v2.size(), hasher(1), key_equal(2), allocator_type(3)); + + t1 = std::thread([&v1, &map1, &start_latch, &end_latch] { + start_latch.arrive_and_wait(); + for (auto const& v : v1) { + map1.insert(v); + } + end_latch.arrive_and_wait(); + }); + + t2 = std::thread([&v2, &map2, &end_latch, &start_latch] { + start_latch.arrive_and_wait(); + for (auto const& v : v2) { + map2.insert(v); + } + end_latch.arrive_and_wait(); + }); + + std::atomic num_assignments{0}; + t3 = std::thread([&map1, &map2, &end_latch, &num_assignments] { + while (map1.empty() && map2.empty()) { + } + + while (!end_latch.try_wait()) { + map1 = map2; + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + map2 = map1; + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + ++num_assignments; + } + }); + + t1.join(); + t2.join(); + t3.join(); + + BOOST_TEST_GT(num_assignments, 0u); + + test_fuzzy_matches_reference(map1, reference_map, rg); + test_fuzzy_matches_reference(map2, reference_map, rg); + } + check_raii_counts(); + } } // namespace // clang-format off @@ -750,6 +811,11 @@ UNORDERED_TEST( move_assign, ((value_type_generator)) ((default_generator)(sequential)(limited_range))) + +UNORDERED_TEST( + insert_and_assign, + ((init_type_generator)) + ((default_generator)(sequential)(limited_range))) // clang-format on RUN_TESTS() diff --git a/test/cfoa/helpers.hpp b/test/cfoa/helpers.hpp index a9c27121..aa5a86a4 100644 --- a/test/cfoa/helpers.hpp +++ b/test/cfoa/helpers.hpp @@ -14,14 +14,16 @@ #include #include +#include #include #include #include #include #include +#include #include -#include #include +#include static std::size_t const num_threads = std::max(2u, std::thread::hardware_concurrency()); @@ -239,6 +241,8 @@ struct raii copy_assignment = 0; move_assignment = 0; } + + friend void swap(raii& lhs, raii& rhs) { std::swap(lhs.x_, rhs.x_); } }; std::atomic raii::default_constructor{0}; @@ -384,4 +388,12 @@ void check_raii_counts() raii::destructor); } +template void shuffle_values(std::vector v) +{ + std::random_device rd; + std::mt19937 g(rd()); + + std::shuffle(v.begin(), v.end(), g); +} + #endif // BOOST_UNORDERED_TEST_CFOA_HELPERS_HPP \ No newline at end of file