Clean up tests to avoid needless yields and extraneous spurious wakeups

This commit is contained in:
Christian Mazakas
2023-05-16 09:19:43 -07:00
parent 6295c7f0d4
commit 63026fd320
3 changed files with 50 additions and 19 deletions

View File

@ -59,32 +59,48 @@ namespace {
std::mutex m;
std::condition_variable cv;
std::atomic<bool> done{false};
std::atomic<unsigned> num_clears{0};
t1 = std::thread([&x, &values, &cv, &done] {
bool ready = false;
t1 = std::thread([&x, &values, &cv, &done, &m, &ready] {
for (auto i = 0u; i < values.size(); ++i) {
x.insert(values[i]);
if (i % 100 == 0) {
if (i % (values.size() / 128) == 0) {
{
std::unique_lock<std::mutex> lk(m);
ready = true;
}
cv.notify_all();
}
}
done = true;
{
std::unique_lock<std::mutex> lk(m);
ready = true;
}
cv.notify_all();
});
t2 = std::thread([&x, &m, &cv, &done] {
while (!done) {
t2 = std::thread([&x, &m, &cv, &done, &ready, &num_clears] {
do {
{
std::unique_lock<std::mutex> lk(m);
cv.wait(lk, [] { return true; });
cv.wait(lk, [&ready] { return ready; });
ready = false;
}
x.clear();
}
++num_clears;
} while (!done);
});
t1.join();
t2.join();
BOOST_TEST_GE(num_clears, 1u);
if (!x.empty()) {
test_fuzzy_matches_reference(x, reference_map, rg);
}

View File

@ -35,7 +35,6 @@ struct transp_hash
template <class T> std::size_t operator()(T const& t) const noexcept
{
std::this_thread::yield();
return boost::hash<T>()(t);
}
};
@ -46,7 +45,6 @@ struct transp_key_equal
template <class T, class U> bool operator()(T const& lhs, U const& rhs) const
{
std::this_thread::yield();
return lhs == rhs;
}
};
@ -70,7 +68,6 @@ struct stateful_hash
{
std::size_t h = static_cast<std::size_t>(x_);
boost::hash_combine(h, t);
std::this_thread::yield();
return h;
}
@ -107,7 +104,6 @@ struct stateful_key_equal
template <class T, class U> bool operator()(T const& t, U const& u) const
{
std::this_thread::yield();
return t == u;
}

View File

@ -196,39 +196,58 @@ namespace {
std::condition_variable cv;
std::atomic_bool done1{false}, done2{false};
std::atomic<unsigned> num_swaps{0};
bool ready = false;
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<std::mutex> lk(m);
ready = true;
}
cv.notify_all();
}
std::this_thread::yield();
}
done1 = true;
{
std::unique_lock<std::mutex> lk(m);
ready = true;
}
cv.notify_all();
});
t2 = std::thread([&x2, &vals2, &l, &done2] {
t2 = std::thread([&x2, &vals2, &l, &done2, &ready, &cv, &m] {
l.arrive_and_wait();
for (auto const& val : vals2) {
for (std::size_t idx = 0; idx < vals2.size(); ++idx) {
auto const& val = vals2[idx];
x2.insert(val);
std::this_thread::yield();
if (idx % 100 == 0) {
std::this_thread::yield();
}
}
done2 = true;
{
std::unique_lock<std::mutex> lk(m);
ready = true;
}
cv.notify_all();
});
t3 =
std::thread([&x1, &x2, &m, &cv, &done1, &done2, &num_swaps, swapper] {
t3 = std::thread(
[&x1, &x2, &m, &cv, &done1, &done2, &num_swaps, swapper, &ready] {
do {
{
std::unique_lock<std::mutex> lk(m);
cv.wait(lk, [] { return true; });
cv.wait(lk, [&ready] { return ready; });
ready = false;
}
swapper(x1, x2);
++num_swaps;