mirror of
https://github.com/boostorg/unordered.git
synced 2025-07-29 19:07:15 +02:00
Add visit_all()
This commit is contained in:
@ -185,9 +185,51 @@ namespace boost {
|
||||
|
||||
template <class F> std::size_t visit_all(F f)
|
||||
{
|
||||
BOOST_UNORDERED_STATIC_ASSERT_INVOCABLE(F)
|
||||
return table_.visit_all(f);
|
||||
}
|
||||
|
||||
template <class F> std::size_t visit_all(F f) const
|
||||
{
|
||||
BOOST_UNORDERED_STATIC_ASSERT_CONST_INVOCABLE(F)
|
||||
return table_.visit_all(f);
|
||||
}
|
||||
|
||||
template <class F> std::size_t cvisit_all(F f) const
|
||||
{
|
||||
BOOST_UNORDERED_STATIC_ASSERT_CONST_INVOCABLE(F)
|
||||
return table_.cvisit_all(f);
|
||||
}
|
||||
|
||||
#if defined(BOOST_UNORDERED_PARALLEL_ALGORITHMS)
|
||||
template <class ExecPolicy, class F>
|
||||
typename std::enable_if<detail::is_execution_policy<ExecPolicy>::value,
|
||||
void>::type
|
||||
visit_all(ExecPolicy p, F f)
|
||||
{
|
||||
BOOST_UNORDERED_STATIC_ASSERT_INVOCABLE(F)
|
||||
table_.visit_all(p, f);
|
||||
}
|
||||
|
||||
template <class ExecPolicy, class F>
|
||||
typename std::enable_if<detail::is_execution_policy<ExecPolicy>::value,
|
||||
void>::type
|
||||
visit_all(ExecPolicy p, F f) const
|
||||
{
|
||||
BOOST_UNORDERED_STATIC_ASSERT_CONST_INVOCABLE(F)
|
||||
table_.visit_all(p, f);
|
||||
}
|
||||
|
||||
template <class ExecPolicy, class F>
|
||||
typename std::enable_if<detail::is_execution_policy<ExecPolicy>::value,
|
||||
void>::type
|
||||
cvisit_all(ExecPolicy p, F f) const
|
||||
{
|
||||
BOOST_UNORDERED_STATIC_ASSERT_CONST_INVOCABLE(F)
|
||||
table_.cvisit_all(p, f);
|
||||
}
|
||||
#endif
|
||||
|
||||
/// Modifiers
|
||||
///
|
||||
|
||||
|
@ -16,32 +16,24 @@ namespace {
|
||||
|
||||
struct lvalue_visitor_type
|
||||
{
|
||||
template <class T, class X>
|
||||
void operator()(std::vector<T>& values, X& x, test::random_generator rg)
|
||||
template <class T, class X, class M>
|
||||
void operator()(std::vector<T>& values, X& x, M const& reference_map)
|
||||
{
|
||||
using value_type = typename X::value_type;
|
||||
|
||||
std::atomic<std::uint64_t> num_visits{0};
|
||||
std::atomic<std::uint64_t> total_count{0};
|
||||
|
||||
auto mut_visitor = [&num_visits, rg](int r, int r2) {
|
||||
return [&num_visits, r, r2, rg](value_type& v) {
|
||||
BOOST_TEST_EQ(v.first.x_, r);
|
||||
if (rg == test::sequential) {
|
||||
BOOST_TEST_EQ(v.second.x_, r2);
|
||||
}
|
||||
++num_visits;
|
||||
};
|
||||
auto mut_visitor = [&num_visits, &reference_map](value_type& v) {
|
||||
BOOST_TEST(reference_map.contains(v.first));
|
||||
BOOST_TEST_EQ(v.second, reference_map.find(v.first)->second);
|
||||
++num_visits;
|
||||
};
|
||||
|
||||
auto const_visitor = [&num_visits, rg](int r, int r2) {
|
||||
return [&num_visits, r, r2, rg](value_type const& v) {
|
||||
BOOST_TEST_EQ(v.first.x_, r);
|
||||
if (rg == test::sequential) {
|
||||
BOOST_TEST_EQ(v.second.x_, r2);
|
||||
}
|
||||
++num_visits;
|
||||
};
|
||||
auto const_visitor = [&num_visits, &reference_map](value_type const& v) {
|
||||
BOOST_TEST(reference_map.contains(v.first));
|
||||
BOOST_TEST_EQ(v.second, reference_map.find(v.first)->second);
|
||||
++num_visits;
|
||||
};
|
||||
|
||||
{
|
||||
@ -50,14 +42,12 @@ namespace {
|
||||
for (auto const& val : s) {
|
||||
auto r = val.first.x_;
|
||||
BOOST_ASSERT(r >= 0);
|
||||
auto r2 = val.second.x_;
|
||||
|
||||
auto count = x.visit(val.first, mut_visitor(r, r2));
|
||||
|
||||
auto count = x.visit(val.first, mut_visitor);
|
||||
BOOST_TEST_EQ(count, 1u);
|
||||
total_count += count;
|
||||
|
||||
count = x.visit(val.second, mut_visitor(r, r2));
|
||||
count = x.visit(val.second, mut_visitor);
|
||||
BOOST_TEST_EQ(count, 0u);
|
||||
}
|
||||
});
|
||||
@ -75,15 +65,14 @@ namespace {
|
||||
for (auto const& val : s) {
|
||||
auto r = val.first.x_;
|
||||
BOOST_ASSERT(r >= 0);
|
||||
auto r2 = val.second.x_;
|
||||
|
||||
auto const& y = x;
|
||||
auto count = y.visit(val.first, const_visitor(r, r2));
|
||||
auto count = y.visit(val.first, const_visitor);
|
||||
|
||||
BOOST_TEST_EQ(count, 1u);
|
||||
total_count += count;
|
||||
|
||||
count = y.visit(val.second, const_visitor(r, r2));
|
||||
count = y.visit(val.second, const_visitor);
|
||||
BOOST_TEST_EQ(count, 0u);
|
||||
}
|
||||
});
|
||||
@ -101,14 +90,13 @@ namespace {
|
||||
for (auto const& val : s) {
|
||||
auto r = val.first.x_;
|
||||
BOOST_ASSERT(r >= 0);
|
||||
auto r2 = val.second.x_;
|
||||
|
||||
auto count = x.cvisit(val.first, const_visitor(r, r2));
|
||||
auto count = x.cvisit(val.first, const_visitor);
|
||||
|
||||
BOOST_TEST_EQ(count, 1u);
|
||||
total_count += count;
|
||||
|
||||
count = x.cvisit(val.second, const_visitor(r, r2));
|
||||
count = x.cvisit(val.second, const_visitor);
|
||||
BOOST_TEST_EQ(count, 0u);
|
||||
}
|
||||
});
|
||||
@ -124,32 +112,24 @@ namespace {
|
||||
|
||||
struct transp_visitor_type
|
||||
{
|
||||
template <class T, class X>
|
||||
void operator()(std::vector<T>& values, X& x, test::random_generator rg)
|
||||
template <class T, class X, class M>
|
||||
void operator()(std::vector<T>& values, X& x, M const& reference_map)
|
||||
{
|
||||
using value_type = typename X::value_type;
|
||||
|
||||
std::atomic<std::uint64_t> num_visits{0};
|
||||
std::atomic<std::uint64_t> total_count{0};
|
||||
|
||||
auto mut_visitor = [&num_visits, rg](int r, int r2) {
|
||||
return [&num_visits, r, r2, rg](value_type& v) {
|
||||
BOOST_TEST_EQ(v.first.x_, r);
|
||||
if (rg == test::sequential) {
|
||||
BOOST_TEST_EQ(v.second.x_, r2);
|
||||
}
|
||||
++num_visits;
|
||||
};
|
||||
auto mut_visitor = [&num_visits, &reference_map](value_type& v) {
|
||||
BOOST_TEST(reference_map.contains(v.first));
|
||||
BOOST_TEST_EQ(v.second, reference_map.find(v.first)->second);
|
||||
++num_visits;
|
||||
};
|
||||
|
||||
auto const_visitor = [&num_visits, rg](int r, int r2) {
|
||||
return [&num_visits, r, r2, rg](value_type const& v) {
|
||||
BOOST_TEST_EQ(v.first.x_, r);
|
||||
if (rg == test::sequential) {
|
||||
BOOST_TEST_EQ(v.second.x_, r2);
|
||||
}
|
||||
++num_visits;
|
||||
};
|
||||
auto const_visitor = [&num_visits, &reference_map](value_type const& v) {
|
||||
BOOST_TEST(reference_map.contains(v.first));
|
||||
BOOST_TEST_EQ(v.second, reference_map.find(v.first)->second);
|
||||
++num_visits;
|
||||
};
|
||||
|
||||
{
|
||||
@ -158,14 +138,13 @@ namespace {
|
||||
for (auto const& val : s) {
|
||||
auto r = val.first.x_;
|
||||
BOOST_ASSERT(r >= 0);
|
||||
auto r2 = val.second.x_;
|
||||
|
||||
auto count = x.visit(val.first.x_, mut_visitor(r, r2));
|
||||
auto count = x.visit(val.first.x_, mut_visitor);
|
||||
|
||||
BOOST_TEST_EQ(count, 1u);
|
||||
total_count += count;
|
||||
|
||||
count = x.visit(val.second.x_, mut_visitor(r, r2));
|
||||
count = x.visit(val.second.x_, mut_visitor);
|
||||
BOOST_TEST_EQ(count, 0u);
|
||||
}
|
||||
});
|
||||
@ -183,15 +162,14 @@ namespace {
|
||||
for (auto const& val : s) {
|
||||
auto r = val.first.x_;
|
||||
BOOST_ASSERT(r >= 0);
|
||||
auto r2 = val.second.x_;
|
||||
|
||||
auto const& y = x;
|
||||
auto count = y.visit(val.first.x_, const_visitor(r, r2));
|
||||
auto count = y.visit(val.first.x_, const_visitor);
|
||||
|
||||
BOOST_TEST_EQ(count, 1u);
|
||||
total_count += count;
|
||||
|
||||
count = y.visit(val.second.x_, const_visitor(r, r2));
|
||||
count = y.visit(val.second.x_, const_visitor);
|
||||
BOOST_TEST_EQ(count, 0u);
|
||||
}
|
||||
});
|
||||
@ -209,14 +187,13 @@ namespace {
|
||||
for (auto const& val : s) {
|
||||
auto r = val.first.x_;
|
||||
BOOST_ASSERT(r >= 0);
|
||||
auto r2 = val.second.x_;
|
||||
|
||||
auto count = x.cvisit(val.first.x_, const_visitor(r, r2));
|
||||
auto count = x.cvisit(val.first.x_, const_visitor);
|
||||
|
||||
BOOST_TEST_EQ(count, 1u);
|
||||
total_count += count;
|
||||
|
||||
count = x.cvisit(val.second.x_, const_visitor(r, r2));
|
||||
count = x.cvisit(val.second.x_, const_visitor);
|
||||
BOOST_TEST_EQ(count, 0u);
|
||||
}
|
||||
});
|
||||
@ -230,6 +207,128 @@ namespace {
|
||||
}
|
||||
} transp_visitor;
|
||||
|
||||
struct visit_all_type
|
||||
{
|
||||
template <class T, class X, class M>
|
||||
void operator()(std::vector<T>& values, X& x, M const& reference_map)
|
||||
{
|
||||
using value_type = typename X::value_type;
|
||||
|
||||
std::atomic<std::uint64_t> total_count{0};
|
||||
|
||||
auto mut_visitor = [&reference_map](std::atomic<uint64_t>& num_visits) {
|
||||
return [&reference_map, &num_visits](value_type& kv) {
|
||||
BOOST_TEST(reference_map.contains(kv.first));
|
||||
BOOST_TEST_EQ(kv.second, reference_map.find(kv.first)->second);
|
||||
++num_visits;
|
||||
};
|
||||
};
|
||||
|
||||
auto const_visitor = [&reference_map](std::atomic<uint64_t>& num_visits) {
|
||||
return [&reference_map, &num_visits](value_type const& kv) {
|
||||
BOOST_TEST(reference_map.contains(kv.first));
|
||||
BOOST_TEST_EQ(kv.second, reference_map.find(kv.first)->second);
|
||||
++num_visits;
|
||||
};
|
||||
};
|
||||
|
||||
{
|
||||
thread_runner(values, [&x, &total_count, &mut_visitor](boost::span<T>) {
|
||||
std::atomic<std::uint64_t> num_visits{0};
|
||||
total_count += x.visit_all(mut_visitor(num_visits));
|
||||
BOOST_TEST_EQ(x.size(), num_visits);
|
||||
});
|
||||
|
||||
BOOST_TEST_EQ(total_count, num_threads * x.size());
|
||||
total_count = 0;
|
||||
}
|
||||
|
||||
{
|
||||
thread_runner(
|
||||
values, [&x, &total_count, &const_visitor](boost::span<T>) {
|
||||
std::atomic<std::uint64_t> num_visits{0};
|
||||
auto const& y = x;
|
||||
total_count += y.visit_all(const_visitor(num_visits));
|
||||
BOOST_TEST_EQ(x.size(), num_visits);
|
||||
});
|
||||
|
||||
BOOST_TEST_EQ(total_count, num_threads * x.size());
|
||||
total_count = 0;
|
||||
}
|
||||
|
||||
{
|
||||
thread_runner(
|
||||
values, [&x, &total_count, &const_visitor](boost::span<T>) {
|
||||
std::atomic<std::uint64_t> num_visits{0};
|
||||
total_count += x.cvisit_all(const_visitor(num_visits));
|
||||
BOOST_TEST_EQ(x.size(), num_visits);
|
||||
});
|
||||
|
||||
BOOST_TEST_EQ(total_count, num_threads * x.size());
|
||||
total_count = 0;
|
||||
}
|
||||
}
|
||||
|
||||
} visit_all;
|
||||
|
||||
struct exec_policy_visit_all_type
|
||||
{
|
||||
template <class T, class X, class M>
|
||||
void operator()(std::vector<T>& values, X& x, M const& reference_map)
|
||||
{
|
||||
#if defined(BOOST_UNORDERED_PARALLEL_ALGORITHMS)
|
||||
using value_type = typename X::value_type;
|
||||
|
||||
auto mut_visitor = [&reference_map](std::atomic<uint64_t>& num_visits) {
|
||||
return [&reference_map, &num_visits](value_type& kv) {
|
||||
BOOST_TEST(reference_map.contains(kv.first));
|
||||
BOOST_TEST_EQ(kv.second, reference_map.find(kv.first)->second);
|
||||
++num_visits;
|
||||
};
|
||||
};
|
||||
|
||||
auto const_visitor = [&reference_map](std::atomic<uint64_t>& num_visits) {
|
||||
return [&reference_map, &num_visits](value_type const& kv) {
|
||||
BOOST_TEST(reference_map.contains(kv.first));
|
||||
BOOST_TEST_EQ(kv.second, reference_map.find(kv.first)->second);
|
||||
++num_visits;
|
||||
};
|
||||
};
|
||||
|
||||
{
|
||||
thread_runner(values, [&x, &mut_visitor](boost::span<T>) {
|
||||
std::atomic<std::uint64_t> num_visits{0};
|
||||
|
||||
x.visit_all(std::execution::par_unseq, mut_visitor(num_visits));
|
||||
BOOST_TEST_EQ(x.size(), num_visits);
|
||||
});
|
||||
}
|
||||
|
||||
{
|
||||
thread_runner(values, [&x, &const_visitor](boost::span<T>) {
|
||||
std::atomic<std::uint64_t> num_visits{0};
|
||||
auto const& y = x;
|
||||
|
||||
y.visit_all(std::execution::par_unseq, const_visitor(num_visits));
|
||||
BOOST_TEST_EQ(x.size(), num_visits);
|
||||
});
|
||||
}
|
||||
|
||||
{
|
||||
thread_runner(values, [&x, &const_visitor](boost::span<T>) {
|
||||
std::atomic<std::uint64_t> num_visits{0};
|
||||
x.cvisit_all(std::execution::par_unseq, const_visitor(num_visits));
|
||||
BOOST_TEST_EQ(x.size(), num_visits);
|
||||
});
|
||||
}
|
||||
#else
|
||||
(void)values;
|
||||
(void)x;
|
||||
(void)reference_map;
|
||||
#endif
|
||||
}
|
||||
} exec_policy_visit_all;
|
||||
|
||||
template <class X, class G, class F>
|
||||
void visit(X*, G gen, F visitor, test::random_generator rg)
|
||||
{
|
||||
@ -258,7 +357,7 @@ namespace {
|
||||
std::uint64_t old_copy_assignment = raii::copy_assignment;
|
||||
std::uint64_t old_move_assignment = raii::move_assignment;
|
||||
|
||||
visitor(values, x, rg);
|
||||
visitor(values, x, reference_map);
|
||||
|
||||
BOOST_TEST_EQ(old_default_constructor, raii::default_constructor);
|
||||
BOOST_TEST_EQ(old_copy_constructor, raii::copy_constructor);
|
||||
@ -293,7 +392,7 @@ UNORDERED_TEST(
|
||||
visit,
|
||||
((map))
|
||||
((value_type_generator)(init_type_generator))
|
||||
((lvalue_visitor))
|
||||
((lvalue_visitor)(visit_all)(exec_policy_visit_all))
|
||||
((default_generator)(sequential)(limited_range)))
|
||||
|
||||
UNORDERED_TEST(
|
||||
|
Reference in New Issue
Block a user