implemented group_synchronized_shared mode for insertion

This commit is contained in:
joaquintides
2023-12-11 20:56:30 +01:00
parent b8d9605107
commit 5c21fa6d81

View File

@@ -1036,6 +1036,16 @@ private:
epoch_type& e; epoch_type& e;
}; };
struct group_synchronized_shared_lock_guard
{
group_synchronized_shared_lock_guard(
epoch_type& e_,group_access::shared_lock_guard&& lck_):
e{e_},lck{std::move(lck_)}{}
~group_synchronized_shared_lock_guard(){e=0;}
epoch_type& e;
group_access::shared_lock_guard lck;
};
struct group_exclusive_lock_guard struct group_exclusive_lock_guard
{ {
group_exclusive_lock_guard( group_exclusive_lock_guard(
@@ -1099,6 +1109,11 @@ private:
/* Tag-dispatched shared/exclusive group access */ /* Tag-dispatched shared/exclusive group access */
using group_shared=std::false_type; using group_shared=std::false_type;
#if defined(BOOST_UNORDERED_LATCH_FREE)
using group_synchronized_shared=int;
#endif
using group_exclusive=std::true_type; using group_exclusive=std::true_type;
inline group_shared_lock_guard access(group_shared,std::size_t pos)const inline group_shared_lock_guard access(group_shared,std::size_t pos)const
@@ -1112,6 +1127,16 @@ private:
#endif #endif
} }
#if defined(BOOST_UNORDERED_LATCH_FREE)
inline group_synchronized_shared_lock_guard access(
group_synchronized_shared,std::size_t pos)const
{
auto& e=garbage_vectors[thread_id()%garbage_vectors.size()].epoch;
e=current_epoch.load(std::memory_order_relaxed);
return {e,this->arrays.group_accesses()[pos].shared_access()};
}
#endif
inline group_exclusive_lock_guard access( inline group_exclusive_lock_guard access(
group_exclusive,std::size_t pos)const group_exclusive,std::size_t pos)const
{ {
@@ -1137,6 +1162,11 @@ private:
static inline const value_type& static inline const value_type&
cast_for(group_shared,value_type& x){return x;} cast_for(group_shared,value_type& x){return x;}
#if defined(BOOST_UNORDERED_LATCH_FREE)
static inline const value_type&
cast_for(group_synchronized_shared,value_type& x){return x;}
#endif
static inline typename std::conditional< static inline typename std::conditional<
std::is_same<key_type,value_type>::value, std::is_same<key_type,value_type>::value,
const value_type&, const value_type&,
@@ -1424,8 +1454,14 @@ private:
template<typename... Args> template<typename... Args>
BOOST_FORCEINLINE bool emplace_impl(Args&&... args) BOOST_FORCEINLINE bool emplace_impl(Args&&... args)
{ {
#if defined(BOOST_UNORDERED_LATCH_FREE)
return emplace_or_visit_impl(
group_synchronized_shared{},
[](const value_type&){},std::forward<Args>(args)...);
#else
return emplace_or_visit_impl( return emplace_or_visit_impl(
group_shared{},[](const value_type&){},std::forward<Args>(args)...); group_shared{},[](const value_type&){},std::forward<Args>(args)...);
#endif
} }
template<typename GroupAccessMode,typename F,typename... Args> template<typename GroupAccessMode,typename F,typename... Args>
@@ -1545,7 +1581,7 @@ private:
for(;;){ for(;;){
startover: startover:
boost::uint32_t counter=++insert_counter(pos0); boost::uint32_t counter=insert_counter(pos0);
if(unprotected_visit( if(unprotected_visit(
access_mode,k,pos0,hash,std::forward<F>(f)))return 0; access_mode,k,pos0,hash,std::forward<F>(f)))return 0;
@@ -1554,6 +1590,7 @@ private:
for(prober pb(pos0);;pb.next(this->arrays.groups_size_mask)){ for(prober pb(pos0);;pb.next(this->arrays.groups_size_mask)){
auto pos=pb.get(); auto pos=pb.get();
auto pg=this->arrays.groups()+pos; auto pg=this->arrays.groups()+pos;
auto lck=access(group_exclusive{},pos);
auto mask=pg->match_available(); auto mask=pg->match_available();
if(BOOST_LIKELY(mask!=0)){ if(BOOST_LIKELY(mask!=0)){
auto n=unchecked_countr_zero(mask); auto n=unchecked_countr_zero(mask);
@@ -1563,16 +1600,14 @@ private:
/* slot wasn't empty */ /* slot wasn't empty */
goto startover; goto startover;
} }
auto lck=access(group_exclusive{},pos0); auto p=this->arrays.elements()+pos*N+n;
reinterpret_cast<std::atomic<unsigned char>*>(pg)[n]. this->construct_element(p,std::forward<Args>(args)...);
load(std::memory_order_acquire); if(BOOST_UNLIKELY(insert_counter(pos0)++!=counter)){
if(BOOST_UNLIKELY(insert_counter(pos0)!=counter)){
/* other thread inserted from pos0, need to start over */ /* other thread inserted from pos0, need to start over */
this->destroy_element(p);
pg->reset(n); pg->reset(n);
goto startover; goto startover;
} }
auto p=this->arrays.elements()+pos*N+n;
this->construct_element(p,std::forward<Args>(args)...);
pg->set(n,hash); pg->set(n,hash);
rsize.commit(); rsize.commit();
return 1; return 1;