Update table_iterators to store fancy pointers

This commit is contained in:
Christian Mazakas
2023-08-17 09:21:12 -07:00
parent 1d93fa12a2
commit c16a3f2a4a

View File

@ -81,12 +81,17 @@ class table;
/* internal conversion from const_iterator to iterator */ /* internal conversion from const_iterator to iterator */
struct const_iterator_cast_tag{}; struct const_iterator_cast_tag{};
template<typename TypePolicy,typename Group,bool Const> template<typename TypePolicy,typename GroupPtr,bool Const>
class table_iterator class table_iterator
{ {
using group_pointer_traits=boost::pointer_traits<GroupPtr>;
using type_policy=TypePolicy; using type_policy=TypePolicy;
using table_element_type=typename type_policy::element_type; using table_element_type=typename type_policy::element_type;
using group_type=Group; using group_type=typename group_pointer_traits::element_type;
using table_element_pointer=
typename group_pointer_traits::template rebind<table_element_type>;
using char_pointer=
typename group_pointer_traits::template rebind<unsigned char>;
static constexpr auto N=group_type::N; static constexpr auto N=group_type::N;
static constexpr auto regular_layout=group_type::regular_layout; static constexpr auto regular_layout=group_type::regular_layout;
@ -103,10 +108,10 @@ 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,Group,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,Group,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
@ -128,10 +133,21 @@ private:
template<typename> friend class table_erase_return_type; template<typename> friend class table_erase_return_type;
template<typename,typename,typename,typename> friend class table; template<typename,typename,typename,typename> friend class table;
table_iterator(Group* 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{reinterpret_cast<unsigned char*>(const_cast<group_type*>(pg))+n}, {
p{const_cast<table_element_type*>(p_)} if(pg)
{} {
using pointer_traits=boost::pointer_traits<char_pointer>;
pc=pointer_traits::pointer_to(
reinterpret_cast<unsigned char*>(const_cast<group_type*>(pg))[n]);
}
if(p_)
{
using pointer_traits=boost::pointer_traits<table_element_pointer>;
p=pointer_traits::pointer_to(*const_cast<table_element_type*>(p_));
}
}
inline void increment()noexcept inline void increment()noexcept
{ {
@ -141,59 +157,63 @@ private:
inline void increment(std::true_type /* regular layout */)noexcept inline void increment(std::true_type /* regular layout */)noexcept
{ {
using diff_type=decltype(pc - pc);
for(;;){ for(;;){
++p; ++p;
if(reinterpret_cast<uintptr_t>(pc)%sizeof(group_type)==N-1){ if(reinterpret_cast<uintptr_t>(boost::to_address(pc))%sizeof(group_type)==N-1){
pc+=sizeof(group_type)-(N-1); pc+=static_cast<diff_type>(sizeof(group_type)-(N-1));
break; break;
} }
++pc; ++pc;
if(!group_type::is_occupied(pc))continue; if(!group_type::is_occupied(boost::to_address(pc)))continue;
if(BOOST_UNLIKELY(group_type::is_sentinel(pc)))p=nullptr; if(BOOST_UNLIKELY(group_type::is_sentinel(boost::to_address(pc))))p=nullptr;
return; return;
} }
for(;;){ for(;;){
int mask=reinterpret_cast<group_type*>(pc)->match_occupied(); int mask=reinterpret_cast<group_type*>(boost::to_address(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*>(pc)->is_sentinel(n))){ if(BOOST_UNLIKELY(reinterpret_cast<group_type*>(boost::to_address(pc))->is_sentinel(n))){
p=nullptr; p=nullptr;
} }
else{ else{
pc+=n; pc+=static_cast<diff_type>(n);
p+=n; p+=static_cast<diff_type>(n);
} }
return; return;
} }
pc+=sizeof(group_type); pc+=static_cast<diff_type>(sizeof(group_type));
p+=N; p+=static_cast<diff_type>(N);
} }
} }
inline void increment(std::false_type /* interleaved */)noexcept inline void increment(std::false_type /* interleaved */)noexcept
{ {
std::size_t n0=reinterpret_cast<uintptr_t>(pc)%sizeof(group_type); using diff_type=decltype(pc - pc);
pc-=n0;
std::size_t n0=reinterpret_cast<uintptr_t>(boost::to_address(pc))%sizeof(group_type);
pc-=static_cast<diff_type>(n0);
int mask=( int mask=(
reinterpret_cast<group_type*>(pc)->match_occupied()>>(n0+1))<<(n0+1); reinterpret_cast<group_type*>(boost::to_address(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*>(pc)->match_occupied())==0); while((mask=reinterpret_cast<group_type*>(boost::to_address(pc))->match_occupied())==0);
} }
auto n=unchecked_countr_zero(mask); auto n=unchecked_countr_zero(mask);
if(BOOST_UNLIKELY(reinterpret_cast<group_type*>(pc)->is_sentinel(n))){ if(BOOST_UNLIKELY(reinterpret_cast<group_type*>(boost::to_address(pc))->is_sentinel(n))){
p=nullptr; p=nullptr;
} }
else{ else{
pc+=n; pc+=static_cast<diff_type>(n);
p-=n0; p-=static_cast<diff_type>(n0);
p+=n; p+=static_cast<diff_type>(n);
} }
} }
@ -216,8 +236,8 @@ private:
serialize_tracked_address(ar,p); serialize_tracked_address(ar,p);
} }
unsigned char *pc=nullptr; char_pointer pc=nullptr;
table_element_type *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
@ -227,11 +247,11 @@ private:
template<typename Iterator> template<typename Iterator>
class table_erase_return_type; class table_erase_return_type;
template<typename TypePolicy,typename Group,bool Const> template<typename TypePolicy,typename GroupPtr,bool Const>
class table_erase_return_type<table_iterator<TypePolicy,Group,Const>> class table_erase_return_type<table_iterator<TypePolicy,GroupPtr,Const>>
{ {
using iterator=table_iterator<TypePolicy,Group,Const>; using iterator=table_iterator<TypePolicy,GroupPtr,Const>;
using const_iterator=table_iterator<TypePolicy,Group,true>; using const_iterator=table_iterator<TypePolicy,GroupPtr,true>;
public: public:
/* can't delete it because VS in pre-C++17 mode needs to see it for RVO */ /* can't delete it because VS in pre-C++17 mode needs to see it for RVO */
@ -313,6 +333,9 @@ class table:table_core_impl<TypePolicy,Hash,Pred,Allocator>
using locator=typename super::locator; using locator=typename super::locator;
using compatible_concurrent_table= using compatible_concurrent_table=
concurrent_table<TypePolicy,Hash,Pred,Allocator>; concurrent_table<TypePolicy,Hash,Pred,Allocator>;
using group_type_pointer=typename boost::pointer_traits<
typename boost::allocator_pointer<Allocator>::type
>::template rebind<group_type>;
friend compatible_concurrent_table; friend compatible_concurrent_table;
public: public:
@ -324,7 +347,6 @@ public:
private: private:
static constexpr bool has_mutable_iterator= static constexpr bool has_mutable_iterator=
!std::is_same<key_type,value_type>::value; !std::is_same<key_type,value_type>::value;
public: public:
using hasher=typename super::hasher; using hasher=typename super::hasher;
using key_equal=typename super::key_equal; using key_equal=typename super::key_equal;
@ -335,10 +357,10 @@ public:
using const_reference=typename super::const_reference; using const_reference=typename super::const_reference;
using size_type=typename super::size_type; using size_type=typename super::size_type;
using difference_type=typename super::difference_type; using difference_type=typename super::difference_type;
using const_iterator=table_iterator<type_policy,group_type,true>; using const_iterator=table_iterator<type_policy,group_type_pointer,true>;
using iterator=typename std::conditional< using iterator=typename std::conditional<
has_mutable_iterator, has_mutable_iterator,
table_iterator<type_policy,group_type,false>, table_iterator<type_policy,group_type_pointer,false>,
const_iterator>::type; const_iterator>::type;
using erase_return_type=table_erase_return_type<iterator>; using erase_return_type=table_erase_return_type<iterator>;
@ -431,7 +453,7 @@ public:
BOOST_FORCEINLINE BOOST_FORCEINLINE
erase_return_type erase(const_iterator pos)noexcept erase_return_type erase(const_iterator pos)noexcept
{ {
super::erase(pos.pc,pos.p); super::erase(boost::to_address(pos.pc),boost::to_address(pos.p));
return {pos}; return {pos};
} }