forked from boostorg/unordered
used two-stage ll/sc
This commit is contained in:
@@ -553,7 +553,7 @@ public:
|
|||||||
#if defined(BOOST_UNORDERED_LATCH_FREE)
|
#if defined(BOOST_UNORDERED_LATCH_FREE)
|
||||||
~concurrent_table(){
|
~concurrent_table(){
|
||||||
std::cout
|
std::cout
|
||||||
<<"version: 2024/02/12 13:40; "
|
<<"version: 2024/02/14 20:10; "
|
||||||
<<"lf: "<<(double)size()/capacity()<<"; "
|
<<"lf: "<<(double)size()/capacity()<<"; "
|
||||||
<<"size: "<<size()<<", "
|
<<"size: "<<size()<<", "
|
||||||
<<"capacity: "<<capacity()<<"; "
|
<<"capacity: "<<capacity()<<"; "
|
||||||
@@ -869,18 +869,15 @@ public:
|
|||||||
group_exclusive{},x,this->position_for(hash),hash,
|
group_exclusive{},x,this->position_for(hash),hash,
|
||||||
[&,this](group_type* pg,unsigned int n,element_type* p)
|
[&,this](group_type* pg,unsigned int n,element_type* p)
|
||||||
{
|
{
|
||||||
if(f(cast_for(group_shared{},type_policy::value_from(*p)))){
|
if(/*is_occupied(pg,n)&&*/
|
||||||
//pg->reset(n);
|
f(cast_for(group_shared{},type_policy::value_from(*p)))){
|
||||||
auto pc=reinterpret_cast<std::atomic<unsigned char>*>(pg)+n;
|
pg->reset(n);
|
||||||
auto c=pc->load(std::memory_order_relaxed);
|
|
||||||
if(c>1&&pc->compare_exchange_strong(c,0,std::memory_order_acq_rel)){
|
|
||||||
auto& sc=local_size_ctrl();
|
auto& sc=local_size_ctrl();
|
||||||
sc.size.fetch_sub(1,std::memory_order_relaxed);
|
sc.size.fetch_sub(1,std::memory_order_relaxed);
|
||||||
sc.mcos.fetch_add(
|
sc.mcos.fetch_add(
|
||||||
!pg->is_not_overflowed(hash),std::memory_order_relaxed);
|
!pg->is_not_overflowed(hash),std::memory_order_relaxed);
|
||||||
res=1;
|
res=1;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
});
|
});
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
@@ -1275,9 +1272,8 @@ private:
|
|||||||
#if defined(BOOST_UNORDERED_LATCH_FREE)
|
#if defined(BOOST_UNORDERED_LATCH_FREE)
|
||||||
static bool is_occupied(group_type* pg,std::size_t pos)
|
static bool is_occupied(group_type* pg,std::size_t pos)
|
||||||
{
|
{
|
||||||
//return reinterpret_cast<std::atomic<unsigned char>*>(pg)[pos].
|
return pg->is_occupied(pos);
|
||||||
// load(std::memory_order_acquire)>1;
|
//return true;
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
static bool is_occupied(group_type* pg,std::size_t pos)
|
static bool is_occupied(group_type* pg,std::size_t pos)
|
||||||
@@ -1355,13 +1351,23 @@ private:
|
|||||||
BOOST_UNORDERED_PREFETCH_ELEMENTS(p,N);
|
BOOST_UNORDERED_PREFETCH_ELEMENTS(p,N);
|
||||||
do{
|
do{
|
||||||
auto n=unchecked_countr_zero(mask);
|
auto n=unchecked_countr_zero(mask);
|
||||||
#if 0
|
#if 1
|
||||||
auto [e,acnt]=load_access(pos,[&]{return *(p+n);});
|
auto [pr,acnt]=load_access(pos,[&]{
|
||||||
|
return std::make_pair(is_occupied(pg,n),*(p+n));
|
||||||
|
});
|
||||||
|
auto [occupied,e]=pr;
|
||||||
|
if(!occupied)return 0;
|
||||||
if(BOOST_LIKELY(this->pred()(x,this->key_from(e)))){
|
if(BOOST_LIKELY(this->pred()(x,this->key_from(e)))){
|
||||||
if constexpr(std::is_same<GroupAccessMode,group_exclusive>::value){
|
if constexpr(std::is_same<GroupAccessMode,group_exclusive>::value){
|
||||||
// ALTERNATIVE: offline f(pg,n,&e)
|
// ALTERNATIVE: offline f(pg,n,&e)
|
||||||
|
|
||||||
if(!save_access(pos,acnt,[&]{f(pg,n,p+n);}))goto startover;
|
if(!save_access(pos,acnt,[&]{f(pg,n,p+n);})){
|
||||||
|
// SPECIFIC FOR erase: if the element changed, it can only be
|
||||||
|
// bc someone erased it.
|
||||||
|
// WATCH OUT: only approximate as acnt controls 15 elements,
|
||||||
|
// not just this one.
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}else{
|
}else{
|
||||||
f(pg,n,&e);
|
f(pg,n,&e);
|
||||||
@@ -1737,26 +1743,38 @@ private:
|
|||||||
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);
|
||||||
latch_free_reserve_slot rslot{pg,n};
|
//latch_free_reserve_slot rslot{pg,n};
|
||||||
if(BOOST_UNLIKELY(!rslot.succeeded())){
|
//if(BOOST_UNLIKELY(!rslot.succeeded())){
|
||||||
/* slot wasn't empty */
|
// /* slot wasn't empty */
|
||||||
goto startover;
|
// goto startover;
|
||||||
}
|
//}
|
||||||
if(BOOST_UNLIKELY(
|
//if(BOOST_UNLIKELY(
|
||||||
!insert_counter(pos0).compare_exchange_strong(
|
// !insert_counter(pos0).compare_exchange_strong(
|
||||||
counter,counter+1,std::memory_order_relaxed))){
|
// counter,counter+1,std::memory_order_relaxed))){
|
||||||
/* other thread inserted from pos0, need to start over */
|
// /* other thread inserted from pos0, need to start over */
|
||||||
goto startover;
|
// goto startover;
|
||||||
}
|
//}
|
||||||
{
|
{
|
||||||
assign_insert_counter_on_exit a{insert_counter(pos0),counter+2};
|
//assign_insert_counter_on_exit a{insert_counter(pos0),counter+2};
|
||||||
save_access(pos,[&]{
|
|
||||||
|
auto [ocuppied,acnt]=load_access(pos,[&]{return is_occupied(pg,n);});
|
||||||
|
if(ocuppied)goto startover;
|
||||||
|
|
||||||
|
|
||||||
|
auto res=false;
|
||||||
|
if(!save_access(pos,acnt,[&]{
|
||||||
|
if(insert_counter(pos0).compare_exchange_strong(
|
||||||
|
counter,counter+1,std::memory_order_relaxed)){
|
||||||
|
assign_insert_counter_on_exit a{
|
||||||
|
insert_counter(pos0),counter+2};
|
||||||
this->construct_element(
|
this->construct_element(
|
||||||
this->arrays.elements()+pos*N+n,std::forward<Args>(args)...);
|
this->arrays.elements()+pos*N+n,std::forward<Args>(args)...);
|
||||||
});
|
pg->set(n,hash);
|
||||||
pg->set(n,hash); // SHOULD GO INSIDE save_access?
|
res=true;
|
||||||
}
|
}
|
||||||
rslot.commit();
|
})||!res)goto startover;
|
||||||
|
}
|
||||||
|
//rslot.commit();
|
||||||
auto& sc=local_size_ctrl();
|
auto& sc=local_size_ctrl();
|
||||||
sc.size.fetch_add(1,std::memory_order_relaxed);
|
sc.size.fetch_add(1,std::memory_order_relaxed);
|
||||||
sc.mcos.fetch_sub(!pg->is_not_overflowed(hash),std::memory_order_relaxed);
|
sc.mcos.fetch_sub(!pg->is_not_overflowed(hash),std::memory_order_relaxed);
|
||||||
@@ -2086,6 +2104,7 @@ private:
|
|||||||
mutable std::array<local_size_ctrl_type,128> local_size_ctrls;
|
mutable std::array<local_size_ctrl_type,128> local_size_ctrls;
|
||||||
std::atomic<std::size_t> max_probe=default_max_probe;
|
std::atomic<std::size_t> max_probe=default_max_probe;
|
||||||
std::size_t rehashes=0;
|
std::size_t rehashes=0;
|
||||||
|
//unsigned char paddd[64];
|
||||||
|
|
||||||
local_size_ctrl_type& local_size_ctrl()const
|
local_size_ctrl_type& local_size_ctrl()const
|
||||||
{
|
{
|
||||||
|
Reference in New Issue
Block a user