Refactor table_iterator to avoid extraneous amounts of boost::to_address

This commit is contained in:
Christian Mazakas
2023-09-07 11:28:48 -07:00
parent 771943e291
commit c707bcb6d8

View File

@ -109,21 +109,21 @@ public:
table_iterator()=default; table_iterator()=default;
template<bool Const2,typename std::enable_if<!Const2>::type* =nullptr> template<bool Const2,typename std::enable_if<!Const2>::type* =nullptr>
table_iterator(const table_iterator<TypePolicy,GroupPtr,Const2>& x): table_iterator(const table_iterator<TypePolicy,GroupPtr,Const2>& x):
pc{x.pc},p{x.p}{} pc_{x.pc_},p_{x.p_}{}
table_iterator( table_iterator(
const_iterator_cast_tag, const table_iterator<TypePolicy,GroupPtr,true>& x): const_iterator_cast_tag, const table_iterator<TypePolicy,GroupPtr,true>& x):
pc{x.pc},p{x.p}{} pc_{x.pc_},p_{x.p_}{}
inline reference operator*()const noexcept inline reference operator*()const noexcept
{return type_policy::value_from(*p);} {return type_policy::value_from(*p());}
inline pointer operator->()const noexcept inline pointer operator->()const noexcept
{return std::addressof(type_policy::value_from(*p));} {return std::addressof(type_policy::value_from(*p()));}
inline table_iterator& operator++()noexcept{increment();return *this;} inline table_iterator& operator++()noexcept{increment();return *this;}
inline table_iterator operator++(int)noexcept inline table_iterator operator++(int)noexcept
{auto x=*this;increment();return x;} {auto x=*this;increment();return x;}
friend inline bool operator==( friend inline bool operator==(
const table_iterator& x,const table_iterator& y) const table_iterator& x,const table_iterator& y)
{return x.p==y.p;} {return x.p()==y.p();}
friend inline bool operator!=( friend inline bool operator!=(
const table_iterator& x,const table_iterator& y) const table_iterator& x,const table_iterator& y)
{return !(x==y);} {return !(x==y);}
@ -149,86 +149,91 @@ private:
return p; return p;
} }
table_iterator(group_type* pg,std::size_t n,const table_element_type* p_): table_iterator(group_type* pg,std::size_t n,const table_element_type* p):
pc{to_pointer<char_pointer>( pc_{to_pointer<char_pointer>(
reinterpret_cast<unsigned char*>(const_cast<group_type*>(pg))+n)}, reinterpret_cast<unsigned char*>(const_cast<group_type*>(pg))+n)},
p{to_pointer<table_element_pointer>(const_cast<table_element_type*>(p_))} p_{to_pointer<table_element_pointer>(const_cast<table_element_type*>(p))}
{} {}
unsigned char* pc()const noexcept{return boost::to_address(pc_);}
table_element_type* p()const noexcept{return boost::to_address(p_);}
inline void increment()noexcept inline void increment()noexcept
{ {
BOOST_ASSERT(p!=nullptr); BOOST_ASSERT(p()!=nullptr);
increment(std::integral_constant<bool,regular_layout>{}); increment(std::integral_constant<bool,regular_layout>{});
} }
inline void increment(std::true_type /* regular layout */)noexcept inline void increment(std::true_type /* regular layout */)noexcept
{ {
using diff_type=decltype(pc - pc); using diff_type=
typename boost::pointer_traits<char_pointer>::difference_type;
for(;;){ for(;;){
++p; ++p_;
if(reinterpret_cast<uintptr_t>(boost::to_address(pc))%sizeof(group_type)==N-1){ if(reinterpret_cast<uintptr_t>(pc())%sizeof(group_type)==N-1){
pc+=static_cast<diff_type>(sizeof(group_type)-(N-1)); pc_+=static_cast<diff_type>(sizeof(group_type)-(N-1));
break; break;
} }
++pc; ++pc_;
if(!group_type::is_occupied(boost::to_address(pc)))continue; if(!group_type::is_occupied(pc()))continue;
if(BOOST_UNLIKELY(group_type::is_sentinel(boost::to_address(pc))))p=nullptr; if(BOOST_UNLIKELY(group_type::is_sentinel(pc())))p_=nullptr;
return; return;
} }
for(;;){ for(;;){
int mask=reinterpret_cast<group_type*>(boost::to_address(pc))->match_occupied(); int mask=reinterpret_cast<group_type*>(pc())->match_occupied();
if(mask!=0){ if(mask!=0){
auto n=unchecked_countr_zero(mask); auto n=unchecked_countr_zero(mask);
if(BOOST_UNLIKELY(reinterpret_cast<group_type*>(boost::to_address(pc))->is_sentinel(n))){ if(BOOST_UNLIKELY(reinterpret_cast<group_type*>(pc())->is_sentinel(n))){
p=nullptr; p_=nullptr;
} }
else{ else{
pc+=static_cast<diff_type>(n); pc_+=static_cast<diff_type>(n);
p+=static_cast<diff_type>(n); p_+=static_cast<diff_type>(n);
} }
return; return;
} }
pc+=static_cast<diff_type>(sizeof(group_type)); pc_+=static_cast<diff_type>(sizeof(group_type));
p+=static_cast<diff_type>(N); p_+=static_cast<diff_type>(N);
} }
} }
inline void increment(std::false_type /* interleaved */)noexcept inline void increment(std::false_type /* interleaved */)noexcept
{ {
using diff_type=decltype(pc - pc); using diff_type=
typename boost::pointer_traits<char_pointer>::difference_type;
std::size_t n0=reinterpret_cast<uintptr_t>(boost::to_address(pc))%sizeof(group_type); std::size_t n0=reinterpret_cast<uintptr_t>(pc())%sizeof(group_type);
pc-=static_cast<diff_type>(n0); pc_-=static_cast<diff_type>(n0);
int mask=( int mask=(
reinterpret_cast<group_type*>(boost::to_address(pc))->match_occupied()>>(n0+1))<<(n0+1); reinterpret_cast<group_type*>(pc())->match_occupied()>>(n0+1))<<(n0+1);
if(!mask){ if(!mask){
do{ do{
pc+=sizeof(group_type); pc_+=sizeof(group_type);
p+=N; p_+=N;
} }
while((mask=reinterpret_cast<group_type*>(boost::to_address(pc))->match_occupied())==0); while((mask=reinterpret_cast<group_type*>(pc())->match_occupied())==0);
} }
auto n=unchecked_countr_zero(mask); auto n=unchecked_countr_zero(mask);
if(BOOST_UNLIKELY(reinterpret_cast<group_type*>(boost::to_address(pc))->is_sentinel(n))){ if(BOOST_UNLIKELY(reinterpret_cast<group_type*>(pc())->is_sentinel(n))){
p=nullptr; p_=nullptr;
} }
else{ else{
pc+=static_cast<diff_type>(n); pc_+=static_cast<diff_type>(n);
p-=static_cast<diff_type>(n0); p_-=static_cast<diff_type>(n0);
p+=static_cast<diff_type>(n); p_+=static_cast<diff_type>(n);
} }
} }
template<typename Archive> template<typename Archive>
friend void serialization_track(Archive& ar,const table_iterator& x) friend void serialization_track(Archive& ar,const table_iterator& x)
{ {
if(x.p){ if(x.p()){
track_address(ar,x.pc); track_address(ar,x.pc_);
track_address(ar,x.p); track_address(ar,x.p_);
} }
} }
@ -237,13 +242,13 @@ private:
template<typename Archive> template<typename Archive>
void serialize(Archive& ar,unsigned int) void serialize(Archive& ar,unsigned int)
{ {
if(!p)pc=nullptr; if(!p())pc_=nullptr;
serialize_tracked_address(ar,pc); serialize_tracked_address(ar,pc_);
serialize_tracked_address(ar,p); serialize_tracked_address(ar,p_);
} }
char_pointer pc=nullptr; char_pointer pc_=nullptr;
table_element_pointer p=nullptr; table_element_pointer p_=nullptr;
}; };
/* Returned by table::erase([const_]iterator) to avoid iterator increment /* Returned by table::erase([const_]iterator) to avoid iterator increment
@ -459,7 +464,7 @@ public:
BOOST_FORCEINLINE BOOST_FORCEINLINE
erase_return_type erase(const_iterator pos)noexcept erase_return_type erase(const_iterator pos)noexcept
{ {
super::erase(boost::to_address(pos.pc),boost::to_address(pos.p)); super::erase(pos.pc(),pos.p());
return {pos}; return {pos};
} }
@ -490,7 +495,7 @@ public:
BOOST_ASSERT(pos!=end()); BOOST_ASSERT(pos!=end());
erase_on_exit e{*this,pos}; erase_on_exit e{*this,pos};
(void)e; (void)e;
return std::move(*pos.p); return std::move(*pos.p());
} }
// TODO: should we accept different allocator too? // TODO: should we accept different allocator too?