mirror of
https://github.com/boostorg/unordered.git
synced 2025-07-30 03:17:15 +02:00
implemented [c]visit_(until|while)
This commit is contained in:
@ -355,6 +355,106 @@ namespace boost {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
template <class F> bool visit_until(F f)
|
||||||
|
{
|
||||||
|
BOOST_UNORDERED_STATIC_ASSERT_INVOCABLE(F)
|
||||||
|
return table_.visit_until(f);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class F> bool visit_until(F f) const
|
||||||
|
{
|
||||||
|
BOOST_UNORDERED_STATIC_ASSERT_CONST_INVOCABLE(F)
|
||||||
|
return table_.visit_until(f);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class F> bool cvisit_until(F f) const
|
||||||
|
{
|
||||||
|
BOOST_UNORDERED_STATIC_ASSERT_CONST_INVOCABLE(F)
|
||||||
|
return table_.cvisit_until(f);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(BOOST_UNORDERED_PARALLEL_ALGORITHMS)
|
||||||
|
template <class ExecPolicy, class F>
|
||||||
|
typename std::enable_if<detail::is_execution_policy<ExecPolicy>::value,
|
||||||
|
bool>::type
|
||||||
|
visit_until(ExecPolicy&& p, F f)
|
||||||
|
{
|
||||||
|
BOOST_UNORDERED_STATIC_ASSERT_INVOCABLE(F)
|
||||||
|
BOOST_UNORDERED_STATIC_ASSERT_EXEC_POLICY(ExecPolicy)
|
||||||
|
return table_.visit_until(p, f);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ExecPolicy, class F>
|
||||||
|
typename std::enable_if<detail::is_execution_policy<ExecPolicy>::value,
|
||||||
|
bool>::type
|
||||||
|
visit_until(ExecPolicy&& p, F f) const
|
||||||
|
{
|
||||||
|
BOOST_UNORDERED_STATIC_ASSERT_CONST_INVOCABLE(F)
|
||||||
|
BOOST_UNORDERED_STATIC_ASSERT_EXEC_POLICY(ExecPolicy)
|
||||||
|
return table_.visit_until(p, f);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ExecPolicy, class F>
|
||||||
|
typename std::enable_if<detail::is_execution_policy<ExecPolicy>::value,
|
||||||
|
bool>::type
|
||||||
|
cvisit_until(ExecPolicy&& p, F f) const
|
||||||
|
{
|
||||||
|
BOOST_UNORDERED_STATIC_ASSERT_CONST_INVOCABLE(F)
|
||||||
|
BOOST_UNORDERED_STATIC_ASSERT_EXEC_POLICY(ExecPolicy)
|
||||||
|
return table_.cvisit_until(p, f);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
template <class F> bool visit_while(F f)
|
||||||
|
{
|
||||||
|
BOOST_UNORDERED_STATIC_ASSERT_INVOCABLE(F)
|
||||||
|
return table_.visit_while(f);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class F> bool visit_while(F f) const
|
||||||
|
{
|
||||||
|
BOOST_UNORDERED_STATIC_ASSERT_CONST_INVOCABLE(F)
|
||||||
|
return table_.visit_while(f);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class F> bool cvisit_while(F f) const
|
||||||
|
{
|
||||||
|
BOOST_UNORDERED_STATIC_ASSERT_CONST_INVOCABLE(F)
|
||||||
|
return table_.cvisit_while(f);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(BOOST_UNORDERED_PARALLEL_ALGORITHMS)
|
||||||
|
template <class ExecPolicy, class F>
|
||||||
|
typename std::enable_if<detail::is_execution_policy<ExecPolicy>::value,
|
||||||
|
bool>::type
|
||||||
|
visit_while(ExecPolicy&& p, F f)
|
||||||
|
{
|
||||||
|
BOOST_UNORDERED_STATIC_ASSERT_INVOCABLE(F)
|
||||||
|
BOOST_UNORDERED_STATIC_ASSERT_EXEC_POLICY(ExecPolicy)
|
||||||
|
return table_.visit_while(p, f);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ExecPolicy, class F>
|
||||||
|
typename std::enable_if<detail::is_execution_policy<ExecPolicy>::value,
|
||||||
|
bool>::type
|
||||||
|
visit_while(ExecPolicy&& p, F f) const
|
||||||
|
{
|
||||||
|
BOOST_UNORDERED_STATIC_ASSERT_CONST_INVOCABLE(F)
|
||||||
|
BOOST_UNORDERED_STATIC_ASSERT_EXEC_POLICY(ExecPolicy)
|
||||||
|
return table_.visit_while(p, f);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ExecPolicy, class F>
|
||||||
|
typename std::enable_if<detail::is_execution_policy<ExecPolicy>::value,
|
||||||
|
bool>::type
|
||||||
|
cvisit_while(ExecPolicy&& p, F f) const
|
||||||
|
{
|
||||||
|
BOOST_UNORDERED_STATIC_ASSERT_CONST_INVOCABLE(F)
|
||||||
|
BOOST_UNORDERED_STATIC_ASSERT_EXEC_POLICY(ExecPolicy)
|
||||||
|
return table_.cvisit_while(p, f);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/// Modifiers
|
/// Modifiers
|
||||||
///
|
///
|
||||||
|
|
||||||
|
@ -539,6 +539,86 @@ public:
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
template<typename F> bool visit_until(F&& f)
|
||||||
|
{
|
||||||
|
return !visit_while([&](value_type& x){return !f(x);});
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename F> bool visit_until(F&& f)const
|
||||||
|
{
|
||||||
|
return !visit_while([&](const value_type& x){return !f(x);});
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename F> bool cvisit_until(F&& f)const
|
||||||
|
{
|
||||||
|
return visit_while(std::forward<F>(f));
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(BOOST_UNORDERED_PARALLEL_ALGORITHMS)
|
||||||
|
template<typename ExecutionPolicy,typename F>
|
||||||
|
bool visit_until(ExecutionPolicy&& policy,F&& f)
|
||||||
|
{
|
||||||
|
return !visit_while(
|
||||||
|
std::forward<ExecutionPolicy>(policy),
|
||||||
|
[&](value_type& x){return !f(x);});
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename ExecutionPolicy,typename F>
|
||||||
|
bool visit_until(ExecutionPolicy&& policy,F&& f)const
|
||||||
|
{
|
||||||
|
return !visit_while(
|
||||||
|
std::forward<ExecutionPolicy>(policy),
|
||||||
|
[&](const value_type& x){return !f(x);});
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename ExecutionPolicy,typename F>
|
||||||
|
bool cvisit_until(ExecutionPolicy&& policy,F&& f)const
|
||||||
|
{
|
||||||
|
return visit_until(
|
||||||
|
std::forward<ExecutionPolicy>(policy),std::forward<F>(f));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
template<typename F> bool visit_while(F&& f)
|
||||||
|
{
|
||||||
|
return visit_while_impl(group_exclusive{},std::forward<F>(f));
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename F> bool visit_while(F&& f)const
|
||||||
|
{
|
||||||
|
return visit_while_impl(group_shared{},std::forward<F>(f));
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename F> bool cvisit_while(F&& f)const
|
||||||
|
{
|
||||||
|
return visit_while(std::forward<F>(f));
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(BOOST_UNORDERED_PARALLEL_ALGORITHMS)
|
||||||
|
template<typename ExecutionPolicy,typename F>
|
||||||
|
bool visit_while(ExecutionPolicy&& policy,F&& f)
|
||||||
|
{
|
||||||
|
return visit_while_impl(
|
||||||
|
group_exclusive{},
|
||||||
|
std::forward<ExecutionPolicy>(policy),std::forward<F>(f));
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename ExecutionPolicy,typename F>
|
||||||
|
bool visit_while(ExecutionPolicy&& policy,F&& f)const
|
||||||
|
{
|
||||||
|
return visit_while_impl(
|
||||||
|
group_shared{},
|
||||||
|
std::forward<ExecutionPolicy>(policy),std::forward<F>(f));
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename ExecutionPolicy,typename F>
|
||||||
|
bool cvisit_while(ExecutionPolicy&& policy,F&& f)const
|
||||||
|
{
|
||||||
|
return visit_while(
|
||||||
|
std::forward<ExecutionPolicy>(policy),std::forward<F>(f));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
bool empty()const noexcept{return size()==0;}
|
bool empty()const noexcept{return size()==0;}
|
||||||
|
|
||||||
std::size_t size()const noexcept
|
std::size_t size()const noexcept
|
||||||
@ -970,6 +1050,29 @@ private:
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
template<typename GroupAccessMode,typename F>
|
||||||
|
bool visit_while_impl(GroupAccessMode access_mode,F&& f)const
|
||||||
|
{
|
||||||
|
auto lck=shared_access();
|
||||||
|
return for_all_elements_while(access_mode,[&](element_type* p){
|
||||||
|
return f(cast_for(access_mode,type_policy::value_from(*p)));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(BOOST_UNORDERED_PARALLEL_ALGORITHMS)
|
||||||
|
template<typename GroupAccessMode,typename ExecutionPolicy,typename F>
|
||||||
|
bool visit_while_impl(
|
||||||
|
GroupAccessMode access_mode,ExecutionPolicy&& policy,F&& f)const
|
||||||
|
{
|
||||||
|
auto lck=shared_access();
|
||||||
|
return for_all_elements_while(
|
||||||
|
access_mode,std::forward<ExecutionPolicy>(policy),
|
||||||
|
[&](element_type* p){
|
||||||
|
return f(cast_for(access_mode,type_policy::value_from(*p)));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
template<typename GroupAccessMode,typename Key,typename F>
|
template<typename GroupAccessMode,typename Key,typename F>
|
||||||
BOOST_FORCEINLINE std::size_t unprotected_visit(
|
BOOST_FORCEINLINE std::size_t unprotected_visit(
|
||||||
GroupAccessMode access_mode,
|
GroupAccessMode access_mode,
|
||||||
@ -1253,19 +1356,38 @@ private:
|
|||||||
template<typename GroupAccessMode,typename F>
|
template<typename GroupAccessMode,typename F>
|
||||||
auto for_all_elements(GroupAccessMode access_mode,F f)const
|
auto for_all_elements(GroupAccessMode access_mode,F f)const
|
||||||
->decltype(f(nullptr,0,nullptr),void())
|
->decltype(f(nullptr,0,nullptr),void())
|
||||||
|
{
|
||||||
|
for_all_elements_while(
|
||||||
|
access_mode,[&](group_type* pg,unsigned int n,element_type* p)
|
||||||
|
{f(pg,n,p);return true;});
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename GroupAccessMode,typename F>
|
||||||
|
auto for_all_elements_while(GroupAccessMode access_mode,F f)const
|
||||||
|
->decltype(f(nullptr),bool())
|
||||||
|
{
|
||||||
|
return for_all_elements_while(
|
||||||
|
access_mode,[&](group_type*,unsigned int,element_type* p){return f(p);});
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename GroupAccessMode,typename F>
|
||||||
|
auto for_all_elements_while(GroupAccessMode access_mode,F f)const
|
||||||
|
->decltype(f(nullptr,0,nullptr),bool())
|
||||||
{
|
{
|
||||||
auto p=this->arrays.elements;
|
auto p=this->arrays.elements;
|
||||||
if(!p)return;
|
if(p){
|
||||||
for(auto pg=this->arrays.groups,last=pg+this->arrays.groups_size_mask+1;
|
for(auto pg=this->arrays.groups,last=pg+this->arrays.groups_size_mask+1;
|
||||||
pg!=last;++pg,p+=N){
|
pg!=last;++pg,p+=N){
|
||||||
auto lck=access(access_mode,(std::size_t)(pg-this->arrays.groups));
|
auto lck=access(access_mode,(std::size_t)(pg-this->arrays.groups));
|
||||||
auto mask=this->match_really_occupied(pg,last);
|
auto mask=this->match_really_occupied(pg,last);
|
||||||
while(mask){
|
while(mask){
|
||||||
auto n=unchecked_countr_zero(mask);
|
auto n=unchecked_countr_zero(mask);
|
||||||
f(pg,n,p+n);
|
if(!f(pg,n,p+n))return false;
|
||||||
mask&=mask-1;
|
mask&=mask-1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(BOOST_UNORDERED_PARALLEL_ALGORITHMS)
|
#if defined(BOOST_UNORDERED_PARALLEL_ALGORITHMS)
|
||||||
@ -1289,10 +1411,10 @@ private:
|
|||||||
last=first+this->arrays.groups_size_mask+1;
|
last=first+this->arrays.groups_size_mask+1;
|
||||||
std::for_each(std::forward<ExecutionPolicy>(policy),first,last,
|
std::for_each(std::forward<ExecutionPolicy>(policy),first,last,
|
||||||
[&,this](group_type& g){
|
[&,this](group_type& g){
|
||||||
std::size_t pos=static_cast<std::size_t>(&g-first);
|
auto pos=static_cast<std::size_t>(&g-first);
|
||||||
auto p=this->arrays.elements+pos*N;
|
auto p=this->arrays.elements+pos*N;
|
||||||
auto lck=access(access_mode,pos);
|
auto lck=access(access_mode,pos);
|
||||||
auto mask=this->match_really_occupied(&g,last);
|
auto mask=this->match_really_occupied(&g,last);
|
||||||
while(mask){
|
while(mask){
|
||||||
auto n=unchecked_countr_zero(mask);
|
auto n=unchecked_countr_zero(mask);
|
||||||
f(&g,n,p+n);
|
f(&g,n,p+n);
|
||||||
@ -1301,6 +1423,29 @@ private:
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename GroupAccessMode,typename ExecutionPolicy,typename F>
|
||||||
|
bool for_all_elements_while(
|
||||||
|
GroupAccessMode access_mode,ExecutionPolicy&& policy,F f)const
|
||||||
|
{
|
||||||
|
if(!this->arrays.elements)return true;
|
||||||
|
auto first=this->arrays.groups,
|
||||||
|
last=first+this->arrays.groups_size_mask+1;
|
||||||
|
return std::all_of(std::forward<ExecutionPolicy>(policy),first,last,
|
||||||
|
[&,this](group_type& g){
|
||||||
|
auto pos=static_cast<std::size_t>(&g-first);
|
||||||
|
auto p=this->arrays.elements+pos*N;
|
||||||
|
auto lck=access(access_mode,pos);
|
||||||
|
auto mask=this->match_really_occupied(&g,last);
|
||||||
|
while(mask){
|
||||||
|
auto n=unchecked_countr_zero(mask);
|
||||||
|
if(!f(p+n))return false;
|
||||||
|
mask&=mask-1;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static std::atomic<std::size_t> thread_counter;
|
static std::atomic<std::size_t> thread_counter;
|
||||||
|
Reference in New Issue
Block a user