mirror of
https://github.com/boostorg/unordered.git
synced 2025-07-31 11:57:15 +02:00
Clean up tests to avoid needless yields and extraneous spurious wakeups
This commit is contained in:
@ -59,32 +59,48 @@ namespace {
|
|||||||
|
|
||||||
std::mutex m;
|
std::mutex m;
|
||||||
std::condition_variable cv;
|
std::condition_variable cv;
|
||||||
|
|
||||||
std::atomic<bool> done{false};
|
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) {
|
for (auto i = 0u; i < values.size(); ++i) {
|
||||||
x.insert(values[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();
|
cv.notify_all();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
done = true;
|
done = true;
|
||||||
|
{
|
||||||
|
std::unique_lock<std::mutex> lk(m);
|
||||||
|
ready = true;
|
||||||
|
}
|
||||||
|
cv.notify_all();
|
||||||
});
|
});
|
||||||
|
|
||||||
t2 = std::thread([&x, &m, &cv, &done] {
|
t2 = std::thread([&x, &m, &cv, &done, &ready, &num_clears] {
|
||||||
while (!done) {
|
do {
|
||||||
{
|
{
|
||||||
std::unique_lock<std::mutex> lk(m);
|
std::unique_lock<std::mutex> lk(m);
|
||||||
cv.wait(lk, [] { return true; });
|
cv.wait(lk, [&ready] { return ready; });
|
||||||
|
ready = false;
|
||||||
}
|
}
|
||||||
x.clear();
|
x.clear();
|
||||||
}
|
++num_clears;
|
||||||
|
} while (!done);
|
||||||
});
|
});
|
||||||
|
|
||||||
t1.join();
|
t1.join();
|
||||||
t2.join();
|
t2.join();
|
||||||
|
|
||||||
|
BOOST_TEST_GE(num_clears, 1u);
|
||||||
|
|
||||||
if (!x.empty()) {
|
if (!x.empty()) {
|
||||||
test_fuzzy_matches_reference(x, reference_map, rg);
|
test_fuzzy_matches_reference(x, reference_map, rg);
|
||||||
}
|
}
|
||||||
|
@ -35,7 +35,6 @@ struct transp_hash
|
|||||||
|
|
||||||
template <class T> std::size_t operator()(T const& t) const noexcept
|
template <class T> std::size_t operator()(T const& t) const noexcept
|
||||||
{
|
{
|
||||||
std::this_thread::yield();
|
|
||||||
return boost::hash<T>()(t);
|
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
|
template <class T, class U> bool operator()(T const& lhs, U const& rhs) const
|
||||||
{
|
{
|
||||||
std::this_thread::yield();
|
|
||||||
return lhs == rhs;
|
return lhs == rhs;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -70,7 +68,6 @@ struct stateful_hash
|
|||||||
{
|
{
|
||||||
std::size_t h = static_cast<std::size_t>(x_);
|
std::size_t h = static_cast<std::size_t>(x_);
|
||||||
boost::hash_combine(h, t);
|
boost::hash_combine(h, t);
|
||||||
std::this_thread::yield();
|
|
||||||
return h;
|
return h;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -107,7 +104,6 @@ struct stateful_key_equal
|
|||||||
|
|
||||||
template <class T, class U> bool operator()(T const& t, U const& u) const
|
template <class T, class U> bool operator()(T const& t, U const& u) const
|
||||||
{
|
{
|
||||||
std::this_thread::yield();
|
|
||||||
return t == u;
|
return t == u;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -196,39 +196,58 @@ namespace {
|
|||||||
std::condition_variable cv;
|
std::condition_variable cv;
|
||||||
std::atomic_bool done1{false}, done2{false};
|
std::atomic_bool done1{false}, done2{false};
|
||||||
std::atomic<unsigned> num_swaps{0};
|
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();
|
l.arrive_and_wait();
|
||||||
|
|
||||||
for (std::size_t idx = 0; idx < vals1.size(); ++idx) {
|
for (std::size_t idx = 0; idx < vals1.size(); ++idx) {
|
||||||
auto const& val = vals1[idx];
|
auto const& val = vals1[idx];
|
||||||
x1.insert(val);
|
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();
|
cv.notify_all();
|
||||||
}
|
}
|
||||||
std::this_thread::yield();
|
std::this_thread::yield();
|
||||||
}
|
}
|
||||||
|
|
||||||
done1 = true;
|
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();
|
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);
|
x2.insert(val);
|
||||||
std::this_thread::yield();
|
if (idx % 100 == 0) {
|
||||||
|
std::this_thread::yield();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
done2 = true;
|
done2 = true;
|
||||||
|
{
|
||||||
|
std::unique_lock<std::mutex> lk(m);
|
||||||
|
ready = true;
|
||||||
|
}
|
||||||
|
cv.notify_all();
|
||||||
});
|
});
|
||||||
|
|
||||||
t3 =
|
t3 = std::thread(
|
||||||
std::thread([&x1, &x2, &m, &cv, &done1, &done2, &num_swaps, swapper] {
|
[&x1, &x2, &m, &cv, &done1, &done2, &num_swaps, swapper, &ready] {
|
||||||
do {
|
do {
|
||||||
{
|
{
|
||||||
std::unique_lock<std::mutex> lk(m);
|
std::unique_lock<std::mutex> lk(m);
|
||||||
cv.wait(lk, [] { return true; });
|
cv.wait(lk, [&ready] { return ready; });
|
||||||
|
ready = false;
|
||||||
}
|
}
|
||||||
swapper(x1, x2);
|
swapper(x1, x2);
|
||||||
++num_swaps;
|
++num_swaps;
|
||||||
|
Reference in New Issue
Block a user