From 1bae403d58e8960c4fd46151da38694f14ae7646 Mon Sep 17 00:00:00 2001 From: joaquintides Date: Sun, 21 Jan 2024 18:53:33 +0100 Subject: [PATCH] added node recycling --- .../unordered/detail/foa/concurrent_table.hpp | 63 ++++++++++++------- 1 file changed, 40 insertions(+), 23 deletions(-) diff --git a/include/boost/unordered/detail/foa/concurrent_table.hpp b/include/boost/unordered/detail/foa/concurrent_table.hpp index 757d896f..be528152 100644 --- a/include/boost/unordered/detail/foa/concurrent_table.hpp +++ b/include/boost/unordered/detail/foa/concurrent_table.hpp @@ -570,7 +570,7 @@ public: } std::cout - <<"version: 2024/01/13 13:10; " + <<"version: 2024/01/21 18:40; " <<"lf: "<<(double)size()/capacity()<<"; " <<"capacity: "<arrays.elements()+pos*N+n; - this->construct_element(p,std::forward(args)...); + auto pv=new_element(); + new (pv) value_type(std::forward(args)...); + p->p=pv; pg->set(n,hash); for(prober pb2(pos0);pb2.get()!=pos; pb2.next(this->arrays.groups_size_mask)){ @@ -2002,7 +2004,7 @@ private: retired_element(const retired_element&){} std::atomic epoch=available_; - std::atomic p; + std::atomic p={}; }; struct garbage_vector { @@ -2017,7 +2019,7 @@ private: retired_element* retired_elements; std::atomic wpos=0; std::atomic rpos=0; - std::atomic reading=false; + std::atomic apos=0; std::atomic size=0; std::atomic mcos=0; }; @@ -2044,8 +2046,7 @@ private: return e-1; } - BOOST_FORCEINLINE void - retire_element(value_type* p,bool mco) + BOOST_FORCEINLINE void retire_element(value_type* p,bool mco) { auto& v=local_garbage_vector(); if(++v.epoch_bump%garbage_vector::min_for_epoch_bump==0){ @@ -2058,21 +2059,43 @@ private: std::size_t expected=retired_element::available_; auto& e=v.retired_elements[wpos%v.garbage_vector::N]; if(e.epoch.compare_exchange_strong(expected,retired_element::reserved_)){ - e.p=p; + p=e.p.exchange(p); + if(p){ + element_type x{p}; + this->destroy_element(&x); + ++v.apos; + } e.epoch=v.epoch.load(); if(++v.wpos%garbage_vector::min_for_garbage_collection==0){ - garbage_collect(); + garbage_collect(v,max_safe_epoch()); } return; } if(expected==retired_element::reserved_){ /* other thread wrote */ } else{ /* vector full */ - garbage_collect(); + garbage_collect(v,max_safe_epoch()); } } } + BOOST_FORCEINLINE value_type* new_element() + { + auto& v=local_garbage_vector(); + for(;;){ + std::size_t apos=v.apos; + if(apos>=v.rpos)break; /*`no available elements*/ + auto pv=v.retired_elements[apos%v.garbage_vector::N].p.load(); + if(v.apos.compare_exchange_weak(apos,apos+1)){ + v.retired_elements[apos%v.garbage_vector::N].p=nullptr; + return pv; + } + } + + /* allocate */ + return boost::allocator_allocate(this->al(),1); + } + std::pair calculate_size_ctrl() { using ssize_t=std::make_signed::type; @@ -2114,21 +2137,15 @@ private: { if(v.rpos==v.wpos)return; - bool expected=false; - if(v.reading.compare_exchange_strong(expected,true)){ - std::size_t rpos=v.rpos; - for(;;){ - auto& e=v.retired_elements[rpos%v.garbage_vector::N]; - if(e.epoch>max_epoch)break; - //++garbage_collected; - element_type x{e.p.load()}; - this->destroy_element(&x); - e.epoch=retired_element::available_; - ++rpos; - } - v.rpos=rpos; - v.reading=false; + std::size_t rpos=v.rpos; + for(;;){ + auto& e=v.retired_elements[rpos%v.garbage_vector::N]; + if(e.epoch>max_epoch)break; + //++garbage_collected; + e.epoch=retired_element::available_; + ++rpos; } + v.rpos=rpos; } BOOST_NOINLINE void garbage_collect()