forked from boostorg/unordered
added insert_and_visit and similar operations to concurrent containers (#283)
This commit is contained in:
@@ -517,6 +517,80 @@ namespace boost {
|
||||
this->insert_or_cvisit(ilist.begin(), ilist.end(), f);
|
||||
}
|
||||
|
||||
template <class Ty, class F1, class F2>
|
||||
BOOST_FORCEINLINE auto insert_and_visit(Ty&& value, F1 f1, F2 f2)
|
||||
-> decltype(table_.insert_and_visit(std::forward<Ty>(value), f1, f2))
|
||||
{
|
||||
BOOST_UNORDERED_STATIC_ASSERT_INVOCABLE(F1)
|
||||
BOOST_UNORDERED_STATIC_ASSERT_INVOCABLE(F2)
|
||||
return table_.insert_and_visit(std::forward<Ty>(value), f1, f2);
|
||||
}
|
||||
|
||||
template <class F1, class F2>
|
||||
BOOST_FORCEINLINE bool insert_and_visit(init_type&& obj, F1 f1, F2 f2)
|
||||
{
|
||||
BOOST_UNORDERED_STATIC_ASSERT_INVOCABLE(F1)
|
||||
BOOST_UNORDERED_STATIC_ASSERT_INVOCABLE(F2)
|
||||
return table_.insert_and_visit(std::move(obj), f1, f2);
|
||||
}
|
||||
|
||||
template <class InputIterator, class F1, class F2>
|
||||
void insert_and_visit(
|
||||
InputIterator first, InputIterator last, F1 f1, F2 f2)
|
||||
{
|
||||
BOOST_UNORDERED_STATIC_ASSERT_INVOCABLE(F1)
|
||||
BOOST_UNORDERED_STATIC_ASSERT_INVOCABLE(F2)
|
||||
for (; first != last; ++first) {
|
||||
table_.emplace_and_visit(*first, f1, f2);
|
||||
}
|
||||
}
|
||||
|
||||
template <class F1, class F2>
|
||||
void insert_and_visit(
|
||||
std::initializer_list<value_type> ilist, F1 f1, F2 f2)
|
||||
{
|
||||
BOOST_UNORDERED_STATIC_ASSERT_INVOCABLE(F1)
|
||||
BOOST_UNORDERED_STATIC_ASSERT_INVOCABLE(F2)
|
||||
this->insert_and_visit(ilist.begin(), ilist.end(), f1, f2);
|
||||
}
|
||||
|
||||
template <class Ty, class F1, class F2>
|
||||
BOOST_FORCEINLINE auto insert_and_cvisit(Ty&& value, F1 f1, F2 f2)
|
||||
-> decltype(table_.insert_and_cvisit(std::forward<Ty>(value), f1, f2))
|
||||
{
|
||||
BOOST_UNORDERED_STATIC_ASSERT_INVOCABLE(F1)
|
||||
BOOST_UNORDERED_STATIC_ASSERT_CONST_INVOCABLE(F2)
|
||||
return table_.insert_and_cvisit(std::forward<Ty>(value), f1, f2);
|
||||
}
|
||||
|
||||
template <class F1, class F2>
|
||||
BOOST_FORCEINLINE bool insert_and_cvisit(init_type&& obj, F1 f1, F2 f2)
|
||||
{
|
||||
BOOST_UNORDERED_STATIC_ASSERT_INVOCABLE(F1)
|
||||
BOOST_UNORDERED_STATIC_ASSERT_CONST_INVOCABLE(F2)
|
||||
return table_.insert_and_cvisit(std::move(obj), f1, f2);
|
||||
}
|
||||
|
||||
template <class InputIterator, class F1, class F2>
|
||||
void insert_and_cvisit(
|
||||
InputIterator first, InputIterator last, F1 f1, F2 f2)
|
||||
{
|
||||
BOOST_UNORDERED_STATIC_ASSERT_INVOCABLE(F1)
|
||||
BOOST_UNORDERED_STATIC_ASSERT_CONST_INVOCABLE(F2)
|
||||
for (; first != last; ++first) {
|
||||
table_.emplace_and_cvisit(*first, f1, f2);
|
||||
}
|
||||
}
|
||||
|
||||
template <class F1, class F2>
|
||||
void insert_and_cvisit(
|
||||
std::initializer_list<value_type> ilist, F1 f1, F2 f2)
|
||||
{
|
||||
BOOST_UNORDERED_STATIC_ASSERT_INVOCABLE(F1)
|
||||
BOOST_UNORDERED_STATIC_ASSERT_CONST_INVOCABLE(F2)
|
||||
this->insert_and_cvisit(ilist.begin(), ilist.end(), f1, f2);
|
||||
}
|
||||
|
||||
template <class... Args> BOOST_FORCEINLINE bool emplace(Args&&... args)
|
||||
{
|
||||
return table_.emplace(std::forward<Args>(args)...);
|
||||
@@ -538,6 +612,30 @@ namespace boost {
|
||||
std::forward<Arg>(arg), std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template <class Arg1, class Arg2, class... Args>
|
||||
BOOST_FORCEINLINE bool emplace_and_visit(
|
||||
Arg1&& arg1, Arg2&& arg2, Args&&... args)
|
||||
{
|
||||
BOOST_UNORDERED_STATIC_ASSERT_PENULTIMATE_ARG_INVOCABLE(
|
||||
Arg1, Arg2, Args...)
|
||||
BOOST_UNORDERED_STATIC_ASSERT_LAST_ARG_INVOCABLE(Arg2, Args...)
|
||||
return table_.emplace_and_visit(
|
||||
std::forward<Arg1>(arg1), std::forward<Arg2>(arg2),
|
||||
std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template <class Arg1, class Arg2, class... Args>
|
||||
BOOST_FORCEINLINE bool emplace_and_cvisit(
|
||||
Arg1&& arg1, Arg2&& arg2, Args&&... args)
|
||||
{
|
||||
BOOST_UNORDERED_STATIC_ASSERT_PENULTIMATE_ARG_INVOCABLE(
|
||||
Arg1, Arg2, Args...)
|
||||
BOOST_UNORDERED_STATIC_ASSERT_LAST_ARG_CONST_INVOCABLE(Arg2, Args...)
|
||||
return table_.emplace_and_cvisit(
|
||||
std::forward<Arg1>(arg1), std::forward<Arg2>(arg2),
|
||||
std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template <class... Args>
|
||||
BOOST_FORCEINLINE bool try_emplace(key_type const& k, Args&&... args)
|
||||
{
|
||||
@@ -613,6 +711,78 @@ namespace boost {
|
||||
std::forward<Arg>(arg), std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template <class Arg1, class Arg2, class... Args>
|
||||
BOOST_FORCEINLINE bool try_emplace_and_visit(
|
||||
key_type const& k, Arg1&& arg1, Arg2&& arg2, Args&&... args)
|
||||
{
|
||||
BOOST_UNORDERED_STATIC_ASSERT_PENULTIMATE_ARG_INVOCABLE(
|
||||
Arg1, Arg2, Args...)
|
||||
BOOST_UNORDERED_STATIC_ASSERT_LAST_ARG_INVOCABLE(Arg2, Args...)
|
||||
return table_.try_emplace_and_visit(
|
||||
k, std::forward<Arg1>(arg1), std::forward<Arg2>(arg2),
|
||||
std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template <class Arg1, class Arg2, class... Args>
|
||||
BOOST_FORCEINLINE bool try_emplace_and_cvisit(
|
||||
key_type const& k, Arg1&& arg1, Arg2&& arg2, Args&&... args)
|
||||
{
|
||||
BOOST_UNORDERED_STATIC_ASSERT_PENULTIMATE_ARG_INVOCABLE(
|
||||
Arg1, Arg2, Args...)
|
||||
BOOST_UNORDERED_STATIC_ASSERT_LAST_ARG_CONST_INVOCABLE(Arg2, Args...)
|
||||
return table_.try_emplace_and_cvisit(
|
||||
k, std::forward<Arg1>(arg1), std::forward<Arg2>(arg2),
|
||||
std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template <class Arg1, class Arg2, class... Args>
|
||||
BOOST_FORCEINLINE bool try_emplace_and_visit(
|
||||
key_type&& k, Arg1&& arg1, Arg2&& arg2, Args&&... args)
|
||||
{
|
||||
BOOST_UNORDERED_STATIC_ASSERT_PENULTIMATE_ARG_INVOCABLE(
|
||||
Arg1, Arg2, Args...)
|
||||
BOOST_UNORDERED_STATIC_ASSERT_LAST_ARG_INVOCABLE(Arg2, Args...)
|
||||
return table_.try_emplace_and_visit(
|
||||
std::move(k), std::forward<Arg1>(arg1), std::forward<Arg2>(arg2),
|
||||
std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template <class Arg1, class Arg2, class... Args>
|
||||
BOOST_FORCEINLINE bool try_emplace_and_cvisit(
|
||||
key_type&& k, Arg1&& arg1, Arg2&& arg2, Args&&... args)
|
||||
{
|
||||
BOOST_UNORDERED_STATIC_ASSERT_PENULTIMATE_ARG_INVOCABLE(
|
||||
Arg1, Arg2, Args...)
|
||||
BOOST_UNORDERED_STATIC_ASSERT_LAST_ARG_CONST_INVOCABLE(Arg2, Args...)
|
||||
return table_.try_emplace_and_cvisit(
|
||||
std::move(k), std::forward<Arg1>(arg1), std::forward<Arg2>(arg2),
|
||||
std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template <class K, class Arg1, class Arg2, class... Args>
|
||||
BOOST_FORCEINLINE bool try_emplace_and_visit(
|
||||
K&& k, Arg1&& arg1, Arg2&& arg2, Args&&... args)
|
||||
{
|
||||
BOOST_UNORDERED_STATIC_ASSERT_PENULTIMATE_ARG_INVOCABLE(
|
||||
Arg1, Arg2, Args...)
|
||||
BOOST_UNORDERED_STATIC_ASSERT_LAST_ARG_INVOCABLE(Arg2, Args...)
|
||||
return table_.try_emplace_and_visit(std::forward<K>(k),
|
||||
std::forward<Arg1>(arg1), std::forward<Arg2>(arg2),
|
||||
std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template <class K, class Arg1, class Arg2, class... Args>
|
||||
BOOST_FORCEINLINE bool try_emplace_and_cvisit(
|
||||
K&& k, Arg1&& arg1, Arg2&& arg2, Args&&... args)
|
||||
{
|
||||
BOOST_UNORDERED_STATIC_ASSERT_PENULTIMATE_ARG_INVOCABLE(
|
||||
Arg1, Arg2, Args...)
|
||||
BOOST_UNORDERED_STATIC_ASSERT_LAST_ARG_CONST_INVOCABLE(Arg2, Args...)
|
||||
return table_.try_emplace_and_cvisit(std::forward<K>(k),
|
||||
std::forward<Arg1>(arg1), std::forward<Arg2>(arg2),
|
||||
std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
BOOST_FORCEINLINE size_type erase(key_type const& k)
|
||||
{
|
||||
return table_.erase(k);
|
||||
|
||||
@@ -517,6 +517,101 @@ namespace boost {
|
||||
this->insert_or_cvisit(ilist.begin(), ilist.end(), f);
|
||||
}
|
||||
|
||||
template <class F1, class F2>
|
||||
BOOST_FORCEINLINE bool insert_and_visit(
|
||||
value_type const& obj, F1 f1, F2 f2)
|
||||
{
|
||||
BOOST_UNORDERED_STATIC_ASSERT_CONST_INVOCABLE(F1)
|
||||
BOOST_UNORDERED_STATIC_ASSERT_CONST_INVOCABLE(F2)
|
||||
return table_.insert_and_visit(obj, f1, f2);
|
||||
}
|
||||
|
||||
template <class F1, class F2>
|
||||
BOOST_FORCEINLINE bool insert_and_visit(value_type&& obj, F1 f1, F2 f2)
|
||||
{
|
||||
BOOST_UNORDERED_STATIC_ASSERT_CONST_INVOCABLE(F1)
|
||||
BOOST_UNORDERED_STATIC_ASSERT_CONST_INVOCABLE(F2)
|
||||
return table_.insert_and_visit(std::move(obj), f1, f2);
|
||||
}
|
||||
|
||||
template <class K, class F1, class F2>
|
||||
BOOST_FORCEINLINE typename std::enable_if<
|
||||
detail::are_transparent<K, hasher, key_equal>::value,
|
||||
bool >::type
|
||||
insert_and_visit(K&& k, F1 f1, F2 f2)
|
||||
{
|
||||
BOOST_UNORDERED_STATIC_ASSERT_CONST_INVOCABLE(F1)
|
||||
BOOST_UNORDERED_STATIC_ASSERT_CONST_INVOCABLE(F2)
|
||||
return table_.try_emplace_and_visit(std::forward<K>(k), f1, f2);
|
||||
}
|
||||
|
||||
template <class InputIterator, class F1, class F2>
|
||||
void insert_and_visit(
|
||||
InputIterator first, InputIterator last, F1 f1, F2 f2)
|
||||
{
|
||||
BOOST_UNORDERED_STATIC_ASSERT_CONST_INVOCABLE(F1)
|
||||
BOOST_UNORDERED_STATIC_ASSERT_CONST_INVOCABLE(F2)
|
||||
for (; first != last; ++first) {
|
||||
table_.emplace_and_visit(*first, f1, f2);
|
||||
}
|
||||
}
|
||||
|
||||
template <class F1, class F2>
|
||||
void insert_and_visit(std::initializer_list<value_type> ilist, F1 f1, F2 f2)
|
||||
{
|
||||
BOOST_UNORDERED_STATIC_ASSERT_CONST_INVOCABLE(F1)
|
||||
BOOST_UNORDERED_STATIC_ASSERT_CONST_INVOCABLE(F2)
|
||||
this->insert_and_visit(ilist.begin(), ilist.end(), f1, f2);
|
||||
}
|
||||
|
||||
template <class F1, class F2>
|
||||
BOOST_FORCEINLINE bool insert_and_cvisit(
|
||||
value_type const& obj, F1 f1, F2 f2)
|
||||
{
|
||||
BOOST_UNORDERED_STATIC_ASSERT_CONST_INVOCABLE(F1)
|
||||
BOOST_UNORDERED_STATIC_ASSERT_CONST_INVOCABLE(F2)
|
||||
return table_.insert_and_cvisit(obj, f1, f2);
|
||||
}
|
||||
|
||||
template <class F1, class F2>
|
||||
BOOST_FORCEINLINE bool insert_and_cvisit(value_type&& obj, F1 f1, F2 f2)
|
||||
{
|
||||
BOOST_UNORDERED_STATIC_ASSERT_CONST_INVOCABLE(F1)
|
||||
BOOST_UNORDERED_STATIC_ASSERT_CONST_INVOCABLE(F2)
|
||||
return table_.insert_and_cvisit(std::move(obj), f1, f2);
|
||||
}
|
||||
|
||||
template <class K, class F1, class F2>
|
||||
BOOST_FORCEINLINE typename std::enable_if<
|
||||
detail::are_transparent<K, hasher, key_equal>::value,
|
||||
bool >::type
|
||||
insert_and_cvisit(K&& k, F1 f1, F2 f2)
|
||||
{
|
||||
BOOST_UNORDERED_STATIC_ASSERT_CONST_INVOCABLE(F1)
|
||||
BOOST_UNORDERED_STATIC_ASSERT_CONST_INVOCABLE(F2)
|
||||
return table_.try_emplace_and_cvisit(std::forward<K>(k), f1, f2);
|
||||
}
|
||||
|
||||
template <class InputIterator, class F1, class F2>
|
||||
void insert_and_cvisit(
|
||||
InputIterator first, InputIterator last, F1 f1, F2 f2)
|
||||
{
|
||||
BOOST_UNORDERED_STATIC_ASSERT_CONST_INVOCABLE(F1)
|
||||
BOOST_UNORDERED_STATIC_ASSERT_CONST_INVOCABLE(F2)
|
||||
for (; first != last; ++first) {
|
||||
table_.emplace_and_cvisit(*first, f1, f2);
|
||||
}
|
||||
}
|
||||
|
||||
template <class F1, class F2>
|
||||
void insert_and_cvisit(
|
||||
std::initializer_list<value_type> ilist, F1 f1, F2 f2)
|
||||
{
|
||||
BOOST_UNORDERED_STATIC_ASSERT_CONST_INVOCABLE(F1)
|
||||
BOOST_UNORDERED_STATIC_ASSERT_CONST_INVOCABLE(F2)
|
||||
this->insert_and_cvisit(ilist.begin(), ilist.end(), f1, f2);
|
||||
}
|
||||
|
||||
template <class... Args> BOOST_FORCEINLINE bool emplace(Args&&... args)
|
||||
{
|
||||
return table_.emplace(std::forward<Args>(args)...);
|
||||
@@ -538,6 +633,30 @@ namespace boost {
|
||||
std::forward<Arg>(arg), std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template <class Arg1, class Arg2, class... Args>
|
||||
BOOST_FORCEINLINE bool emplace_and_visit(
|
||||
Arg1&& arg1, Arg2&& arg2, Args&&... args)
|
||||
{
|
||||
BOOST_UNORDERED_STATIC_ASSERT_PENULTIMATE_ARG_CONST_INVOCABLE(
|
||||
Arg1, Arg2, Args...)
|
||||
BOOST_UNORDERED_STATIC_ASSERT_LAST_ARG_CONST_INVOCABLE(Arg2, Args...)
|
||||
return table_.emplace_and_visit(
|
||||
std::forward<Arg1>(arg1), std::forward<Arg2>(arg2),
|
||||
std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template <class Arg1, class Arg2, class... Args>
|
||||
BOOST_FORCEINLINE bool emplace_and_cvisit(
|
||||
Arg1&& arg1, Arg2&& arg2, Args&&... args)
|
||||
{
|
||||
BOOST_UNORDERED_STATIC_ASSERT_PENULTIMATE_ARG_CONST_INVOCABLE(
|
||||
Arg1, Arg2, Args...)
|
||||
BOOST_UNORDERED_STATIC_ASSERT_LAST_ARG_CONST_INVOCABLE(Arg2, Args...)
|
||||
return table_.emplace_and_cvisit(
|
||||
std::forward<Arg1>(arg1), std::forward<Arg2>(arg2),
|
||||
std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
BOOST_FORCEINLINE size_type erase(key_type const& k)
|
||||
{
|
||||
return table_.erase(k);
|
||||
|
||||
@@ -585,6 +585,124 @@ namespace boost {
|
||||
}
|
||||
}
|
||||
|
||||
template <class Ty, class F1, class F2>
|
||||
BOOST_FORCEINLINE auto insert_and_visit(Ty&& value, F1 f1, F2 f2)
|
||||
-> decltype(table_.insert_and_visit(std::forward<Ty>(value), f1, f2))
|
||||
{
|
||||
BOOST_UNORDERED_STATIC_ASSERT_INVOCABLE(F1)
|
||||
BOOST_UNORDERED_STATIC_ASSERT_INVOCABLE(F2)
|
||||
return table_.insert_and_visit(std::forward<Ty>(value), f1, f2);
|
||||
}
|
||||
|
||||
template <class F1, class F2>
|
||||
BOOST_FORCEINLINE bool insert_and_visit(init_type&& obj, F1 f1, F2 f2)
|
||||
{
|
||||
BOOST_UNORDERED_STATIC_ASSERT_INVOCABLE(F1)
|
||||
BOOST_UNORDERED_STATIC_ASSERT_INVOCABLE(F2)
|
||||
return table_.insert_and_visit(std::move(obj), f1, f2);
|
||||
}
|
||||
|
||||
template <class InputIterator, class F1, class F2>
|
||||
void insert_and_visit(
|
||||
InputIterator first, InputIterator last, F1 f1, F2 f2)
|
||||
{
|
||||
BOOST_UNORDERED_STATIC_ASSERT_INVOCABLE(F1)
|
||||
BOOST_UNORDERED_STATIC_ASSERT_INVOCABLE(F2)
|
||||
for (; first != last; ++first) {
|
||||
table_.emplace_and_visit(*first, f1, f2);
|
||||
}
|
||||
}
|
||||
|
||||
template <class F1, class F2>
|
||||
void insert_and_visit(
|
||||
std::initializer_list<value_type> ilist, F1 f1, F2 f2)
|
||||
{
|
||||
BOOST_UNORDERED_STATIC_ASSERT_INVOCABLE(F1)
|
||||
BOOST_UNORDERED_STATIC_ASSERT_INVOCABLE(F2)
|
||||
this->insert_and_visit(ilist.begin(), ilist.end(), f1, f2);
|
||||
}
|
||||
|
||||
template <class F1, class F2>
|
||||
insert_return_type insert_and_visit(node_type&& nh, F1 f1, F2 f2)
|
||||
{
|
||||
BOOST_UNORDERED_STATIC_ASSERT_INVOCABLE(F1)
|
||||
BOOST_UNORDERED_STATIC_ASSERT_INVOCABLE(F2)
|
||||
using access = detail::foa::node_handle_access;
|
||||
|
||||
if (nh.empty()) {
|
||||
return {false, node_type{}};
|
||||
}
|
||||
|
||||
// Caveat: get_allocator() incurs synchronization (not cheap)
|
||||
BOOST_ASSERT(get_allocator() == nh.get_allocator());
|
||||
|
||||
if (table_.insert_and_visit(std::move(access::element(nh)), f1, f2)) {
|
||||
access::reset(nh);
|
||||
return {true, node_type{}};
|
||||
} else {
|
||||
return {false, std::move(nh)};
|
||||
}
|
||||
}
|
||||
|
||||
template <class Ty, class F1, class F2>
|
||||
BOOST_FORCEINLINE auto insert_and_cvisit(Ty&& value, F1 f1, F2 f2)
|
||||
-> decltype(table_.insert_and_cvisit(std::forward<Ty>(value), f1, f2))
|
||||
{
|
||||
BOOST_UNORDERED_STATIC_ASSERT_INVOCABLE(F1)
|
||||
BOOST_UNORDERED_STATIC_ASSERT_CONST_INVOCABLE(F2)
|
||||
return table_.insert_and_cvisit(std::forward<Ty>(value), f1, f2);
|
||||
}
|
||||
|
||||
template <class F1, class F2>
|
||||
BOOST_FORCEINLINE bool insert_and_cvisit(init_type&& obj, F1 f1, F2 f2)
|
||||
{
|
||||
BOOST_UNORDERED_STATIC_ASSERT_INVOCABLE(F1)
|
||||
BOOST_UNORDERED_STATIC_ASSERT_CONST_INVOCABLE(F2)
|
||||
return table_.insert_and_cvisit(std::move(obj), f1, f2);
|
||||
}
|
||||
|
||||
template <class InputIterator, class F1, class F2>
|
||||
void insert_and_cvisit(
|
||||
InputIterator first, InputIterator last, F1 f1, F2 f2)
|
||||
{
|
||||
BOOST_UNORDERED_STATIC_ASSERT_INVOCABLE(F1)
|
||||
BOOST_UNORDERED_STATIC_ASSERT_CONST_INVOCABLE(F2)
|
||||
for (; first != last; ++first) {
|
||||
table_.emplace_and_cvisit(*first, f1, f2);
|
||||
}
|
||||
}
|
||||
|
||||
template <class F1, class F2>
|
||||
void insert_and_cvisit(
|
||||
std::initializer_list<value_type> ilist, F1 f1, F2 f2)
|
||||
{
|
||||
BOOST_UNORDERED_STATIC_ASSERT_INVOCABLE(F1)
|
||||
BOOST_UNORDERED_STATIC_ASSERT_CONST_INVOCABLE(F2)
|
||||
this->insert_and_cvisit(ilist.begin(), ilist.end(), f1, f2);
|
||||
}
|
||||
|
||||
template <class F1, class F2>
|
||||
insert_return_type insert_and_cvisit(node_type&& nh, F1 f1, F2 f2)
|
||||
{
|
||||
BOOST_UNORDERED_STATIC_ASSERT_INVOCABLE(F1)
|
||||
BOOST_UNORDERED_STATIC_ASSERT_CONST_INVOCABLE(F2)
|
||||
using access = detail::foa::node_handle_access;
|
||||
|
||||
if (nh.empty()) {
|
||||
return {false, node_type{}};
|
||||
}
|
||||
|
||||
// Caveat: get_allocator() incurs synchronization (not cheap)
|
||||
BOOST_ASSERT(get_allocator() == nh.get_allocator());
|
||||
|
||||
if (table_.insert_and_cvisit(std::move(access::element(nh)), f1, f2)) {
|
||||
access::reset(nh);
|
||||
return {true, node_type{}};
|
||||
} else {
|
||||
return {false, std::move(nh)};
|
||||
}
|
||||
}
|
||||
|
||||
template <class... Args> BOOST_FORCEINLINE bool emplace(Args&&... args)
|
||||
{
|
||||
return table_.emplace(std::forward<Args>(args)...);
|
||||
@@ -606,6 +724,30 @@ namespace boost {
|
||||
std::forward<Arg>(arg), std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template <class Arg1, class Arg2, class... Args>
|
||||
BOOST_FORCEINLINE bool emplace_and_visit(
|
||||
Arg1&& arg1, Arg2&& arg2, Args&&... args)
|
||||
{
|
||||
BOOST_UNORDERED_STATIC_ASSERT_PENULTIMATE_ARG_INVOCABLE(
|
||||
Arg1, Arg2, Args...)
|
||||
BOOST_UNORDERED_STATIC_ASSERT_LAST_ARG_INVOCABLE(Arg2, Args...)
|
||||
return table_.emplace_and_visit(
|
||||
std::forward<Arg1>(arg1), std::forward<Arg2>(arg2),
|
||||
std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template <class Arg1, class Arg2, class... Args>
|
||||
BOOST_FORCEINLINE bool emplace_and_cvisit(
|
||||
Arg1&& arg1, Arg2&& arg2, Args&&... args)
|
||||
{
|
||||
BOOST_UNORDERED_STATIC_ASSERT_PENULTIMATE_ARG_INVOCABLE(
|
||||
Arg1, Arg2, Args...)
|
||||
BOOST_UNORDERED_STATIC_ASSERT_LAST_ARG_CONST_INVOCABLE(Arg2, Args...)
|
||||
return table_.emplace_and_cvisit(
|
||||
std::forward<Arg1>(arg1), std::forward<Arg2>(arg2),
|
||||
std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template <class... Args>
|
||||
BOOST_FORCEINLINE bool try_emplace(key_type const& k, Args&&... args)
|
||||
{
|
||||
@@ -681,6 +823,78 @@ namespace boost {
|
||||
std::forward<Arg>(arg), std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template <class Arg1, class Arg2, class... Args>
|
||||
BOOST_FORCEINLINE bool try_emplace_and_visit(
|
||||
key_type const& k, Arg1&& arg1, Arg2&& arg2, Args&&... args)
|
||||
{
|
||||
BOOST_UNORDERED_STATIC_ASSERT_PENULTIMATE_ARG_INVOCABLE(
|
||||
Arg1, Arg2, Args...)
|
||||
BOOST_UNORDERED_STATIC_ASSERT_LAST_ARG_INVOCABLE(Arg2, Args...)
|
||||
return table_.try_emplace_and_visit(
|
||||
k, std::forward<Arg1>(arg1), std::forward<Arg2>(arg2),
|
||||
std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template <class Arg1, class Arg2, class... Args>
|
||||
BOOST_FORCEINLINE bool try_emplace_and_cvisit(
|
||||
key_type const& k, Arg1&& arg1, Arg2&& arg2, Args&&... args)
|
||||
{
|
||||
BOOST_UNORDERED_STATIC_ASSERT_PENULTIMATE_ARG_INVOCABLE(
|
||||
Arg1, Arg2, Args...)
|
||||
BOOST_UNORDERED_STATIC_ASSERT_LAST_ARG_CONST_INVOCABLE(Arg2, Args...)
|
||||
return table_.try_emplace_and_cvisit(
|
||||
k, std::forward<Arg1>(arg1), std::forward<Arg2>(arg2),
|
||||
std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template <class Arg1, class Arg2, class... Args>
|
||||
BOOST_FORCEINLINE bool try_emplace_and_visit(
|
||||
key_type&& k, Arg1&& arg1, Arg2&& arg2, Args&&... args)
|
||||
{
|
||||
BOOST_UNORDERED_STATIC_ASSERT_PENULTIMATE_ARG_INVOCABLE(
|
||||
Arg1, Arg2, Args...)
|
||||
BOOST_UNORDERED_STATIC_ASSERT_LAST_ARG_INVOCABLE(Arg2, Args...)
|
||||
return table_.try_emplace_and_visit(
|
||||
std::move(k), std::forward<Arg1>(arg1), std::forward<Arg2>(arg2),
|
||||
std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template <class Arg1, class Arg2, class... Args>
|
||||
BOOST_FORCEINLINE bool try_emplace_and_cvisit(
|
||||
key_type&& k, Arg1&& arg1, Arg2&& arg2, Args&&... args)
|
||||
{
|
||||
BOOST_UNORDERED_STATIC_ASSERT_PENULTIMATE_ARG_INVOCABLE(
|
||||
Arg1, Arg2, Args...)
|
||||
BOOST_UNORDERED_STATIC_ASSERT_LAST_ARG_CONST_INVOCABLE(Arg2, Args...)
|
||||
return table_.try_emplace_and_cvisit(
|
||||
std::move(k), std::forward<Arg1>(arg1), std::forward<Arg2>(arg2),
|
||||
std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template <class K, class Arg1, class Arg2, class... Args>
|
||||
BOOST_FORCEINLINE bool try_emplace_and_visit(
|
||||
K&& k, Arg1&& arg1, Arg2&& arg2, Args&&... args)
|
||||
{
|
||||
BOOST_UNORDERED_STATIC_ASSERT_PENULTIMATE_ARG_INVOCABLE(
|
||||
Arg1, Arg2, Args...)
|
||||
BOOST_UNORDERED_STATIC_ASSERT_LAST_ARG_INVOCABLE(Arg2, Args...)
|
||||
return table_.try_emplace_and_visit(std::forward<K>(k),
|
||||
std::forward<Arg1>(arg1), std::forward<Arg2>(arg2),
|
||||
std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template <class K, class Arg1, class Arg2, class... Args>
|
||||
BOOST_FORCEINLINE bool try_emplace_and_cvisit(
|
||||
K&& k, Arg1&& arg1, Arg2&& arg2, Args&&... args)
|
||||
{
|
||||
BOOST_UNORDERED_STATIC_ASSERT_PENULTIMATE_ARG_INVOCABLE(
|
||||
Arg1, Arg2, Args...)
|
||||
BOOST_UNORDERED_STATIC_ASSERT_LAST_ARG_CONST_INVOCABLE(Arg2, Args...)
|
||||
return table_.try_emplace_and_cvisit(std::forward<K>(k),
|
||||
std::forward<Arg1>(arg1), std::forward<Arg2>(arg2),
|
||||
std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
BOOST_FORCEINLINE size_type erase(key_type const& k)
|
||||
{
|
||||
return table_.erase(k);
|
||||
|
||||
@@ -585,6 +585,145 @@ namespace boost {
|
||||
}
|
||||
}
|
||||
|
||||
template <class F1, class F2>
|
||||
BOOST_FORCEINLINE bool insert_and_visit(
|
||||
value_type const& obj, F1 f1, F2 f2)
|
||||
{
|
||||
BOOST_UNORDERED_STATIC_ASSERT_CONST_INVOCABLE(F1)
|
||||
BOOST_UNORDERED_STATIC_ASSERT_CONST_INVOCABLE(F2)
|
||||
return table_.insert_and_visit(obj, f1, f2);
|
||||
}
|
||||
|
||||
template <class F1, class F2>
|
||||
BOOST_FORCEINLINE bool insert_and_visit(value_type&& obj, F1 f1, F2 f2)
|
||||
{
|
||||
BOOST_UNORDERED_STATIC_ASSERT_CONST_INVOCABLE(F1)
|
||||
BOOST_UNORDERED_STATIC_ASSERT_CONST_INVOCABLE(F2)
|
||||
return table_.insert_and_visit(std::move(obj), f1, f2);
|
||||
}
|
||||
|
||||
template <class K, class F1, class F2>
|
||||
BOOST_FORCEINLINE typename std::enable_if<
|
||||
detail::are_transparent<K, hasher, key_equal>::value,
|
||||
bool >::type
|
||||
insert_and_visit(K&& k, F1 f1, F2 f2)
|
||||
{
|
||||
BOOST_UNORDERED_STATIC_ASSERT_CONST_INVOCABLE(F1)
|
||||
BOOST_UNORDERED_STATIC_ASSERT_CONST_INVOCABLE(F2)
|
||||
return table_.try_emplace_and_visit(std::forward<K>(k), f1, f2);
|
||||
}
|
||||
|
||||
template <class InputIterator, class F1, class F2>
|
||||
void insert_and_visit(
|
||||
InputIterator first, InputIterator last, F1 f1, F2 f2)
|
||||
{
|
||||
BOOST_UNORDERED_STATIC_ASSERT_CONST_INVOCABLE(F1)
|
||||
BOOST_UNORDERED_STATIC_ASSERT_CONST_INVOCABLE(F2)
|
||||
for (; first != last; ++first) {
|
||||
table_.emplace_and_visit(*first, f1, f2);
|
||||
}
|
||||
}
|
||||
|
||||
template <class F1, class F2>
|
||||
void insert_and_visit(std::initializer_list<value_type> ilist, F1 f1, F2 f2)
|
||||
{
|
||||
BOOST_UNORDERED_STATIC_ASSERT_CONST_INVOCABLE(F1)
|
||||
BOOST_UNORDERED_STATIC_ASSERT_CONST_INVOCABLE(F2)
|
||||
this->insert_and_visit(ilist.begin(), ilist.end(), f1, f2);
|
||||
}
|
||||
|
||||
template <class F1, class F2>
|
||||
insert_return_type insert_and_visit(node_type&& nh, F1 f1, F2 f2)
|
||||
{
|
||||
BOOST_UNORDERED_STATIC_ASSERT_CONST_INVOCABLE(F1)
|
||||
BOOST_UNORDERED_STATIC_ASSERT_CONST_INVOCABLE(F2)
|
||||
using access = detail::foa::node_handle_access;
|
||||
|
||||
if (nh.empty()) {
|
||||
return {false, node_type{}};
|
||||
}
|
||||
|
||||
// Caveat: get_allocator() incurs synchronization (not cheap)
|
||||
BOOST_ASSERT(get_allocator() == nh.get_allocator());
|
||||
|
||||
if (table_.insert_and_visit(std::move(access::element(nh)), f1, f2)) {
|
||||
access::reset(nh);
|
||||
return {true, node_type{}};
|
||||
} else {
|
||||
return {false, std::move(nh)};
|
||||
}
|
||||
}
|
||||
|
||||
template <class F1, class F2>
|
||||
BOOST_FORCEINLINE bool insert_and_cvisit(
|
||||
value_type const& obj, F1 f1, F2 f2)
|
||||
{
|
||||
BOOST_UNORDERED_STATIC_ASSERT_CONST_INVOCABLE(F1)
|
||||
BOOST_UNORDERED_STATIC_ASSERT_CONST_INVOCABLE(F2)
|
||||
return table_.insert_and_cvisit(obj, f1, f2);
|
||||
}
|
||||
|
||||
template <class F1, class F2>
|
||||
BOOST_FORCEINLINE bool insert_and_cvisit(value_type&& obj, F1 f1, F2 f2)
|
||||
{
|
||||
BOOST_UNORDERED_STATIC_ASSERT_CONST_INVOCABLE(F1)
|
||||
BOOST_UNORDERED_STATIC_ASSERT_CONST_INVOCABLE(F2)
|
||||
return table_.insert_and_cvisit(std::move(obj), f1, f2);
|
||||
}
|
||||
|
||||
template <class K, class F1, class F2>
|
||||
BOOST_FORCEINLINE typename std::enable_if<
|
||||
detail::are_transparent<K, hasher, key_equal>::value,
|
||||
bool >::type
|
||||
insert_and_cvisit(K&& k, F1 f1, F2 f2)
|
||||
{
|
||||
BOOST_UNORDERED_STATIC_ASSERT_CONST_INVOCABLE(F1)
|
||||
BOOST_UNORDERED_STATIC_ASSERT_CONST_INVOCABLE(F2)
|
||||
return table_.try_emplace_and_cvisit(std::forward<K>(k), f1, f2);
|
||||
}
|
||||
|
||||
template <class InputIterator, class F1, class F2>
|
||||
void insert_and_cvisit(
|
||||
InputIterator first, InputIterator last, F1 f1, F2 f2)
|
||||
{
|
||||
BOOST_UNORDERED_STATIC_ASSERT_CONST_INVOCABLE(F1)
|
||||
BOOST_UNORDERED_STATIC_ASSERT_CONST_INVOCABLE(F2)
|
||||
for (; first != last; ++first) {
|
||||
table_.emplace_and_cvisit(*first, f1, f2);
|
||||
}
|
||||
}
|
||||
|
||||
template <class F1, class F2>
|
||||
void insert_and_cvisit(
|
||||
std::initializer_list<value_type> ilist, F1 f1, F2 f2)
|
||||
{
|
||||
BOOST_UNORDERED_STATIC_ASSERT_CONST_INVOCABLE(F1)
|
||||
BOOST_UNORDERED_STATIC_ASSERT_CONST_INVOCABLE(F2)
|
||||
this->insert_and_cvisit(ilist.begin(), ilist.end(), f1, f2);
|
||||
}
|
||||
|
||||
template <class F1, class F2>
|
||||
insert_return_type insert_and_cvisit(node_type&& nh, F1 f1, F2 f2)
|
||||
{
|
||||
BOOST_UNORDERED_STATIC_ASSERT_CONST_INVOCABLE(F1)
|
||||
BOOST_UNORDERED_STATIC_ASSERT_CONST_INVOCABLE(F2)
|
||||
using access = detail::foa::node_handle_access;
|
||||
|
||||
if (nh.empty()) {
|
||||
return {false, node_type{}};
|
||||
}
|
||||
|
||||
// Caveat: get_allocator() incurs synchronization (not cheap)
|
||||
BOOST_ASSERT(get_allocator() == nh.get_allocator());
|
||||
|
||||
if (table_.insert_and_cvisit(std::move(access::element(nh)), f1, f2)) {
|
||||
access::reset(nh);
|
||||
return {true, node_type{}};
|
||||
} else {
|
||||
return {false, std::move(nh)};
|
||||
}
|
||||
}
|
||||
|
||||
template <class... Args> BOOST_FORCEINLINE bool emplace(Args&&... args)
|
||||
{
|
||||
return table_.emplace(std::forward<Args>(args)...);
|
||||
@@ -606,6 +745,30 @@ namespace boost {
|
||||
std::forward<Arg>(arg), std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template <class Arg1, class Arg2, class... Args>
|
||||
BOOST_FORCEINLINE bool emplace_and_visit(
|
||||
Arg1&& arg1, Arg2&& arg2, Args&&... args)
|
||||
{
|
||||
BOOST_UNORDERED_STATIC_ASSERT_PENULTIMATE_ARG_CONST_INVOCABLE(
|
||||
Arg1, Arg2, Args...)
|
||||
BOOST_UNORDERED_STATIC_ASSERT_LAST_ARG_CONST_INVOCABLE(Arg2, Args...)
|
||||
return table_.emplace_and_visit(
|
||||
std::forward<Arg1>(arg1), std::forward<Arg2>(arg2),
|
||||
std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template <class Arg1, class Arg2, class... Args>
|
||||
BOOST_FORCEINLINE bool emplace_and_cvisit(
|
||||
Arg1&& arg1, Arg2&& arg2, Args&&... args)
|
||||
{
|
||||
BOOST_UNORDERED_STATIC_ASSERT_PENULTIMATE_ARG_CONST_INVOCABLE(
|
||||
Arg1, Arg2, Args...)
|
||||
BOOST_UNORDERED_STATIC_ASSERT_LAST_ARG_CONST_INVOCABLE(Arg2, Args...)
|
||||
return table_.emplace_and_cvisit(
|
||||
std::forward<Arg1>(arg1), std::forward<Arg2>(arg2),
|
||||
std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
BOOST_FORCEINLINE size_type erase(key_type const& k)
|
||||
{
|
||||
return table_.erase(k);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* Copyright 2023 Christian Mazakas.
|
||||
* Copyright 2023 Joaquin M Lopez Munoz.
|
||||
* Copyright 2023-2024 Joaquin M Lopez Munoz.
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
* http://www.boost.org/LICENSE_1_0.txt)
|
||||
@@ -58,6 +58,24 @@
|
||||
BOOST_UNORDERED_STATIC_ASSERT_CONST_INVOCABLE( \
|
||||
BOOST_UNORDERED_DETAIL_LAST_ARG(Arg, Args))
|
||||
|
||||
#define BOOST_UNORDERED_DETAIL_PENULTIMATE_ARG(Arg1, Arg2, Args) \
|
||||
mp11::mp_at_c<mp11::mp_list< \
|
||||
Arg1 BOOST_UNORDERED_DETAIL_COMMA Arg2 BOOST_UNORDERED_DETAIL_COMMA Args \
|
||||
>, \
|
||||
mp11::mp_size<mp11::mp_list< \
|
||||
Arg1 BOOST_UNORDERED_DETAIL_COMMA Arg2 BOOST_UNORDERED_DETAIL_COMMA Args \
|
||||
>>::value - 2>
|
||||
|
||||
#define BOOST_UNORDERED_STATIC_ASSERT_PENULTIMATE_ARG_INVOCABLE( \
|
||||
Arg1, Arg2, Args) \
|
||||
BOOST_UNORDERED_STATIC_ASSERT_INVOCABLE( \
|
||||
BOOST_UNORDERED_DETAIL_PENULTIMATE_ARG(Arg1, Arg2, Args))
|
||||
|
||||
#define BOOST_UNORDERED_STATIC_ASSERT_PENULTIMATE_ARG_CONST_INVOCABLE( \
|
||||
Arg1, Arg2, Args) \
|
||||
BOOST_UNORDERED_STATIC_ASSERT_CONST_INVOCABLE( \
|
||||
BOOST_UNORDERED_DETAIL_PENULTIMATE_ARG(Arg1, Arg2, Args))
|
||||
|
||||
namespace boost {
|
||||
namespace unordered {
|
||||
namespace detail {
|
||||
|
||||
@@ -215,7 +215,7 @@ struct atomic_integral
|
||||
|
||||
/* Group-level concurrency protection. It provides a rw mutex plus an
|
||||
* atomic insertion counter for optimistic insertion (see
|
||||
* unprotected_norehash_emplace_or_visit).
|
||||
* unprotected_norehash_emplace_and_visit).
|
||||
*/
|
||||
|
||||
struct group_access
|
||||
@@ -755,6 +755,22 @@ public:
|
||||
try_emplace_args_t{},std::forward<Key>(x),std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template<typename Key,typename... Args>
|
||||
BOOST_FORCEINLINE bool try_emplace_and_visit(Key&& x,Args&&... args)
|
||||
{
|
||||
return emplace_and_visit_flast(
|
||||
group_exclusive{},
|
||||
try_emplace_args_t{},std::forward<Key>(x),std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template<typename Key,typename... Args>
|
||||
BOOST_FORCEINLINE bool try_emplace_and_cvisit(Key&& x,Args&&... args)
|
||||
{
|
||||
return emplace_and_visit_flast(
|
||||
group_shared{},
|
||||
try_emplace_args_t{},std::forward<Key>(x),std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template<typename... Args>
|
||||
BOOST_FORCEINLINE bool emplace_or_visit(Args&&... args)
|
||||
{
|
||||
@@ -769,86 +785,121 @@ public:
|
||||
group_shared{},std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template<typename F>
|
||||
BOOST_FORCEINLINE bool insert_or_visit(const init_type& x,F&& f)
|
||||
template<typename... Args>
|
||||
BOOST_FORCEINLINE bool emplace_and_visit(Args&&... args)
|
||||
{
|
||||
return emplace_or_visit_impl(group_exclusive{},std::forward<F>(f),x);
|
||||
return construct_and_emplace_and_visit_flast(
|
||||
group_exclusive{},std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template<typename F>
|
||||
BOOST_FORCEINLINE bool insert_or_cvisit(const init_type& x,F&& f)
|
||||
template<typename... Args>
|
||||
BOOST_FORCEINLINE bool emplace_and_cvisit(Args&&... args)
|
||||
{
|
||||
return emplace_or_visit_impl(group_shared{},std::forward<F>(f),x);
|
||||
return construct_and_emplace_and_visit_flast(
|
||||
group_shared{},std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template<typename F>
|
||||
BOOST_FORCEINLINE bool insert_or_visit(init_type&& x,F&& f)
|
||||
template<typename Value,typename F>
|
||||
BOOST_FORCEINLINE bool insert_or_visit(Value&& x,F&& f)
|
||||
{
|
||||
return emplace_or_visit_impl(
|
||||
group_exclusive{},std::forward<F>(f),std::move(x));
|
||||
return insert_and_visit(
|
||||
std::forward<Value>(x),[](const value_type&){},std::forward<F>(f));
|
||||
}
|
||||
|
||||
template<typename F>
|
||||
BOOST_FORCEINLINE bool insert_or_cvisit(init_type&& x,F&& f)
|
||||
template<typename Value,typename F>
|
||||
BOOST_FORCEINLINE bool insert_or_cvisit(Value&& x,F&& f)
|
||||
{
|
||||
return emplace_or_visit_impl(
|
||||
group_shared{},std::forward<F>(f),std::move(x));
|
||||
return insert_and_cvisit(
|
||||
std::forward<Value>(x),[](const value_type&){},std::forward<F>(f));
|
||||
}
|
||||
|
||||
template<typename F1,typename F2>
|
||||
BOOST_FORCEINLINE bool insert_and_visit(const init_type& x,F1&& f1,F2&& f2)
|
||||
{
|
||||
return emplace_and_visit_impl(
|
||||
group_exclusive{},std::forward<F1>(f1),std::forward<F2>(f2),x);
|
||||
}
|
||||
|
||||
template<typename F1,typename F2>
|
||||
BOOST_FORCEINLINE bool insert_and_cvisit(const init_type& x,F1&& f1,F2&& f2)
|
||||
{
|
||||
return emplace_and_visit_impl(
|
||||
group_shared{},std::forward<F1>(f1),std::forward<F2>(f2),x);
|
||||
}
|
||||
|
||||
template<typename F1,typename F2>
|
||||
BOOST_FORCEINLINE bool insert_and_visit(init_type&& x,F1&& f1,F2&& f2)
|
||||
{
|
||||
return emplace_and_visit_impl(
|
||||
group_exclusive{},std::forward<F1>(f1),std::forward<F2>(f2),
|
||||
std::move(x));
|
||||
}
|
||||
|
||||
template<typename F1,typename F2>
|
||||
BOOST_FORCEINLINE bool insert_and_cvisit(init_type&& x,F1&& f1,F2&& f2)
|
||||
{
|
||||
return emplace_and_visit_impl(
|
||||
group_shared{},std::forward<F1>(f1),std::forward<F2>(f2),std::move(x));
|
||||
}
|
||||
|
||||
/* SFINAE tilts call ambiguities in favor of init_type */
|
||||
|
||||
template<typename Value,typename F>
|
||||
BOOST_FORCEINLINE auto insert_or_visit(const Value& x,F&& f)
|
||||
template<typename Value,typename F1,typename F2>
|
||||
BOOST_FORCEINLINE auto insert_and_visit(const Value& x,F1&& f1,F2&& f2)
|
||||
->enable_if_is_value_type<Value,bool>
|
||||
{
|
||||
return emplace_or_visit_impl(group_exclusive{},std::forward<F>(f),x);
|
||||
return emplace_and_visit_impl(
|
||||
group_exclusive{},std::forward<F1>(f1),std::forward<F2>(f2),x);
|
||||
}
|
||||
|
||||
template<typename Value,typename F>
|
||||
BOOST_FORCEINLINE auto insert_or_cvisit(const Value& x,F&& f)
|
||||
template<typename Value,typename F1,typename F2>
|
||||
BOOST_FORCEINLINE auto insert_and_cvisit(const Value& x,F1&& f1,F2&& f2)
|
||||
->enable_if_is_value_type<Value,bool>
|
||||
{
|
||||
return emplace_or_visit_impl(group_shared{},std::forward<F>(f),x);
|
||||
return emplace_and_visit_impl(
|
||||
group_shared{},std::forward<F1>(f1),std::forward<F2>(f2),x);
|
||||
}
|
||||
|
||||
template<typename Value,typename F>
|
||||
BOOST_FORCEINLINE auto insert_or_visit(Value&& x,F&& f)
|
||||
template<typename Value,typename F1,typename F2>
|
||||
BOOST_FORCEINLINE auto insert_and_visit(Value&& x,F1&& f1,F2&& f2)
|
||||
->enable_if_is_value_type<Value,bool>
|
||||
{
|
||||
return emplace_or_visit_impl(
|
||||
group_exclusive{},std::forward<F>(f),std::move(x));
|
||||
return emplace_and_visit_impl(
|
||||
group_exclusive{},std::forward<F1>(f1),std::forward<F2>(f2),
|
||||
std::move(x));
|
||||
}
|
||||
|
||||
template<typename Value,typename F>
|
||||
BOOST_FORCEINLINE auto insert_or_cvisit(Value&& x,F&& f)
|
||||
template<typename Value,typename F1,typename F2>
|
||||
BOOST_FORCEINLINE auto insert_and_cvisit(Value&& x,F1&& f1,F2&& f2)
|
||||
->enable_if_is_value_type<Value,bool>
|
||||
{
|
||||
return emplace_or_visit_impl(
|
||||
group_shared{},std::forward<F>(f),std::move(x));
|
||||
return emplace_and_visit_impl(
|
||||
group_shared{},std::forward<F1>(f1),std::forward<F2>(f2),std::move(x));
|
||||
}
|
||||
|
||||
template<typename F,typename T=element_type>
|
||||
template<typename F1,typename F2,typename T=element_type>
|
||||
BOOST_FORCEINLINE
|
||||
typename std::enable_if<
|
||||
!std::is_same<T,value_type>::value,
|
||||
bool
|
||||
>::type
|
||||
insert_or_visit(element_type&& x, F&& f)
|
||||
insert_and_visit(element_type&& x,F1&& f1,F2&& f2)
|
||||
{
|
||||
return emplace_or_visit_impl(
|
||||
group_exclusive{},std::forward<F>(f),std::move(x));
|
||||
return emplace_and_visit_impl(
|
||||
group_exclusive{},std::forward<F1>(f1),std::forward<F2>(f2),
|
||||
std::move(x));
|
||||
}
|
||||
|
||||
template<typename F,typename T=element_type>
|
||||
template<typename F1,typename F2,typename T=element_type>
|
||||
BOOST_FORCEINLINE
|
||||
typename std::enable_if<
|
||||
!std::is_same<T,value_type>::value,
|
||||
bool
|
||||
>::type
|
||||
insert_or_cvisit(element_type&& x, F&& f)
|
||||
insert_and_cvisit(element_type&& x,F1&& f1,F2&& f2)
|
||||
{
|
||||
return emplace_or_visit_impl(
|
||||
group_shared{},std::forward<F>(f),std::move(x));
|
||||
return emplace_and_visit_impl(
|
||||
group_shared{},std::forward<F1>(f1),std::forward<F2>(f2),std::move(x));
|
||||
}
|
||||
|
||||
template<typename Key>
|
||||
@@ -1408,23 +1459,59 @@ private:
|
||||
);
|
||||
}
|
||||
|
||||
struct call_construct_and_emplace_and_visit
|
||||
{
|
||||
template<typename... Args>
|
||||
BOOST_FORCEINLINE bool operator()(
|
||||
concurrent_table* this_,Args&&... args)const
|
||||
{
|
||||
return this_->construct_and_emplace_and_visit(
|
||||
std::forward<Args>(args)...);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename GroupAccessMode,typename... Args>
|
||||
BOOST_FORCEINLINE bool construct_and_emplace_and_visit_flast(
|
||||
GroupAccessMode access_mode,Args&&... args)
|
||||
{
|
||||
return mp11::tuple_apply(
|
||||
call_construct_and_emplace_and_visit{},
|
||||
std::tuple_cat(
|
||||
std::make_tuple(this,access_mode),
|
||||
tuple_rotate_right<2>(
|
||||
std::forward_as_tuple(std::forward<Args>(args)...))
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
template<typename GroupAccessMode,typename F,typename... Args>
|
||||
BOOST_FORCEINLINE bool construct_and_emplace_or_visit(
|
||||
GroupAccessMode access_mode,F&& f,Args&&... args)
|
||||
{
|
||||
return construct_and_emplace_and_visit(
|
||||
access_mode,[](const value_type&){},std::forward<F>(f),
|
||||
std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template<typename GroupAccessMode,typename F1,typename F2,typename... Args>
|
||||
BOOST_FORCEINLINE bool construct_and_emplace_and_visit(
|
||||
GroupAccessMode access_mode,F1&& f1,F2&& f2,Args&&... args)
|
||||
{
|
||||
auto lck=shared_access();
|
||||
|
||||
alloc_cted_insert_type<type_policy,Allocator,Args...> x(
|
||||
this->al(),std::forward<Args>(args)...);
|
||||
int res=unprotected_norehash_emplace_or_visit(
|
||||
access_mode,std::forward<F>(f),type_policy::move(x.value()));
|
||||
int res=unprotected_norehash_emplace_and_visit(
|
||||
access_mode,std::forward<F1>(f1),std::forward<F2>(f2),
|
||||
type_policy::move(x.value()));
|
||||
if(BOOST_LIKELY(res>=0))return res!=0;
|
||||
|
||||
lck.unlock();
|
||||
|
||||
rehash_if_full();
|
||||
return noinline_emplace_or_visit(
|
||||
access_mode,std::forward<F>(f),type_policy::move(x.value()));
|
||||
return noinline_emplace_and_visit(
|
||||
access_mode,std::forward<F1>(f1),std::forward<F2>(f2),
|
||||
type_policy::move(x.value()));
|
||||
}
|
||||
|
||||
template<typename... Args>
|
||||
@@ -1442,6 +1529,15 @@ private:
|
||||
access_mode,std::forward<F>(f),std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template<typename GroupAccessMode,typename F1,typename F2,typename... Args>
|
||||
BOOST_NOINLINE bool noinline_emplace_and_visit(
|
||||
GroupAccessMode access_mode,F1&& f1,F2&& f2,Args&&... args)
|
||||
{
|
||||
return emplace_and_visit_impl(
|
||||
access_mode,std::forward<F1>(f1),std::forward<F2>(f2),
|
||||
std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
struct call_emplace_or_visit_impl
|
||||
{
|
||||
template<typename... Args>
|
||||
@@ -1465,15 +1561,49 @@ private:
|
||||
);
|
||||
}
|
||||
|
||||
struct call_emplace_and_visit_impl
|
||||
{
|
||||
template<typename... Args>
|
||||
BOOST_FORCEINLINE bool operator()(
|
||||
concurrent_table* this_,Args&&... args)const
|
||||
{
|
||||
return this_->emplace_and_visit_impl(std::forward<Args>(args)...);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename GroupAccessMode,typename... Args>
|
||||
BOOST_FORCEINLINE bool emplace_and_visit_flast(
|
||||
GroupAccessMode access_mode,Args&&... args)
|
||||
{
|
||||
return mp11::tuple_apply(
|
||||
call_emplace_and_visit_impl{},
|
||||
std::tuple_cat(
|
||||
std::make_tuple(this,access_mode),
|
||||
tuple_rotate_right<2>(
|
||||
std::forward_as_tuple(std::forward<Args>(args)...))
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
template<typename GroupAccessMode,typename F,typename... Args>
|
||||
BOOST_FORCEINLINE bool emplace_or_visit_impl(
|
||||
GroupAccessMode access_mode,F&& f,Args&&... args)
|
||||
{
|
||||
return emplace_and_visit_impl(
|
||||
access_mode,[](const value_type&){},std::forward<F>(f),
|
||||
std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template<typename GroupAccessMode,typename F1,typename F2,typename... Args>
|
||||
BOOST_FORCEINLINE bool emplace_and_visit_impl(
|
||||
GroupAccessMode access_mode,F1&& f1,F2&& f2,Args&&... args)
|
||||
{
|
||||
for(;;){
|
||||
{
|
||||
auto lck=shared_access();
|
||||
int res=unprotected_norehash_emplace_or_visit(
|
||||
access_mode,std::forward<F>(f),std::forward<Args>(args)...);
|
||||
int res=unprotected_norehash_emplace_and_visit(
|
||||
access_mode,std::forward<F1>(f1),std::forward<F2>(f2),
|
||||
std::forward<Args>(args)...);
|
||||
if(BOOST_LIKELY(res>=0))return res!=0;
|
||||
}
|
||||
rehash_if_full();
|
||||
@@ -1498,6 +1628,16 @@ private:
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename GroupAccessMode,typename F,typename... Args>
|
||||
BOOST_FORCEINLINE int
|
||||
unprotected_norehash_emplace_or_visit(
|
||||
GroupAccessMode access_mode,F&& f,Args&&... args)
|
||||
{
|
||||
return unprotected_norehash_emplace_and_visit(
|
||||
access_mode,[&](const value_type&){},
|
||||
std::forward<F>(f),std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
struct reserve_size
|
||||
{
|
||||
reserve_size(concurrent_table& x_):x(x_)
|
||||
@@ -1539,10 +1679,10 @@ private:
|
||||
bool commit_=false;
|
||||
};
|
||||
|
||||
template<typename GroupAccessMode,typename F,typename... Args>
|
||||
template<typename GroupAccessMode,typename F1,typename F2,typename... Args>
|
||||
BOOST_FORCEINLINE int
|
||||
unprotected_norehash_emplace_or_visit(
|
||||
GroupAccessMode access_mode,F&& f,Args&&... args)
|
||||
unprotected_norehash_emplace_and_visit(
|
||||
GroupAccessMode access_mode,F1&& f1,F2&& f2,Args&&... args)
|
||||
{
|
||||
const auto &k=this->key_from(std::forward<Args>(args)...);
|
||||
auto hash=this->hash_for(k);
|
||||
@@ -1552,7 +1692,7 @@ private:
|
||||
startover:
|
||||
boost::uint32_t counter=insert_counter(pos0);
|
||||
if(unprotected_visit(
|
||||
access_mode,k,pos0,hash,std::forward<F>(f)))return 0;
|
||||
access_mode,k,pos0,hash,std::forward<F2>(f2)))return 0;
|
||||
|
||||
reserve_size rsize(*this);
|
||||
if(BOOST_LIKELY(rsize.succeeded())){
|
||||
@@ -1572,6 +1712,7 @@ private:
|
||||
this->construct_element(p,std::forward<Args>(args)...);
|
||||
rslot.commit();
|
||||
rsize.commit();
|
||||
f1(cast_for(group_exclusive{},type_policy::value_from(*p)));
|
||||
BOOST_UNORDERED_ADD_STATS(this->cstats.insertion,(pb.length()));
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright 2023 Joaquin M Lopez Munoz.
|
||||
/* Copyright 2023-2024 Joaquin M Lopez Munoz.
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
* http://www.boost.org/LICENSE_1_0.txt)
|
||||
@@ -19,27 +19,28 @@ namespace unordered{
|
||||
namespace detail{
|
||||
namespace foa{
|
||||
|
||||
template<typename Tuple>
|
||||
template<std::size_t Offset,typename Tuple>
|
||||
using tuple_rotate_right_return_type=mp11::mp_rotate_right_c<
|
||||
typename std::remove_cv<typename std::remove_reference<Tuple>::type>::type,
|
||||
1
|
||||
Offset
|
||||
>;
|
||||
|
||||
template<std::size_t... Is,typename Tuple>
|
||||
tuple_rotate_right_return_type<Tuple>
|
||||
template<std::size_t Offset,std::size_t... Is,typename Tuple>
|
||||
tuple_rotate_right_return_type<Offset,Tuple>
|
||||
tuple_rotate_right_aux(mp11::index_sequence<Is...>,Tuple&& x)
|
||||
{
|
||||
return tuple_rotate_right_return_type<Tuple>{
|
||||
std::get<(Is+sizeof...(Is)-1)%sizeof...(Is)>(std::forward<Tuple>(x))...};
|
||||
return tuple_rotate_right_return_type<Offset,Tuple>{
|
||||
std::get<(Is+sizeof...(Is)-Offset)%sizeof...(Is)>(
|
||||
std::forward<Tuple>(x))...};
|
||||
}
|
||||
|
||||
template<typename Tuple>
|
||||
tuple_rotate_right_return_type<Tuple> tuple_rotate_right(Tuple&& x)
|
||||
template<std::size_t Offset=1,typename Tuple>
|
||||
tuple_rotate_right_return_type<Offset,Tuple> tuple_rotate_right(Tuple&& x)
|
||||
{
|
||||
using RawTuple=typename std::remove_cv<
|
||||
typename std::remove_reference<Tuple>::type>::type;
|
||||
|
||||
return tuple_rotate_right_aux(
|
||||
return tuple_rotate_right_aux<Offset>(
|
||||
mp11::make_index_sequence<std::tuple_size<RawTuple>::value>{},
|
||||
std::forward<Tuple>(x));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user