mirror of
https://github.com/boostorg/container.git
synced 2026-07-10 19:30:51 +02:00
Removed segmented iterator machinery
This commit is contained in:
@@ -80,20 +80,9 @@
|
||||
#include <emmintrin.h>
|
||||
#endif
|
||||
|
||||
#if !defined(BOOST_CONTAINER_NEST_NO_PDEP)
|
||||
# if defined(__BMI2__)
|
||||
# define BOOST_CONTAINER_NEST_HAS_PDEP
|
||||
# elif defined(BOOST_MSVC) && defined(__AVX2__) && (defined(_M_X64) || defined(_M_IX86))
|
||||
# define BOOST_CONTAINER_NEST_HAS_PDEP
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_CONTAINER_NEST_HAS_PDEP)
|
||||
# if defined(BOOST_MSVC)
|
||||
# include <intrin.h>
|
||||
# else
|
||||
# include <immintrin.h>
|
||||
# endif
|
||||
//_BitScanForward64 / _BitScanReverse64 used by the bit helpers below.
|
||||
#if defined(BOOST_MSVC) && (defined(_M_X64) || defined(_M_ARM64))
|
||||
# include <intrin.h>
|
||||
#endif
|
||||
|
||||
#ifdef __has_builtin
|
||||
@@ -233,11 +222,6 @@ std::pair< nest_iterator<ValuePointer, StoreDataInBlock, Prefetch>, F >
|
||||
, nest_iterator<ValuePointer, StoreDataInBlock, Prefetch>
|
||||
, F);
|
||||
|
||||
struct segmented_iterator_tag;
|
||||
|
||||
template<class Iterator>
|
||||
struct segmented_iterator_traits;
|
||||
|
||||
namespace nest_detail {
|
||||
|
||||
//////////////////////////////////////////////
|
||||
@@ -292,84 +276,6 @@ BOOST_CONTAINER_FORCEINLINE int unchecked_countl_zero(boost::uint64_t x)
|
||||
#endif
|
||||
}
|
||||
|
||||
// nth_set_bit: returns the bit-position of the nth set bit (0-indexed) in mask.
|
||||
// Precondition: popcount(mask) > n >= 0.
|
||||
//
|
||||
// Two implementations selected at compile time:
|
||||
// 1. BMI2 pdep + countr_zero (BOOST_CONTAINER_NEST_HAS_PDEP)
|
||||
// 2. Binary search using popcount (default fallback)
|
||||
//
|
||||
// The default fallback halves the 64-bit mask with popcount at each step
|
||||
// (branching variant). Define BOOST_CONTAINER_NEST_NTH_BIT_BRANCHLESS to
|
||||
// select a branchless arithmetic variant of the same algorithm.
|
||||
|
||||
#if defined(BOOST_CONTAINER_NEST_HAS_PDEP)
|
||||
|
||||
BOOST_CONTAINER_FORCEINLINE int nth_set_bit(boost::uint64_t mask, int n)
|
||||
{
|
||||
return unchecked_countr_zero(_pdep_u64(boost::uint64_t(1) << n, mask));
|
||||
}
|
||||
|
||||
#elif defined(BOOST_CONTAINER_NEST_NTH_BIT_BRANCHLESS)
|
||||
|
||||
inline int nth_set_bit(boost::uint64_t mask, int n)
|
||||
{
|
||||
int pos = 0;
|
||||
int c;
|
||||
|
||||
c = boost::core::popcount(boost::uint64_t(mask & boost::uint64_t(0x00000000FFFFFFFFu)));
|
||||
{ const int s = (n >= c); pos += s * 32; mask >>= unsigned(s * 32); n -= s * c; }
|
||||
|
||||
c = boost::core::popcount(boost::uint64_t(mask & boost::uint64_t(0x000000000000FFFFu)));
|
||||
{ const int s = (n >= c); pos += s * 16; mask >>= unsigned(s * 16); n -= s * c; }
|
||||
|
||||
c = boost::core::popcount(boost::uint64_t(mask & boost::uint64_t(0x00000000000000FFu)));
|
||||
{ const int s = (n >= c); pos += s * 8; mask >>= unsigned(s * 8); n -= s * c; }
|
||||
|
||||
c = boost::core::popcount(boost::uint64_t(mask & boost::uint64_t(0x000000000000000Fu)));
|
||||
{ const int s = (n >= c); pos += s * 4; mask >>= unsigned(s * 4); n -= s * c; }
|
||||
|
||||
c = boost::core::popcount(boost::uint64_t(mask & boost::uint64_t(0x0000000000000003u)));
|
||||
{ const int s = (n >= c); pos += s * 2; mask >>= unsigned(s * 2); n -= s * c; }
|
||||
|
||||
{ const int s = (n > 0); pos += s; mask >>= unsigned(s); }
|
||||
|
||||
return pos + unchecked_countr_zero(mask);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
inline int nth_set_bit(boost::uint64_t mask, int n)
|
||||
{
|
||||
int pos = 0;
|
||||
int c;
|
||||
|
||||
c = boost::core::popcount(boost::uint64_t(mask & boost::uint64_t(0x00000000FFFFFFFFu)));
|
||||
if (n >= c) { pos += 32; mask >>= 32; n -= c; }
|
||||
|
||||
c = boost::core::popcount(boost::uint64_t(mask & boost::uint64_t(0x000000000000FFFFu)));
|
||||
if (n >= c) { pos += 16; mask >>= 16; n -= c; }
|
||||
|
||||
c = boost::core::popcount(boost::uint64_t(mask & boost::uint64_t(0x00000000000000FFu)));
|
||||
if (n >= c) { pos += 8; mask >>= 8; n -= c; }
|
||||
|
||||
c = boost::core::popcount(boost::uint64_t(mask & boost::uint64_t(0x000000000000000Fu)));
|
||||
if (n >= c) { pos += 4; mask >>= 4; n -= c; }
|
||||
|
||||
c = boost::core::popcount(boost::uint64_t(mask & boost::uint64_t(0x0000000000000003u)));
|
||||
if (n >= c) { pos += 2; mask >>= 2; n -= c; }
|
||||
|
||||
if (n > 0) { pos += 1; mask >>= 1; }
|
||||
|
||||
return pos + unchecked_countr_zero(mask);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//////////////////////////////////////////////
|
||||
//
|
||||
@@ -872,7 +778,6 @@ public:
|
||||
private:
|
||||
template<class, bool, bool> friend class nest_iterator;
|
||||
template<class, class, class> friend class boost::container::nest;
|
||||
template<class> friend struct ::boost::container::segmented_iterator_traits;
|
||||
template<class VP, bool SDIB, bool Pf, class FF>
|
||||
friend std::pair< nest_iterator<VP, SDIB, Pf>, FF >
|
||||
for_each_while
|
||||
@@ -909,370 +814,6 @@ private:
|
||||
int n;
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////
|
||||
//
|
||||
// nest_local_iterator
|
||||
//
|
||||
//////////////////////////////////////////////
|
||||
|
||||
#define NEST_LOCAL_ITERATOR_FULL
|
||||
|
||||
#if defined(NEST_LOCAL_ITERATOR_FULL)
|
||||
template<class ValuePointer, bool StoreDataInBlock>
|
||||
class nest_local_iterator
|
||||
{
|
||||
typedef typename boost::intrusive::pointer_traits<ValuePointer>::element_type element_type;
|
||||
|
||||
typedef typename nest_detail::pointer_rebind<ValuePointer, void>::type void_pointer;
|
||||
typedef nest_detail::block_base<void_pointer> block_base_type;
|
||||
typedef typename nest_detail::pointer_rebind<ValuePointer,
|
||||
typename dtl::remove_const<element_type>::type>::type nonconst_pointer;
|
||||
typedef nest_detail::block<nonconst_pointer, StoreDataInBlock> block_type;
|
||||
typedef typename block_base_type::mask_type mask_type;
|
||||
|
||||
BOOST_STATIC_CONSTEXPR std::size_t N = block_base_type::N;
|
||||
BOOST_STATIC_CONSTEXPR mask_type full = block_base_type::full;
|
||||
BOOST_STATIC_CONSTEXPR mask_type full_l = (full << 1);
|
||||
|
||||
public:
|
||||
typedef typename dtl::remove_const<element_type>::type value_type;
|
||||
typedef typename boost::intrusive::pointer_traits<ValuePointer>::difference_type difference_type;
|
||||
typedef ValuePointer pointer;
|
||||
typedef element_type& reference;
|
||||
typedef std::random_access_iterator_tag iterator_category;
|
||||
|
||||
typedef typename nest_detail::pointer_rebind<ValuePointer, block_base_type>::type block_base_pointer;
|
||||
|
||||
nest_local_iterator() BOOST_NOEXCEPT
|
||||
: pbb(), n(0)
|
||||
{}
|
||||
|
||||
nest_local_iterator(block_base_pointer pbb_, int n_) BOOST_NOEXCEPT
|
||||
: pbb(pbb_), n(n_)
|
||||
{}
|
||||
|
||||
BOOST_CONTAINER_FORCEINLINE reference operator*() const BOOST_NOEXCEPT
|
||||
{ return static_cast<block_type&>(*pbb).data()[n]; }
|
||||
|
||||
BOOST_CONTAINER_FORCEINLINE pointer operator->() const BOOST_NOEXCEPT
|
||||
{ return static_cast<block_type&>(*pbb).data() + n; }
|
||||
|
||||
BOOST_CONTAINER_FORCEINLINE nest_local_iterator& operator++() BOOST_NOEXCEPT
|
||||
{
|
||||
BOOST_CONTAINER_ASSUME(n != (int)N);
|
||||
const mask_type m = pbb->mask & (full_l << n);
|
||||
n = m ? nest_detail::first_in_mask(m) : (int)N;
|
||||
return *this;
|
||||
}
|
||||
|
||||
BOOST_CONTAINER_FORCEINLINE nest_local_iterator operator++(int) BOOST_NOEXCEPT
|
||||
{ nest_local_iterator tmp(*this); ++*this; return tmp; }
|
||||
|
||||
BOOST_CONTAINER_FORCEINLINE nest_local_iterator& operator--() BOOST_NOEXCEPT
|
||||
{
|
||||
BOOST_CONTAINER_ASSUME(n != 0);
|
||||
const mask_type m = pbb->mask & (full >> (int(N) - n));
|
||||
n = nest_detail::last_in_mask(m);
|
||||
return *this;
|
||||
}
|
||||
|
||||
BOOST_CONTAINER_FORCEINLINE nest_local_iterator operator--(int) BOOST_NOEXCEPT
|
||||
{ nest_local_iterator tmp(*this); --*this; return tmp; }
|
||||
|
||||
// random-access: advance by k occupied slots
|
||||
BOOST_CONTAINER_FORCEINLINE nest_local_iterator& operator+=(difference_type k) BOOST_NOEXCEPT
|
||||
{
|
||||
const mask_type m = pbb->mask;
|
||||
const mask_type lo = (n == int(N)) ? full : ((mask_type(1) << n) - 1);
|
||||
const int idx = (int)boost::core::popcount(m & lo);
|
||||
const int target = idx + (int)k;
|
||||
const int total = (int)boost::core::popcount(m);
|
||||
BOOST_CONTAINER_ASSUME(target >= 0 && target <= total);
|
||||
n = (target >= total) ? (int)N : nest_detail::nth_set_bit(m, target);
|
||||
return *this;
|
||||
}
|
||||
|
||||
BOOST_CONTAINER_FORCEINLINE nest_local_iterator& operator-=(difference_type k) BOOST_NOEXCEPT
|
||||
{ return *this += (-k); }
|
||||
|
||||
BOOST_CONTAINER_FORCEINLINE
|
||||
friend nest_local_iterator operator+(nest_local_iterator it, difference_type k) BOOST_NOEXCEPT
|
||||
{ it += k; return it; }
|
||||
|
||||
BOOST_CONTAINER_FORCEINLINE
|
||||
friend nest_local_iterator operator+(difference_type k, nest_local_iterator it) BOOST_NOEXCEPT
|
||||
{ it += k; return it; }
|
||||
|
||||
BOOST_CONTAINER_FORCEINLINE
|
||||
friend nest_local_iterator operator-(nest_local_iterator it, difference_type k) BOOST_NOEXCEPT
|
||||
{ it -= k; return it; }
|
||||
|
||||
BOOST_CONTAINER_FORCEINLINE reference operator[](difference_type k) const BOOST_NOEXCEPT
|
||||
{ return *(*this + k); }
|
||||
|
||||
// equality
|
||||
BOOST_CONTAINER_FORCEINLINE
|
||||
friend bool operator==(const nest_local_iterator& x, const nest_local_iterator& y) BOOST_NOEXCEPT
|
||||
{ return x.n == y.n; }
|
||||
|
||||
BOOST_CONTAINER_FORCEINLINE
|
||||
friend bool operator!=(const nest_local_iterator& x, const nest_local_iterator& y) BOOST_NOEXCEPT
|
||||
{ return x.n != y.n; }
|
||||
|
||||
// ordering
|
||||
BOOST_CONTAINER_FORCEINLINE
|
||||
friend bool operator<(const nest_local_iterator& x, const nest_local_iterator& y) BOOST_NOEXCEPT
|
||||
{ return x.n < y.n; }
|
||||
|
||||
BOOST_CONTAINER_FORCEINLINE
|
||||
friend bool operator>(const nest_local_iterator& x, const nest_local_iterator& y) BOOST_NOEXCEPT
|
||||
{ return x.n > y.n; }
|
||||
|
||||
BOOST_CONTAINER_FORCEINLINE
|
||||
friend bool operator<=(const nest_local_iterator& x, const nest_local_iterator& y) BOOST_NOEXCEPT
|
||||
{ return x.n <= y.n; }
|
||||
|
||||
BOOST_CONTAINER_FORCEINLINE
|
||||
friend bool operator>=(const nest_local_iterator& x, const nest_local_iterator& y) BOOST_NOEXCEPT
|
||||
{ return x.n >= y.n; }
|
||||
|
||||
// distance
|
||||
BOOST_CONTAINER_FORCEINLINE
|
||||
friend difference_type operator-(const nest_local_iterator& x, const nest_local_iterator& y) BOOST_NOEXCEPT
|
||||
{
|
||||
BOOST_CONTAINER_ASSUME(x.pbb == y.pbb);
|
||||
#if 0 //Supporting negative difference would require additional checks
|
||||
const mask_type m = x.pbb->mask;
|
||||
const mask_type lo_x = (x.n == int(N)) ? full : ((mask_type(1) << x.n) - 1);
|
||||
const mask_type lo_y = (y.n == int(N)) ? full : ((mask_type(1) << y.n) - 1);
|
||||
return difference_type(boost::core::popcount(m & lo_x))
|
||||
- difference_type(boost::core::popcount(m & lo_y));
|
||||
#endif
|
||||
const mask_type lo_x = (x.n == int(N)) ? full : ((mask_type(1) << x.n) - 1);
|
||||
const mask_type lo_y = (y.n == int(N)) ? full : ((mask_type(1) << y.n) - 1);
|
||||
const mask_type m = x.pbb->mask;
|
||||
return boost::core::popcount(m & lo_x & (~lo_y));
|
||||
}
|
||||
|
||||
BOOST_CONTAINER_FORCEINLINE block_base_pointer get_block() const BOOST_NOEXCEPT { return pbb; }
|
||||
BOOST_CONTAINER_FORCEINLINE int get_slot() const BOOST_NOEXCEPT { return n; }
|
||||
|
||||
private:
|
||||
block_base_pointer pbb;
|
||||
int n;
|
||||
};
|
||||
|
||||
#else
|
||||
|
||||
template<class ValuePointer, bool StoreDataInBlock>
|
||||
class nest_local_iterator
|
||||
{
|
||||
typedef typename boost::intrusive::pointer_traits<ValuePointer>::element_type element_type;
|
||||
|
||||
typedef typename nest_detail::pointer_rebind<ValuePointer, void>::type void_pointer;
|
||||
typedef nest_detail::block_base<void_pointer> block_base_type;
|
||||
typedef typename nest_detail::pointer_rebind<ValuePointer,
|
||||
typename dtl::remove_const<element_type>::type>::type nonconst_pointer;
|
||||
typedef nest_detail::block<nonconst_pointer, StoreDataInBlock> block_type;
|
||||
typedef typename block_base_type::mask_type mask_type;
|
||||
|
||||
BOOST_STATIC_CONSTEXPR std::size_t N = block_base_type::N;
|
||||
BOOST_STATIC_CONSTEXPR mask_type full = block_base_type::full;
|
||||
BOOST_STATIC_CONSTEXPR mask_type full_l = (full << 1);
|
||||
|
||||
public:
|
||||
typedef typename dtl::remove_const<element_type>::type value_type;
|
||||
typedef typename boost::intrusive::pointer_traits<ValuePointer>::difference_type difference_type;
|
||||
typedef ValuePointer pointer;
|
||||
typedef element_type& reference;
|
||||
typedef std::random_access_iterator_tag iterator_category;
|
||||
|
||||
typedef typename nest_detail::pointer_rebind<ValuePointer, block_base_type>::type block_base_pointer;
|
||||
|
||||
nest_local_iterator() BOOST_NOEXCEPT
|
||||
: pos()
|
||||
{}
|
||||
|
||||
nest_local_iterator(block_base_pointer pbb_, int n_) BOOST_NOEXCEPT
|
||||
: pos(static_cast<block_type&>(*pbb_).data()+n_), n(n_), mask(pbb_->mask)
|
||||
{}
|
||||
|
||||
BOOST_CONTAINER_FORCEINLINE reference operator*() const BOOST_NOEXCEPT
|
||||
{ return *pos; }
|
||||
|
||||
BOOST_CONTAINER_FORCEINLINE pointer operator->() const BOOST_NOEXCEPT
|
||||
{ return pos; }
|
||||
|
||||
BOOST_CONTAINER_FORCEINLINE nest_local_iterator& operator++() BOOST_NOEXCEPT
|
||||
{
|
||||
BOOST_CONTAINER_ASSUME(n != (int)N);
|
||||
const mask_type m = mask & (full_l << n);
|
||||
const int old_n = n;
|
||||
n = m ? nest_detail::first_in_mask(m) : (int)N;
|
||||
pos += (n - old_n);
|
||||
return *this;
|
||||
}
|
||||
|
||||
BOOST_CONTAINER_FORCEINLINE nest_local_iterator operator++(int) BOOST_NOEXCEPT
|
||||
{ nest_local_iterator tmp(*this); ++*this; return tmp; }
|
||||
|
||||
BOOST_CONTAINER_FORCEINLINE nest_local_iterator& operator--() BOOST_NOEXCEPT
|
||||
{
|
||||
BOOST_CONTAINER_ASSUME(n != 0);
|
||||
const mask_type m = mask & (full >> (N - n));
|
||||
const int old_n = n;
|
||||
n = nest_detail::last_in_mask(m);
|
||||
pos -= (old_n - n);
|
||||
return *this;
|
||||
}
|
||||
|
||||
BOOST_CONTAINER_FORCEINLINE nest_local_iterator operator--(int) BOOST_NOEXCEPT
|
||||
{ nest_local_iterator tmp(*this); --*this; return tmp; }
|
||||
|
||||
// random-access: advance by k occupied slots
|
||||
BOOST_CONTAINER_FORCEINLINE nest_local_iterator& operator+=(difference_type k) BOOST_NOEXCEPT
|
||||
{
|
||||
const mask_type m = mask;
|
||||
const mask_type lo = (n == int(N)) ? full : ((mask_type(1) << n) - 1);
|
||||
const int idx = (int)boost::core::popcount(m & lo);
|
||||
const int target = idx + (int)k;
|
||||
const int total = (int)boost::core::popcount(m);
|
||||
BOOST_CONTAINER_ASSUME(target >= 0 && target <= total);
|
||||
const int old_n = n;
|
||||
n = (target >= total) ? (int)N : nest_detail::nth_set_bit(m, target);
|
||||
pos += (n - old_n);
|
||||
return *this;
|
||||
}
|
||||
|
||||
BOOST_CONTAINER_FORCEINLINE nest_local_iterator& operator-=(difference_type k) BOOST_NOEXCEPT
|
||||
{ return *this += (-k); }
|
||||
|
||||
BOOST_CONTAINER_FORCEINLINE
|
||||
friend nest_local_iterator operator+(nest_local_iterator it, difference_type k) BOOST_NOEXCEPT
|
||||
{ it += k; return it; }
|
||||
|
||||
BOOST_CONTAINER_FORCEINLINE
|
||||
friend nest_local_iterator operator+(difference_type k, nest_local_iterator it) BOOST_NOEXCEPT
|
||||
{ it += k; return it; }
|
||||
|
||||
BOOST_CONTAINER_FORCEINLINE
|
||||
friend nest_local_iterator operator-(nest_local_iterator it, difference_type k) BOOST_NOEXCEPT
|
||||
{ it -= k; return it; }
|
||||
|
||||
BOOST_CONTAINER_FORCEINLINE reference operator[](difference_type k) const BOOST_NOEXCEPT
|
||||
{ return *(*this + k); }
|
||||
|
||||
// equality
|
||||
BOOST_CONTAINER_FORCEINLINE
|
||||
friend bool operator==(const nest_local_iterator& x, const nest_local_iterator& y) BOOST_NOEXCEPT
|
||||
{ return x.n == y.n; }
|
||||
|
||||
BOOST_CONTAINER_FORCEINLINE
|
||||
friend bool operator!=(const nest_local_iterator& x, const nest_local_iterator& y) BOOST_NOEXCEPT
|
||||
{ return x.n != y.n; }
|
||||
|
||||
// ordering
|
||||
BOOST_CONTAINER_FORCEINLINE
|
||||
friend bool operator<(const nest_local_iterator& x, const nest_local_iterator& y) BOOST_NOEXCEPT
|
||||
{ return x.n < y.n; }
|
||||
|
||||
BOOST_CONTAINER_FORCEINLINE
|
||||
friend bool operator>(const nest_local_iterator& x, const nest_local_iterator& y) BOOST_NOEXCEPT
|
||||
{ return x.n > y.n; }
|
||||
|
||||
BOOST_CONTAINER_FORCEINLINE
|
||||
friend bool operator<=(const nest_local_iterator& x, const nest_local_iterator& y) BOOST_NOEXCEPT
|
||||
{ return x.n <= y.n; }
|
||||
|
||||
BOOST_CONTAINER_FORCEINLINE
|
||||
friend bool operator>=(const nest_local_iterator& x, const nest_local_iterator& y) BOOST_NOEXCEPT
|
||||
{ return x.n >= y.n; }
|
||||
|
||||
// distance
|
||||
BOOST_CONTAINER_FORCEINLINE
|
||||
friend difference_type operator-(const nest_local_iterator& x, const nest_local_iterator& y) BOOST_NOEXCEPT
|
||||
{
|
||||
BOOST_CONTAINER_ASSUME(x.mask == y.mask);
|
||||
#if 0
|
||||
const mask_type m = x.mask;
|
||||
const mask_type lo_x = (x.n == int(N)) ? full : ((mask_type(1) << x.n) - 1);
|
||||
const mask_type lo_y = (y.n == int(N)) ? full : ((mask_type(1) << y.n) - 1);
|
||||
return difference_type(boost::core::popcount(m & lo_x))
|
||||
- difference_type(boost::core::popcount(m & lo_y));
|
||||
#endif
|
||||
BOOST_CONTAINER_ASSUME(x.n >= y.n); // Undefined behavior otherwise
|
||||
const mask_type m = x.mask;
|
||||
const mask_type lo_x = (x.n == int(N)) ? full : ((mask_type(1) << x.n) - 1);
|
||||
const mask_type lo_y = (y.n == int(N)) ? full : ((mask_type(1) << y.n) - 1);
|
||||
return boost::core::popcount(m & lo_x & (~lo_y));
|
||||
}
|
||||
|
||||
//BOOST_CONTAINER_FORCEINLINE block_base_pointer get_block() const BOOST_NOEXCEPT { return pbb; }
|
||||
BOOST_CONTAINER_FORCEINLINE int get_slot() const BOOST_NOEXCEPT { return n; }
|
||||
|
||||
private:
|
||||
pointer pos;
|
||||
int n;
|
||||
mask_type mask;
|
||||
};
|
||||
|
||||
#endif //defined(NEST_LOCAL_ITERATOR_FULL)
|
||||
|
||||
//////////////////////////////////////////////
|
||||
//
|
||||
// nest_segment_iterator
|
||||
//
|
||||
//////////////////////////////////////////////
|
||||
|
||||
template<class ValuePointer>
|
||||
class nest_segment_iterator
|
||||
{
|
||||
typedef typename nest_detail::pointer_rebind<ValuePointer, void>::type void_pointer;
|
||||
typedef nest_detail::block_base<void_pointer> block_base_type;
|
||||
|
||||
public:
|
||||
typedef void value_type;
|
||||
typedef std::ptrdiff_t difference_type;
|
||||
typedef void pointer;
|
||||
typedef void reference;
|
||||
typedef std::bidirectional_iterator_tag iterator_category;
|
||||
|
||||
typedef typename nest_detail::pointer_rebind<ValuePointer, block_base_type>::type block_base_pointer;
|
||||
|
||||
nest_segment_iterator() BOOST_NOEXCEPT
|
||||
: pbb()
|
||||
{}
|
||||
|
||||
explicit nest_segment_iterator(block_base_pointer pbb_) BOOST_NOEXCEPT
|
||||
: pbb(pbb_)
|
||||
{}
|
||||
|
||||
BOOST_CONTAINER_FORCEINLINE nest_segment_iterator& operator++() BOOST_NOEXCEPT
|
||||
{ pbb = pbb->next; return *this; }
|
||||
|
||||
BOOST_CONTAINER_FORCEINLINE nest_segment_iterator operator++(int) BOOST_NOEXCEPT
|
||||
{ nest_segment_iterator tmp(*this); ++*this; return tmp; }
|
||||
|
||||
BOOST_CONTAINER_FORCEINLINE nest_segment_iterator& operator--() BOOST_NOEXCEPT
|
||||
{ pbb = pbb->prev; return *this; }
|
||||
|
||||
BOOST_CONTAINER_FORCEINLINE nest_segment_iterator operator--(int) BOOST_NOEXCEPT
|
||||
{ nest_segment_iterator tmp(*this); --*this; return tmp; }
|
||||
|
||||
BOOST_CONTAINER_FORCEINLINE friend bool operator==(
|
||||
const nest_segment_iterator& x, const nest_segment_iterator& y) BOOST_NOEXCEPT
|
||||
{ return x.pbb == y.pbb; }
|
||||
|
||||
BOOST_CONTAINER_FORCEINLINE friend bool operator!=(
|
||||
const nest_segment_iterator& x, const nest_segment_iterator& y) BOOST_NOEXCEPT
|
||||
{ return !(x == y); }
|
||||
|
||||
BOOST_CONTAINER_FORCEINLINE block_base_pointer get_block() const BOOST_NOEXCEPT { return pbb; }
|
||||
|
||||
private:
|
||||
block_base_pointer pbb;
|
||||
};
|
||||
|
||||
namespace nest_detail {
|
||||
|
||||
//////////////////////////////////////////////
|
||||
@@ -1565,71 +1106,6 @@ struct ref_predicate_adaptor
|
||||
|
||||
} // namespace nest_detail
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Specialization of segmented_iterator_traits for nest::iterator
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<class ValuePointer, bool StoreDataInBlock, bool Prefetch>
|
||||
struct segmented_iterator_traits
|
||||
< nest_iterator<ValuePointer, StoreDataInBlock, Prefetch> >
|
||||
{
|
||||
typedef segmented_iterator_tag is_segmented_iterator;
|
||||
typedef nest_iterator<ValuePointer, StoreDataInBlock, Prefetch> nest_iterator_type;
|
||||
typedef nest_local_iterator<ValuePointer, StoreDataInBlock> local_iterator;
|
||||
typedef nest_segment_iterator<ValuePointer> segment_iterator;
|
||||
|
||||
private:
|
||||
|
||||
typedef typename boost::intrusive::pointer_traits
|
||||
<ValuePointer>::element_type element_type;
|
||||
typedef typename dtl::remove_const<element_type>::type value_type;
|
||||
|
||||
typedef typename nest_detail::pointer_rebind<ValuePointer, void>::type void_pointer;
|
||||
typedef nest_detail::block_base<void_pointer> block_base_type;
|
||||
typedef typename nest_detail::pointer_rebind
|
||||
<ValuePointer, value_type>::type nonconst_pointer;
|
||||
typedef nest_detail::block<nonconst_pointer, StoreDataInBlock> block_type;
|
||||
typedef typename block_base_type::mask_type mask_type;
|
||||
|
||||
BOOST_STATIC_CONSTEXPR std::size_t N = block_base_type::N;
|
||||
|
||||
public:
|
||||
|
||||
BOOST_CONTAINER_FORCEINLINE static segment_iterator segment(const nest_iterator_type &it)
|
||||
{ return segment_iterator(it.pbb); }
|
||||
|
||||
BOOST_CONTAINER_FORCEINLINE static local_iterator local(const nest_iterator_type &it)
|
||||
{ return local_iterator(it.pbb, it.n); }
|
||||
|
||||
BOOST_CONTAINER_FORCEINLINE static nest_iterator_type compose(segment_iterator s, const local_iterator& l)
|
||||
{
|
||||
int n = l.get_slot();
|
||||
if (BOOST_UNLIKELY(n == N)) {
|
||||
++s;
|
||||
n = 0;
|
||||
}
|
||||
return nest_iterator_type(s.get_block(), n);
|
||||
}
|
||||
|
||||
BOOST_CONTAINER_FORCEINLINE static local_iterator begin(const segment_iterator &s)
|
||||
{
|
||||
typedef typename segment_iterator::block_base_pointer block_base_pointer;
|
||||
block_base_pointer const bp = s.get_block();
|
||||
const mask_type m = bp->mask;
|
||||
const int n = nest_detail::first_in_mask(m);
|
||||
//Prefetch the eact line the
|
||||
//returned local_iterator will dereference first instead of the
|
||||
//unconditional slot-0 line.
|
||||
BOOST_CONTAINER_NEST_PREFETCH_BLOCK_NTH(bp, n);
|
||||
return local_iterator(bp, n);
|
||||
}
|
||||
|
||||
BOOST_CONTAINER_FORCEINLINE static local_iterator end(const segment_iterator &s)
|
||||
{ return local_iterator(s.get_block(), int(N)); }
|
||||
};
|
||||
|
||||
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
|
||||
|
||||
template<class Options>
|
||||
|
||||
@@ -717,344 +717,6 @@ void test_initializer_list_operations()
|
||||
}
|
||||
#endif
|
||||
|
||||
void test_segment_iterator_operations()
|
||||
{
|
||||
typedef nest<int> nest_t;
|
||||
typedef nest_t::iterator iterator;
|
||||
typedef segmented_iterator_traits<iterator> traits;
|
||||
typedef traits::segment_iterator segment_iterator;
|
||||
typedef traits::local_iterator local_iterator;
|
||||
|
||||
nest_t h;
|
||||
for (int i = 0; i < 200; ++i)
|
||||
h.insert(i);
|
||||
|
||||
segment_iterator seg_begin = traits::segment(h.begin());
|
||||
segment_iterator seg_end = traits::segment(h.end());
|
||||
|
||||
// Default construction compiles
|
||||
{
|
||||
segment_iterator s;
|
||||
(void)s;
|
||||
}
|
||||
|
||||
// segment() + equality / inequality
|
||||
{
|
||||
segment_iterator s1 = traits::segment(h.begin());
|
||||
segment_iterator s2 = traits::segment(h.begin());
|
||||
BOOST_TEST(s1 == s2);
|
||||
BOOST_TEST(!(s1 != s2));
|
||||
BOOST_TEST(s1 != seg_end);
|
||||
BOOST_TEST(!(s1 == seg_end));
|
||||
}
|
||||
|
||||
// Pre-increment returns reference to self and advances
|
||||
{
|
||||
segment_iterator s = seg_begin;
|
||||
segment_iterator& ref = ++s;
|
||||
BOOST_TEST(&ref == &s);
|
||||
BOOST_TEST(s != seg_begin);
|
||||
BOOST_TEST(s != seg_end);
|
||||
}
|
||||
|
||||
// Post-increment returns old value and advances
|
||||
{
|
||||
segment_iterator s = seg_begin;
|
||||
segment_iterator old = s++;
|
||||
BOOST_TEST(old == seg_begin);
|
||||
segment_iterator expected = seg_begin;
|
||||
++expected;
|
||||
BOOST_TEST(s == expected);
|
||||
}
|
||||
|
||||
// Pre-decrement returns reference to self and retreats
|
||||
{
|
||||
segment_iterator s = seg_begin;
|
||||
++s;
|
||||
segment_iterator& ref = --s;
|
||||
BOOST_TEST(&ref == &s);
|
||||
BOOST_TEST(s == seg_begin);
|
||||
}
|
||||
|
||||
// Post-decrement returns old value and retreats
|
||||
{
|
||||
segment_iterator second = seg_begin;
|
||||
++second;
|
||||
segment_iterator old = second--;
|
||||
BOOST_TEST(second == seg_begin);
|
||||
segment_iterator expected = seg_begin;
|
||||
++expected;
|
||||
BOOST_TEST(old == expected);
|
||||
}
|
||||
|
||||
// Increment then decrement is identity
|
||||
{
|
||||
segment_iterator s = seg_begin;
|
||||
++s; ++s;
|
||||
--s; --s;
|
||||
BOOST_TEST(s == seg_begin);
|
||||
}
|
||||
|
||||
// Count segments (200 elements, 64 per block => at least 4 segments)
|
||||
{
|
||||
int num_segments = 0;
|
||||
for (segment_iterator s = seg_begin; s != seg_end; ++s)
|
||||
++num_segments;
|
||||
BOOST_TEST(num_segments >= 4);
|
||||
}
|
||||
|
||||
// Full segmented traversal yields all elements
|
||||
{
|
||||
int count = 0;
|
||||
segment_iterator s = seg_begin;
|
||||
local_iterator loc = traits::local(h.begin());
|
||||
while (s != seg_end) {
|
||||
local_iterator loc_end = traits::end(s);
|
||||
for (; loc != loc_end; ++loc)
|
||||
++count;
|
||||
++s;
|
||||
if (s != seg_end)
|
||||
loc = traits::begin(s);
|
||||
}
|
||||
BOOST_TEST_EQ(count, 200);
|
||||
}
|
||||
|
||||
// Reverse traversal over segments
|
||||
{
|
||||
int fwd_count = 0;
|
||||
for (segment_iterator s = seg_begin; s != seg_end; ++s)
|
||||
++fwd_count;
|
||||
|
||||
segment_iterator s = seg_end;
|
||||
int rev_count = 0;
|
||||
while (s != seg_begin) {
|
||||
--s;
|
||||
++rev_count;
|
||||
}
|
||||
BOOST_TEST_EQ(fwd_count, rev_count);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void test_local_iterator_operations()
|
||||
{
|
||||
typedef nest<int> nest_t;
|
||||
typedef nest_t::iterator iterator;
|
||||
typedef segmented_iterator_traits<iterator> traits;
|
||||
typedef traits::segment_iterator segment_iterator;
|
||||
typedef traits::local_iterator local_iterator;
|
||||
|
||||
// ---- Dense case (no gaps in bitmask) ----
|
||||
nest_t h;
|
||||
for (int i = 0; i < 200; ++i)
|
||||
h.insert(i);
|
||||
|
||||
segment_iterator seg = traits::segment(h.begin());
|
||||
|
||||
// Default construction compiles
|
||||
{
|
||||
local_iterator l;
|
||||
(void)l;
|
||||
}
|
||||
|
||||
// begin() / end() of a segment
|
||||
{
|
||||
local_iterator b = traits::begin(seg);
|
||||
local_iterator e = traits::end(seg);
|
||||
BOOST_TEST(b != e);
|
||||
}
|
||||
|
||||
// operator* dereference
|
||||
{
|
||||
local_iterator b = traits::begin(seg);
|
||||
int val = *b;
|
||||
(void)val;
|
||||
}
|
||||
|
||||
// operator-> returns valid pointer
|
||||
{
|
||||
local_iterator b = traits::begin(seg);
|
||||
BOOST_TEST(b.operator->() != 0);
|
||||
BOOST_TEST_EQ(*b.operator->(), *b);
|
||||
}
|
||||
|
||||
// Equality / inequality
|
||||
{
|
||||
local_iterator b1 = traits::begin(seg);
|
||||
local_iterator b2 = traits::begin(seg);
|
||||
local_iterator e = traits::end(seg);
|
||||
BOOST_TEST(b1 == b2);
|
||||
BOOST_TEST(!(b1 != b2));
|
||||
BOOST_TEST(b1 != e);
|
||||
BOOST_TEST(!(b1 == e));
|
||||
}
|
||||
|
||||
// Pre-increment returns reference to self and advances
|
||||
{
|
||||
local_iterator b = traits::begin(seg);
|
||||
local_iterator orig = b;
|
||||
local_iterator& ref = ++b;
|
||||
BOOST_TEST(&ref == &b);
|
||||
BOOST_TEST(b != orig);
|
||||
}
|
||||
|
||||
// Post-increment returns old value
|
||||
{
|
||||
local_iterator b = traits::begin(seg);
|
||||
local_iterator old = b++;
|
||||
BOOST_TEST(old == traits::begin(seg));
|
||||
local_iterator expected = traits::begin(seg);
|
||||
++expected;
|
||||
BOOST_TEST(b == expected);
|
||||
}
|
||||
|
||||
// Pre-decrement returns reference to self and retreats
|
||||
{
|
||||
local_iterator b = traits::begin(seg);
|
||||
local_iterator second = b;
|
||||
++second;
|
||||
local_iterator& ref = --second;
|
||||
BOOST_TEST(&ref == &second);
|
||||
BOOST_TEST(second == b);
|
||||
}
|
||||
|
||||
// Post-decrement returns old value
|
||||
{
|
||||
local_iterator b = traits::begin(seg);
|
||||
local_iterator second = b;
|
||||
++second;
|
||||
local_iterator old = second--;
|
||||
BOOST_TEST(second == b);
|
||||
local_iterator expected = b;
|
||||
++expected;
|
||||
BOOST_TEST(old == expected);
|
||||
}
|
||||
|
||||
// Increment then decrement is identity
|
||||
{
|
||||
local_iterator b = traits::begin(seg);
|
||||
++b; ++b; ++b;
|
||||
--b; --b; --b;
|
||||
BOOST_TEST(b == traits::begin(seg));
|
||||
}
|
||||
|
||||
// operator- (distance) on a dense (fully packed) block
|
||||
{
|
||||
local_iterator b = traits::begin(seg);
|
||||
local_iterator e = traits::end(seg);
|
||||
|
||||
int count = 0;
|
||||
for (local_iterator tmp = b; tmp != e; ++tmp)
|
||||
++count;
|
||||
|
||||
BOOST_TEST_EQ(e - b, count);
|
||||
BOOST_TEST_EQ(b - b, 0);
|
||||
BOOST_TEST_EQ(e - e, 0);
|
||||
|
||||
local_iterator second = b;
|
||||
++second;
|
||||
BOOST_TEST_EQ(second - b, 1);
|
||||
}
|
||||
|
||||
// operator- at intermediate positions
|
||||
{
|
||||
local_iterator b = traits::begin(seg);
|
||||
local_iterator it = b;
|
||||
for (int i = 0; i < 5; ++i) ++it;
|
||||
BOOST_TEST_EQ(it - b, 5);
|
||||
}
|
||||
|
||||
// compose() round-trip: compose(segment(it), local(it)) == it
|
||||
{
|
||||
iterator it = h.begin();
|
||||
segment_iterator s = traits::segment(it);
|
||||
local_iterator l = traits::local(it);
|
||||
iterator composed = traits::compose(s, l);
|
||||
BOOST_TEST(composed == it);
|
||||
BOOST_TEST_EQ(*composed, *it);
|
||||
}
|
||||
|
||||
// compose() round-trip after advancing the nest iterator
|
||||
{
|
||||
iterator it = h.begin();
|
||||
++it; ++it; ++it;
|
||||
segment_iterator s = traits::segment(it);
|
||||
local_iterator l = traits::local(it);
|
||||
iterator composed = traits::compose(s, l);
|
||||
BOOST_TEST(composed == it);
|
||||
BOOST_TEST_EQ(*composed, *it);
|
||||
}
|
||||
|
||||
// local() gives an iterator that dereferences to the same value
|
||||
{
|
||||
iterator it = h.begin();
|
||||
local_iterator l = traits::local(it);
|
||||
BOOST_TEST_EQ(*l, *it);
|
||||
}
|
||||
|
||||
// begin(seg) matches local(compose(seg, begin(seg)))
|
||||
{
|
||||
local_iterator b = traits::begin(seg);
|
||||
iterator it = traits::compose(seg, b);
|
||||
local_iterator l = traits::local(it);
|
||||
BOOST_TEST(l == b);
|
||||
}
|
||||
|
||||
// ---- Sparse case (gaps in bitmask after erasures) ----
|
||||
{
|
||||
nest_t h2;
|
||||
for (int i = 0; i < 128; ++i)
|
||||
h2.insert(i);
|
||||
|
||||
int remaining = 128;
|
||||
int erase_idx = 0;
|
||||
for (iterator it = h2.begin(); it != h2.end(); ) {
|
||||
if (erase_idx % 3 == 0) {
|
||||
it = h2.erase(it);
|
||||
--remaining;
|
||||
} else {
|
||||
++it;
|
||||
}
|
||||
++erase_idx;
|
||||
}
|
||||
BOOST_TEST_EQ(h2.size(), (nest_t::size_type)remaining);
|
||||
|
||||
segment_iterator s = traits::segment(h2.begin());
|
||||
segment_iterator s_end = traits::segment(h2.end());
|
||||
|
||||
int total_count = 0;
|
||||
local_iterator loc = traits::local(h2.begin());
|
||||
while (s != s_end) {
|
||||
local_iterator lb = traits::begin(s);
|
||||
local_iterator le = traits::end(s);
|
||||
|
||||
int seg_count = 0;
|
||||
for (local_iterator tmp = lb; tmp != le; ++tmp)
|
||||
++seg_count;
|
||||
|
||||
// operator- must match the manual count
|
||||
BOOST_TEST_EQ(le - lb, seg_count);
|
||||
BOOST_TEST_EQ(lb - lb, 0);
|
||||
|
||||
// Intermediate distances
|
||||
if (seg_count >= 4) {
|
||||
local_iterator mid = lb;
|
||||
++mid; ++mid; ++mid;
|
||||
BOOST_TEST_EQ(mid - lb, 3);
|
||||
BOOST_TEST_EQ(le - mid, seg_count - 3);
|
||||
}
|
||||
|
||||
for (; loc != le; ++loc)
|
||||
++total_count;
|
||||
|
||||
++s;
|
||||
if (s != s_end)
|
||||
loc = traits::begin(s);
|
||||
}
|
||||
BOOST_TEST_EQ(total_count, remaining);
|
||||
}
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
test_default_construction();
|
||||
@@ -1106,7 +768,5 @@ int main()
|
||||
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
|
||||
test_initializer_list_operations();
|
||||
#endif
|
||||
test_segment_iterator_operations();
|
||||
test_local_iterator_operations();
|
||||
return boost::report_errors();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user