forked from boostorg/unordered
refactored some more for future concurrent_table
This commit is contained in:
committed by
Christian Mazakas
parent
447306bfb9
commit
840ea1ce5c
@ -152,6 +152,8 @@ static constexpr std::size_t default_bucket_count=0;
|
|||||||
* "logical" 128-bit word, and so forth. With this layout, match can be
|
* "logical" 128-bit word, and so forth. With this layout, match can be
|
||||||
* implemented with 4 ANDs, 3 shifts, 2 XORs, 1 OR and 1 NOT.
|
* implemented with 4 ANDs, 3 shifts, 2 XORs, 1 OR and 1 NOT.
|
||||||
*
|
*
|
||||||
|
* TODO: Explain IntegralWrapper.
|
||||||
|
*
|
||||||
* group15 has no user-defined ctor so that it's a trivial type and can be
|
* group15 has no user-defined ctor so that it's a trivial type and can be
|
||||||
* initialized via memset etc. Where needed, group15::initialize sets the
|
* initialized via memset etc. Where needed, group15::initialize sets the
|
||||||
* metadata to all zeros.
|
* metadata to all zeros.
|
||||||
@ -242,6 +244,12 @@ struct group15
|
|||||||
_mm_cmpeq_epi8(w,_mm_setzero_si128()))&0x7FFF;
|
_mm_cmpeq_epi8(w,_mm_setzero_si128()))&0x7FFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline bool is_occupied(std::size_t pos)const
|
||||||
|
{
|
||||||
|
BOOST_ASSERT(pos<N);
|
||||||
|
return at(pos)!=available_;
|
||||||
|
}
|
||||||
|
|
||||||
static inline bool is_occupied(unsigned char* pc)noexcept
|
static inline bool is_occupied(unsigned char* pc)noexcept
|
||||||
{
|
{
|
||||||
return *reinterpret_cast<slot_type*>(pc)!=available_;
|
return *reinterpret_cast<slot_type*>(pc)!=available_;
|
||||||
@ -417,6 +425,12 @@ struct group15
|
|||||||
vdupq_n_u8(0)))&0x7FFF;
|
vdupq_n_u8(0)))&0x7FFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline bool is_occupied(std::size_t pos)const
|
||||||
|
{
|
||||||
|
BOOST_ASSERT(pos<N);
|
||||||
|
return at(pos)!=available_;
|
||||||
|
}
|
||||||
|
|
||||||
static inline bool is_occupied(unsigned char* pc)noexcept
|
static inline bool is_occupied(unsigned char* pc)noexcept
|
||||||
{
|
{
|
||||||
return *reinterpret_cast<slot_type*>(pc)!=available_;
|
return *reinterpret_cast<slot_type*>(pc)!=available_;
|
||||||
@ -594,6 +608,13 @@ struct group15
|
|||||||
return y&0x7FFF;
|
return y&0x7FFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline bool is_occupied(std::size_t pos)const
|
||||||
|
{
|
||||||
|
BOOST_ASSERT(pos<N);
|
||||||
|
boost::uint64_t x=m[0]|m[1];
|
||||||
|
return (x&(0x0001000100010001ull<<pos))!=0;
|
||||||
|
}
|
||||||
|
|
||||||
inline int match_occupied()const
|
inline int match_occupied()const
|
||||||
{
|
{
|
||||||
boost::uint64_t x=m[0]|m[1];
|
boost::uint64_t x=m[0]|m[1];
|
||||||
@ -1028,6 +1049,14 @@ struct table_locator
|
|||||||
|
|
||||||
struct try_emplace_args_t{};
|
struct try_emplace_args_t{};
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
union uninitialized_storage
|
||||||
|
{
|
||||||
|
T t_;
|
||||||
|
uninitialized_storage(){}
|
||||||
|
~uninitialized_storage(){}
|
||||||
|
};
|
||||||
|
|
||||||
/* table_core. The TypePolicy template parameter is used to generate
|
/* table_core. The TypePolicy template parameter is used to generate
|
||||||
* instantiations suitable for either maps or sets, and introduces non-standard
|
* instantiations suitable for either maps or sets, and introduces non-standard
|
||||||
* init_type and element_type:
|
* init_type and element_type:
|
||||||
@ -1130,8 +1159,8 @@ public:
|
|||||||
std::size_t n=default_bucket_count,const Hash& h_=Hash(),
|
std::size_t n=default_bucket_count,const Hash& h_=Hash(),
|
||||||
const Pred& pred_=Pred(),const Allocator& al_=Allocator()):
|
const Pred& pred_=Pred(),const Allocator& al_=Allocator()):
|
||||||
hash_base{empty_init,h_},pred_base{empty_init,pred_},
|
hash_base{empty_init,h_},pred_base{empty_init,pred_},
|
||||||
allocator_base{empty_init,al_},size_{0},arrays(new_arrays(n)),
|
allocator_base{empty_init,al_},arrays(new_arrays(n)),
|
||||||
ml{initial_max_load()}
|
ml{initial_max_load()},available{ml}
|
||||||
{}
|
{}
|
||||||
|
|
||||||
table_core(const table_core& x):
|
table_core(const table_core& x):
|
||||||
@ -1145,11 +1174,11 @@ public:
|
|||||||
hash_base{empty_init,std::move(x.h())},
|
hash_base{empty_init,std::move(x.h())},
|
||||||
pred_base{empty_init,std::move(x.pred())},
|
pred_base{empty_init,std::move(x.pred())},
|
||||||
allocator_base{empty_init,std::move(x.al())},
|
allocator_base{empty_init,std::move(x.al())},
|
||||||
size_{x.size_},arrays(x.arrays),ml{x.ml}
|
arrays(x.arrays),ml{x.ml},available{x.available}
|
||||||
{
|
{
|
||||||
x.size_=0;
|
|
||||||
x.arrays=x.new_arrays(0);
|
x.arrays=x.new_arrays(0);
|
||||||
x.ml=x.initial_max_load();
|
x.ml=x.initial_max_load();
|
||||||
|
x.available=x.ml;
|
||||||
}
|
}
|
||||||
|
|
||||||
table_core(const table_core& x,const Allocator& al_):
|
table_core(const table_core& x,const Allocator& al_):
|
||||||
@ -1162,9 +1191,9 @@ public:
|
|||||||
table_core{0,std::move(x.h()),std::move(x.pred()),al_}
|
table_core{0,std::move(x.h()),std::move(x.pred()),al_}
|
||||||
{
|
{
|
||||||
if(al()==x.al()){
|
if(al()==x.al()){
|
||||||
std::swap(size_,x.size_);
|
|
||||||
std::swap(arrays,x.arrays);
|
std::swap(arrays,x.arrays);
|
||||||
std::swap(ml,x.ml);
|
std::swap(ml,x.ml);
|
||||||
|
std::swap(available,x.available);
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
reserve(x.size());
|
reserve(x.size());
|
||||||
@ -1261,9 +1290,9 @@ public:
|
|||||||
if(pocma||al()==x.al()){
|
if(pocma||al()==x.al()){
|
||||||
reserve(0);
|
reserve(0);
|
||||||
move_assign_if<pocma>(al(),x.al());
|
move_assign_if<pocma>(al(),x.al());
|
||||||
swap(size_,x.size_);
|
|
||||||
swap(arrays,x.arrays);
|
swap(arrays,x.arrays);
|
||||||
swap(ml,x.ml);
|
swap(ml,x.ml);
|
||||||
|
swap(available,x.available);
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
/* noshrink: favor memory reuse over tightness */
|
/* noshrink: favor memory reuse over tightness */
|
||||||
@ -1289,7 +1318,7 @@ public:
|
|||||||
allocator_type get_allocator()const noexcept{return al();}
|
allocator_type get_allocator()const noexcept{return al();}
|
||||||
|
|
||||||
bool empty()const noexcept{return size()==0;}
|
bool empty()const noexcept{return size()==0;}
|
||||||
std::size_t size()const noexcept{return size_;}
|
std::size_t size()const noexcept{return ml-available;}
|
||||||
std::size_t max_size()const noexcept{return SIZE_MAX;}
|
std::size_t max_size()const noexcept{return SIZE_MAX;}
|
||||||
|
|
||||||
// TODO unify erase?
|
// TODO unify erase?
|
||||||
@ -1329,9 +1358,9 @@ public:
|
|||||||
|
|
||||||
swap(h(),x.h());
|
swap(h(),x.h());
|
||||||
swap(pred(),x.pred());
|
swap(pred(),x.pred());
|
||||||
swap(size_,x.size_);
|
|
||||||
swap(arrays,x.arrays);
|
swap(arrays,x.arrays);
|
||||||
swap(ml,x.ml);
|
swap(ml,x.ml);
|
||||||
|
swap(available,x.available);
|
||||||
}
|
}
|
||||||
|
|
||||||
void clear()noexcept
|
void clear()noexcept
|
||||||
@ -1349,8 +1378,8 @@ public:
|
|||||||
pg->initialize();
|
pg->initialize();
|
||||||
}
|
}
|
||||||
arrays.groups[arrays.groups_size_mask].set_sentinel();
|
arrays.groups[arrays.groups_size_mask].set_sentinel();
|
||||||
size_=0;
|
|
||||||
ml=initial_max_load();
|
ml=initial_max_load();
|
||||||
|
available=ml;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1493,7 +1522,7 @@ public:
|
|||||||
{
|
{
|
||||||
auto res=nosize_unchecked_emplace_at(
|
auto res=nosize_unchecked_emplace_at(
|
||||||
arrays,pos0,hash,std::forward<Args>(args)...);
|
arrays,pos0,hash,std::forward<Args>(args)...);
|
||||||
++size_;
|
--available;
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1512,7 +1541,7 @@ public:
|
|||||||
* ideal conditions, yielding F ~ 0.0165 ~ 1/61.
|
* ideal conditions, yielding F ~ 0.0165 ~ 1/61.
|
||||||
*/
|
*/
|
||||||
auto new_arrays_=new_arrays(std::size_t(
|
auto new_arrays_=new_arrays(std::size_t(
|
||||||
std::ceil(static_cast<float>(size_+size_/61+1)/mlf)));
|
std::ceil(static_cast<float>(size()+size()/61+1)/mlf)));
|
||||||
locator it;
|
locator it;
|
||||||
BOOST_TRY{
|
BOOST_TRY{
|
||||||
/* strong exception guarantee -> try insertion before rehash */
|
/* strong exception guarantee -> try insertion before rehash */
|
||||||
@ -1528,7 +1557,7 @@ public:
|
|||||||
|
|
||||||
/* new_arrays_ lifetime taken care of by unchecked_rehash */
|
/* new_arrays_ lifetime taken care of by unchecked_rehash */
|
||||||
unchecked_rehash(new_arrays_);
|
unchecked_rehash(new_arrays_);
|
||||||
++size_;
|
--available;
|
||||||
return it;
|
return it;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1595,9 +1624,9 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::size_t size_;
|
|
||||||
arrays_type arrays;
|
arrays_type arrays;
|
||||||
std::size_t ml;
|
std::size_t ml;
|
||||||
|
std::size_t available;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
template<typename,typename,typename,typename,typename>
|
template<typename,typename,typename,typename,typename>
|
||||||
@ -1660,7 +1689,7 @@ private:
|
|||||||
std::memcpy(
|
std::memcpy(
|
||||||
arrays.groups,x.arrays.groups,
|
arrays.groups,x.arrays.groups,
|
||||||
(arrays.groups_size_mask+1)*sizeof(group_type));
|
(arrays.groups_size_mask+1)*sizeof(group_type));
|
||||||
size_=x.size();
|
available=x.available;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1725,7 +1754,7 @@ private:
|
|||||||
*/
|
*/
|
||||||
ml-=group_type::maybe_caused_overflow(pc);
|
ml-=group_type::maybe_caused_overflow(pc);
|
||||||
group_type::reset(pc);
|
group_type::reset(pc);
|
||||||
--size_;
|
++available;
|
||||||
}
|
}
|
||||||
|
|
||||||
void recover_slot(group_type* pg,std::size_t pos)
|
void recover_slot(group_type* pg,std::size_t pos)
|
||||||
|
@ -190,14 +190,6 @@ private:
|
|||||||
table_element_type *p=nullptr;
|
table_element_type *p=nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <class T>
|
|
||||||
union uninitialized_storage
|
|
||||||
{
|
|
||||||
T t_;
|
|
||||||
uninitialized_storage(){}
|
|
||||||
~uninitialized_storage(){}
|
|
||||||
};
|
|
||||||
|
|
||||||
/* foa::table interface departs in a number of ways from that of C++ unordered
|
/* foa::table interface departs in a number of ways from that of C++ unordered
|
||||||
* associative containers because it's not for end-user consumption
|
* associative containers because it's not for end-user consumption
|
||||||
* (boost::unordered_[flat|node]_[map|set] wrappers complete it as
|
* (boost::unordered_[flat|node]_[map|set] wrappers complete it as
|
||||||
@ -508,7 +500,7 @@ private:
|
|||||||
if(it!=end()){
|
if(it!=end()){
|
||||||
return {it,false};
|
return {it,false};
|
||||||
}
|
}
|
||||||
if(BOOST_LIKELY(this->size_<this->ml)){
|
if(BOOST_LIKELY(this->available)){
|
||||||
return {
|
return {
|
||||||
make_iterator(
|
make_iterator(
|
||||||
this->unchecked_emplace_at(pos0,hash,std::forward<Args>(args)...)),
|
this->unchecked_emplace_at(pos0,hash,std::forward<Args>(args)...)),
|
||||||
|
Reference in New Issue
Block a user