mirror of
https://github.com/boostorg/unordered.git
synced 2025-07-30 03:17:15 +02:00
Add policy check that excludes unsequenced policies
It's technically UB for the callable in an unsequenced policy to acquire a lock so we add static_assert()s to catch potential user error.
This commit is contained in:
@ -37,6 +37,14 @@
|
|||||||
boost::unordered::detail::is_invocable<F, value_type const&>::value, \
|
boost::unordered::detail::is_invocable<F, value_type const&>::value, \
|
||||||
"The provided Callable must be invocable with `value_type const&`");
|
"The provided Callable must be invocable with `value_type const&`");
|
||||||
|
|
||||||
|
#define BOOST_UNORDERED_STATIC_ASSERT_EXEC_POLICY(P) \
|
||||||
|
static_assert(!std::is_base_of<std::execution::parallel_unsequenced_policy, \
|
||||||
|
ExecPolicy>::value, \
|
||||||
|
"ExecPolicy must be sequenced."); \
|
||||||
|
static_assert( \
|
||||||
|
!std::is_base_of<std::execution::unsequenced_policy, ExecPolicy>::value, \
|
||||||
|
"ExecPolicy must be sequenced.");
|
||||||
|
|
||||||
#define BOOST_UNORDERED_COMMA ,
|
#define BOOST_UNORDERED_COMMA ,
|
||||||
|
|
||||||
#define BOOST_UNORDERED_LAST_ARG(Arg, Args) \
|
#define BOOST_UNORDERED_LAST_ARG(Arg, Args) \
|
||||||
@ -357,6 +365,7 @@ namespace boost {
|
|||||||
visit_all(ExecPolicy p, F f)
|
visit_all(ExecPolicy p, F f)
|
||||||
{
|
{
|
||||||
BOOST_UNORDERED_STATIC_ASSERT_INVOCABLE(F)
|
BOOST_UNORDERED_STATIC_ASSERT_INVOCABLE(F)
|
||||||
|
BOOST_UNORDERED_STATIC_ASSERT_EXEC_POLICY(ExecPolicy)
|
||||||
table_.visit_all(p, f);
|
table_.visit_all(p, f);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -367,6 +376,7 @@ namespace boost {
|
|||||||
visit_all(ExecPolicy p, F f) const
|
visit_all(ExecPolicy p, F f) const
|
||||||
{
|
{
|
||||||
BOOST_UNORDERED_STATIC_ASSERT_CONST_INVOCABLE(F)
|
BOOST_UNORDERED_STATIC_ASSERT_CONST_INVOCABLE(F)
|
||||||
|
BOOST_UNORDERED_STATIC_ASSERT_EXEC_POLICY(ExecPolicy)
|
||||||
table_.visit_all(p, f);
|
table_.visit_all(p, f);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -377,6 +387,7 @@ namespace boost {
|
|||||||
cvisit_all(ExecPolicy p, F f) const
|
cvisit_all(ExecPolicy p, F f) const
|
||||||
{
|
{
|
||||||
BOOST_UNORDERED_STATIC_ASSERT_CONST_INVOCABLE(F)
|
BOOST_UNORDERED_STATIC_ASSERT_CONST_INVOCABLE(F)
|
||||||
|
BOOST_UNORDERED_STATIC_ASSERT_EXEC_POLICY(ExecPolicy)
|
||||||
table_.cvisit_all(p, f);
|
table_.cvisit_all(p, f);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -663,6 +674,8 @@ namespace boost {
|
|||||||
void>::type
|
void>::type
|
||||||
erase_if(ExecPolicy p, F f)
|
erase_if(ExecPolicy p, F f)
|
||||||
{
|
{
|
||||||
|
BOOST_UNORDERED_STATIC_ASSERT_EXEC_POLICY(ExecPolicy)
|
||||||
|
BOOST_UNORDERED_STATIC_ASSERT_EXEC_POLICY(ExecPolicy)
|
||||||
table_.erase_if(p, f);
|
table_.erase_if(p, f);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -281,7 +281,7 @@ namespace {
|
|||||||
thread_runner(values, [&num_invokes, &x, threshold](boost::span<T> s) {
|
thread_runner(values, [&num_invokes, &x, threshold](boost::span<T> s) {
|
||||||
(void)s;
|
(void)s;
|
||||||
x.erase_if(
|
x.erase_if(
|
||||||
std::execution::par_unseq, [&num_invokes, threshold](value_type& v) {
|
std::execution::par, [&num_invokes, threshold](value_type& v) {
|
||||||
++num_invokes;
|
++num_invokes;
|
||||||
return v.second.x_ > threshold;
|
return v.second.x_ > threshold;
|
||||||
});
|
});
|
||||||
|
@ -299,7 +299,7 @@ namespace {
|
|||||||
thread_runner(values, [&x, &mut_visitor](boost::span<T>) {
|
thread_runner(values, [&x, &mut_visitor](boost::span<T>) {
|
||||||
std::atomic<std::uint64_t> num_visits{0};
|
std::atomic<std::uint64_t> num_visits{0};
|
||||||
|
|
||||||
x.visit_all(std::execution::par_unseq, mut_visitor(num_visits));
|
x.visit_all(std::execution::par, mut_visitor(num_visits));
|
||||||
BOOST_TEST_EQ(x.size(), num_visits);
|
BOOST_TEST_EQ(x.size(), num_visits);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -309,7 +309,7 @@ namespace {
|
|||||||
std::atomic<std::uint64_t> num_visits{0};
|
std::atomic<std::uint64_t> num_visits{0};
|
||||||
auto const& y = x;
|
auto const& y = x;
|
||||||
|
|
||||||
y.visit_all(std::execution::par_unseq, const_visitor(num_visits));
|
y.visit_all(std::execution::par, const_visitor(num_visits));
|
||||||
BOOST_TEST_EQ(x.size(), num_visits);
|
BOOST_TEST_EQ(x.size(), num_visits);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -317,7 +317,7 @@ namespace {
|
|||||||
{
|
{
|
||||||
thread_runner(values, [&x, &const_visitor](boost::span<T>) {
|
thread_runner(values, [&x, &const_visitor](boost::span<T>) {
|
||||||
std::atomic<std::uint64_t> num_visits{0};
|
std::atomic<std::uint64_t> num_visits{0};
|
||||||
x.cvisit_all(std::execution::par_unseq, const_visitor(num_visits));
|
x.cvisit_all(std::execution::par, const_visitor(num_visits));
|
||||||
BOOST_TEST_EQ(x.size(), num_visits);
|
BOOST_TEST_EQ(x.size(), num_visits);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user