1// Copyright (C) 2023 Christian Mazakas
2// Copyright (C) 2023 Joaquin M Lopez Munoz
3// Distributed under the Boost Software License, Version 1.0. (See accompanying
4// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
5
6#include "helpers.hpp"
7
8#include <boost/unordered/concurrent_flat_map.hpp>
9#include <boost/unordered/concurrent_flat_set.hpp>
10
11test::seed_t initialize_seed{674140082};
12
13using test::default_generator;
14using test::limited_range;
15using test::sequential;
16
17using hasher = stateful_hash;
18using key_equal = stateful_key_equal;
19
20using map_type = boost::unordered::concurrent_flat_map<raii, raii, hasher,
21 key_equal, stateful_allocator<std::pair<raii const, raii> > >;
22
23using set_type = boost::unordered::concurrent_flat_set<raii, hasher,
24 key_equal, stateful_allocator<raii> >;
25
26map_type* test_map;
27set_type* test_set;
28
29namespace {
30 template <class X, class GF>
31 void clear_tests(X*, GF gen_factory, test::random_generator rg)
32 {
33 using value_type = typename X::value_type;
34 static constexpr auto value_type_cardinality =
35 value_cardinality<value_type>::value;
36 using allocator_type = typename X::allocator_type;
37
38 auto gen = gen_factory.template get<X>();
39 auto values = make_random_values(1024 * 16, [&] { return gen(rg); });
40
41 raii::reset_counts();
42
43 X x(values.begin(), values.end(), values.size(), hasher(1),
44 key_equal(2), allocator_type(3));
45
46 auto const old_size = x.size();
47 auto const old_d = +raii::destructor;
48
49 thread_runner(values, [&x](boost::span<value_type> s) {
50 (void)s;
51 x.clear();
52 });
53
54 BOOST_TEST(x.empty());
55 BOOST_TEST_EQ(raii::destructor, old_d + value_type_cardinality * old_size);
56
57 check_raii_counts();
58 }
59
60 template <class X, class GF>
61 void insert_and_clear(X*, GF gen_factory, test::random_generator rg)
62 {
63 using allocator_type = typename X::allocator_type;
64
65 auto gen = gen_factory.template get<X>();
66 auto values = make_random_values(1024 * 16, [&] { return gen(rg); });
67 auto reference_cont = reference_container<X>(values.begin(), values.end());
68
69 raii::reset_counts();
70
71 std::thread t1, t2;
72
73 {
74 X x(0, hasher(1), key_equal(2), allocator_type(3));
75
76 std::mutex m;
77 std::condition_variable cv;
78 std::atomic<bool> done{false};
79 std::atomic<unsigned> num_clears{0};
80
81 bool ready = false;
82
83 t1 = std::thread([&x, &values, &cv, &done, &m, &ready] {
84 for (auto i = 0u; i < values.size(); ++i) {
85 x.insert(values[i]);
86 if (i % (values.size() / 128) == 0) {
87 {
88 std::unique_lock<std::mutex> lk(m);
89 ready = true;
90 }
91 cv.notify_all();
92 }
93 }
94
95 done = true;
96 {
97 std::unique_lock<std::mutex> lk(m);
98 ready = true;
99 }
100 cv.notify_all();
101 });
102
103 t2 = std::thread([&x, &m, &cv, &done, &ready, &num_clears] {
104 do {
105 {
106 std::unique_lock<std::mutex> lk(m);
107 cv.wait(lk, [&ready] { return ready; });
108 ready = false;
109 }
110 x.clear();
111 ++num_clears;
112 } while (!done);
113 });
114
115 t1.join();
116 t2.join();
117
118 BOOST_TEST_GE(num_clears, 1u);
119
120 if (!x.empty()) {
121 test_fuzzy_matches_reference(x, reference_cont, rg);
122 }
123 }
124
125 check_raii_counts();
126 }
127
128} // namespace
129
130// clang-format off
131UNORDERED_TEST(
132 clear_tests,
133 ((test_map)(test_set))
134 ((value_type_generator_factory))
135 ((default_generator)(sequential)(limited_range)))
136
137UNORDERED_TEST(insert_and_clear,
138 ((test_map)(test_set))
139 ((value_type_generator_factory))
140 ((default_generator)(sequential)(limited_range)))
141// clang-format on
142
143RUN_TESTS()
144

source code of boost/libs/unordered/test/cfoa/clear_tests.cpp