mirror of
https://github.com/boostorg/intrusive.git
synced 2025-08-02 14:04:36 +02:00
Rewritten hash semi-intrusive containers to improve compilation times and runtime performance. Added experimental "linear_buckets" option.
This commit is contained in:
@@ -3886,6 +3886,12 @@ to be inserted in intrusive containers are allocated using `std::vector` or `std
|
|||||||
|
|
||||||
[section:release_notes Release Notes]
|
[section:release_notes Release Notes]
|
||||||
|
|
||||||
|
[section:release_notes_boost_1_80_00 Boost 1.80 Release]
|
||||||
|
|
||||||
|
* Semi-intrusive hash containers rewritten to reduce compilation times and improve runtime performance.
|
||||||
|
|
||||||
|
[endsect]
|
||||||
|
|
||||||
[section:release_notes_boost_1_79_00 Boost 1.79 Release]
|
[section:release_notes_boost_1_79_00 Boost 1.79 Release]
|
||||||
|
|
||||||
* The library now compiles without warnings with GCC's -Wcast-align=strict
|
* The library now compiles without warnings with GCC's -Wcast-align=strict
|
||||||
|
@@ -52,37 +52,6 @@ class exception_disposer
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<class Container, class Disposer, class SizeType>
|
|
||||||
class exception_array_disposer
|
|
||||||
{
|
|
||||||
Container *cont_;
|
|
||||||
Disposer &disp_;
|
|
||||||
SizeType &constructed_;
|
|
||||||
|
|
||||||
exception_array_disposer(const exception_array_disposer&);
|
|
||||||
exception_array_disposer &operator=(const exception_array_disposer&);
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
exception_array_disposer
|
|
||||||
(Container &cont, Disposer &disp, SizeType &constructed)
|
|
||||||
: cont_(&cont), disp_(disp), constructed_(constructed)
|
|
||||||
{}
|
|
||||||
|
|
||||||
BOOST_INTRUSIVE_FORCEINLINE void release()
|
|
||||||
{ cont_ = 0; }
|
|
||||||
|
|
||||||
~exception_array_disposer()
|
|
||||||
{
|
|
||||||
SizeType n = constructed_;
|
|
||||||
if(cont_){
|
|
||||||
while(n--){
|
|
||||||
cont_[n].clear_and_dispose(disp_);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
} //namespace detail{
|
} //namespace detail{
|
||||||
} //namespace intrusive{
|
} //namespace intrusive{
|
||||||
} //namespace boost{
|
} //namespace boost{
|
||||||
|
@@ -26,7 +26,10 @@
|
|||||||
#include <boost/intrusive/pointer_traits.hpp>
|
#include <boost/intrusive/pointer_traits.hpp>
|
||||||
#include <boost/intrusive/detail/mpl.hpp>
|
#include <boost/intrusive/detail/mpl.hpp>
|
||||||
#include <boost/intrusive/trivial_value_traits.hpp>
|
#include <boost/intrusive/trivial_value_traits.hpp>
|
||||||
#include <boost/intrusive/slist.hpp> //make_slist
|
#include <boost/intrusive/detail/common_slist_algorithms.hpp>
|
||||||
|
#include <boost/intrusive/detail/iiterator.hpp>
|
||||||
|
#include <boost/intrusive/detail/slist_iterator.hpp>
|
||||||
|
#include <boost/move/detail/to_raw_pointer.hpp>
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
#include <climits>
|
#include <climits>
|
||||||
#include <boost/move/core.hpp>
|
#include <boost/move/core.hpp>
|
||||||
@@ -35,10 +38,20 @@
|
|||||||
namespace boost {
|
namespace boost {
|
||||||
namespace intrusive {
|
namespace intrusive {
|
||||||
|
|
||||||
template <class Slist>
|
template <class NodeTraits>
|
||||||
struct bucket_impl : public Slist
|
struct bucket_impl
|
||||||
|
: public NodeTraits::node
|
||||||
{
|
{
|
||||||
typedef Slist slist_type;
|
public:
|
||||||
|
typedef NodeTraits node_traits;
|
||||||
|
|
||||||
|
private:
|
||||||
|
typedef typename node_traits::node_ptr node_ptr;
|
||||||
|
typedef typename node_traits::const_node_ptr const_node_ptr;
|
||||||
|
|
||||||
|
typedef detail::common_slist_algorithms<NodeTraits> algo_t;
|
||||||
|
|
||||||
|
public:
|
||||||
BOOST_INTRUSIVE_FORCEINLINE bucket_impl()
|
BOOST_INTRUSIVE_FORCEINLINE bucket_impl()
|
||||||
{}
|
{}
|
||||||
|
|
||||||
@@ -46,68 +59,22 @@ struct bucket_impl : public Slist
|
|||||||
{}
|
{}
|
||||||
|
|
||||||
BOOST_INTRUSIVE_FORCEINLINE ~bucket_impl()
|
BOOST_INTRUSIVE_FORCEINLINE ~bucket_impl()
|
||||||
{
|
{}
|
||||||
//This bucket is still being used!
|
|
||||||
BOOST_INTRUSIVE_INVARIANT_ASSERT(Slist::empty());
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOST_INTRUSIVE_FORCEINLINE bucket_impl &operator=(const bucket_impl&)
|
BOOST_INTRUSIVE_FORCEINLINE bucket_impl &operator=(const bucket_impl&)
|
||||||
{
|
{ return *this; }
|
||||||
//This bucket is still in use!
|
|
||||||
BOOST_INTRUSIVE_INVARIANT_ASSERT(Slist::empty());
|
BOOST_INTRUSIVE_FORCEINLINE node_ptr get_node_ptr()
|
||||||
return *this;
|
{ return pointer_traits<node_ptr>::pointer_to(*this); }
|
||||||
}
|
|
||||||
|
BOOST_INTRUSIVE_FORCEINLINE const_node_ptr get_node_ptr() const
|
||||||
|
{ return pointer_traits<const_node_ptr>::pointer_to(*this); }
|
||||||
|
|
||||||
|
BOOST_INTRUSIVE_FORCEINLINE node_ptr begin_ptr()
|
||||||
|
{ return node_traits::get_next(get_node_ptr()); }
|
||||||
};
|
};
|
||||||
|
|
||||||
template<class Slist>
|
|
||||||
struct bucket_traits_impl
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
BOOST_COPYABLE_AND_MOVABLE(bucket_traits_impl)
|
|
||||||
|
|
||||||
public:
|
|
||||||
/// @cond
|
|
||||||
|
|
||||||
typedef typename pointer_traits
|
|
||||||
<typename Slist::pointer>::template rebind_pointer
|
|
||||||
< bucket_impl<Slist> >::type bucket_ptr;
|
|
||||||
typedef Slist slist;
|
|
||||||
typedef typename Slist::size_type size_type;
|
|
||||||
/// @endcond
|
|
||||||
|
|
||||||
BOOST_INTRUSIVE_FORCEINLINE bucket_traits_impl(bucket_ptr buckets, size_type len)
|
|
||||||
: buckets_(buckets), buckets_len_(len)
|
|
||||||
{}
|
|
||||||
|
|
||||||
BOOST_INTRUSIVE_FORCEINLINE bucket_traits_impl(const bucket_traits_impl &x)
|
|
||||||
: buckets_(x.buckets_), buckets_len_(x.buckets_len_)
|
|
||||||
{}
|
|
||||||
|
|
||||||
BOOST_INTRUSIVE_FORCEINLINE bucket_traits_impl(BOOST_RV_REF(bucket_traits_impl) x)
|
|
||||||
: buckets_(x.buckets_), buckets_len_(x.buckets_len_)
|
|
||||||
{ x.buckets_ = bucket_ptr(); x.buckets_len_ = 0; }
|
|
||||||
|
|
||||||
BOOST_INTRUSIVE_FORCEINLINE bucket_traits_impl& operator=(BOOST_RV_REF(bucket_traits_impl) x)
|
|
||||||
{
|
|
||||||
buckets_ = x.buckets_; buckets_len_ = x.buckets_len_;
|
|
||||||
x.buckets_ = bucket_ptr(); x.buckets_len_ = 0; return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOST_INTRUSIVE_FORCEINLINE bucket_traits_impl& operator=(BOOST_COPY_ASSIGN_REF(bucket_traits_impl) x)
|
|
||||||
{
|
|
||||||
buckets_ = x.buckets_; buckets_len_ = x.buckets_len_; return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOST_INTRUSIVE_FORCEINLINE bucket_ptr bucket_begin() const
|
|
||||||
{ return buckets_; }
|
|
||||||
|
|
||||||
BOOST_INTRUSIVE_FORCEINLINE size_type bucket_count() const BOOST_NOEXCEPT
|
|
||||||
{ return buckets_len_; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
bucket_ptr buckets_;
|
|
||||||
size_type buckets_len_;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <class NodeTraits>
|
template <class NodeTraits>
|
||||||
struct hash_reduced_slist_node_traits
|
struct hash_reduced_slist_node_traits
|
||||||
@@ -133,22 +100,7 @@ struct reduced_slist_node_traits
|
|||||||
>::type type;
|
>::type type;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<class NodeTraits>
|
template<class BucketValueTraits, bool LinearBuckets, bool IsConst>
|
||||||
struct get_slist_impl
|
|
||||||
{
|
|
||||||
typedef trivial_value_traits<NodeTraits, normal_link> trivial_traits;
|
|
||||||
|
|
||||||
//Reducing symbol length
|
|
||||||
struct type : make_slist
|
|
||||||
< typename NodeTraits::node
|
|
||||||
, boost::intrusive::value_traits<trivial_traits>
|
|
||||||
, boost::intrusive::constant_time_size<false>
|
|
||||||
, boost::intrusive::size_type<std::size_t>
|
|
||||||
>::type
|
|
||||||
{};
|
|
||||||
};
|
|
||||||
|
|
||||||
template<class BucketValueTraits, bool IsConst>
|
|
||||||
class hashtable_iterator
|
class hashtable_iterator
|
||||||
{
|
{
|
||||||
typedef typename BucketValueTraits::value_traits value_traits;
|
typedef typename BucketValueTraits::value_traits value_traits;
|
||||||
@@ -166,24 +118,25 @@ class hashtable_iterator
|
|||||||
private:
|
private:
|
||||||
typedef typename value_traits::node_traits node_traits;
|
typedef typename value_traits::node_traits node_traits;
|
||||||
typedef typename node_traits::node_ptr node_ptr;
|
typedef typename node_traits::node_ptr node_ptr;
|
||||||
typedef typename get_slist_impl
|
typedef typename BucketValueTraits::bucket_type bucket_type;
|
||||||
< typename reduced_slist_node_traits
|
typedef typename bucket_type::node_traits slist_node_traits;
|
||||||
<node_traits>::type >::type slist_impl;
|
typedef typename slist_node_traits::node_ptr slist_node_ptr;
|
||||||
typedef typename slist_impl::iterator siterator;
|
typedef trivial_value_traits
|
||||||
typedef typename slist_impl::const_iterator const_siterator;
|
<slist_node_traits, normal_link> slist_value_traits;
|
||||||
typedef bucket_impl<slist_impl> bucket_type;
|
typedef slist_iterator<slist_value_traits, false> siterator;
|
||||||
|
typedef slist_iterator<slist_value_traits, true> const_siterator;
|
||||||
|
typedef circular_slist_algorithms<slist_node_traits> slist_node_algorithms;
|
||||||
|
|
||||||
typedef typename pointer_traits
|
typedef typename pointer_traits
|
||||||
<pointer>::template rebind_pointer
|
<pointer>::template rebind_pointer
|
||||||
< const BucketValueTraits >::type const_bucketvaltraits_ptr;
|
< const BucketValueTraits >::type const_bucketvaltraits_ptr;
|
||||||
typedef typename slist_impl::size_type size_type;
|
|
||||||
class nat;
|
class nat;
|
||||||
typedef typename
|
typedef typename
|
||||||
detail::if_c< IsConst
|
detail::if_c< IsConst
|
||||||
, hashtable_iterator<BucketValueTraits, false>
|
, hashtable_iterator<BucketValueTraits, LinearBuckets, false>
|
||||||
, nat>::type nonconst_iterator;
|
, nat>::type nonconst_iterator;
|
||||||
|
|
||||||
BOOST_INTRUSIVE_FORCEINLINE static node_ptr downcast_bucket(typename bucket_type::node_ptr p)
|
BOOST_INTRUSIVE_FORCEINLINE static node_ptr downcast_bucket(typename bucket_type::node_traits::node_ptr p)
|
||||||
{
|
{
|
||||||
return pointer_traits<node_ptr>::
|
return pointer_traits<node_ptr>::
|
||||||
pointer_to(static_cast<typename node_traits::node&>(*p));
|
pointer_to(static_cast<typename node_traits::node&>(*p));
|
||||||
@@ -211,8 +164,8 @@ class hashtable_iterator
|
|||||||
BOOST_INTRUSIVE_FORCEINLINE const siterator &slist_it() const
|
BOOST_INTRUSIVE_FORCEINLINE const siterator &slist_it() const
|
||||||
{ return slist_it_; }
|
{ return slist_it_; }
|
||||||
|
|
||||||
BOOST_INTRUSIVE_FORCEINLINE hashtable_iterator<BucketValueTraits, false> unconst() const
|
BOOST_INTRUSIVE_FORCEINLINE hashtable_iterator<BucketValueTraits, LinearBuckets, false> unconst() const
|
||||||
{ return hashtable_iterator<BucketValueTraits, false>(this->slist_it(), this->get_bucket_value_traits()); }
|
{ return hashtable_iterator<BucketValueTraits, LinearBuckets, false>(this->slist_it(), this->get_bucket_value_traits()); }
|
||||||
|
|
||||||
BOOST_INTRUSIVE_FORCEINLINE hashtable_iterator& operator++()
|
BOOST_INTRUSIVE_FORCEINLINE hashtable_iterator& operator++()
|
||||||
{ this->increment(); return *this; }
|
{ this->increment(); return *this; }
|
||||||
@@ -252,33 +205,36 @@ class hashtable_iterator
|
|||||||
{ return traitsptr_->priv_bucket_traits(); }
|
{ return traitsptr_->priv_bucket_traits(); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
void increment()
|
void increment()
|
||||||
{
|
{
|
||||||
const bucket_traits &rbuck_traits = this->priv_bucket_traits();
|
const bucket_traits &rbuck_traits = this->priv_bucket_traits();
|
||||||
bucket_type* const buckets = boost::movelib::to_raw_pointer(rbuck_traits.bucket_begin());
|
bucket_type* const buckets = boost::movelib::to_raw_pointer(rbuck_traits.bucket_begin());
|
||||||
const size_type buckets_len = rbuck_traits.bucket_count();
|
const std::size_t buckets_len = rbuck_traits.bucket_count();
|
||||||
|
|
||||||
++slist_it_;
|
++slist_it_;
|
||||||
const typename slist_impl::node_ptr n = slist_it_.pointed_node();
|
const slist_node_ptr n = slist_it_.pointed_node();
|
||||||
const siterator first_bucket_bbegin = buckets->end();
|
const siterator first_bucket_bbegin(buckets->get_node_ptr());
|
||||||
if(first_bucket_bbegin.pointed_node() <= n && n <= buckets[buckets_len-1].cend().pointed_node()){
|
if(first_bucket_bbegin.pointed_node() <= n && n <= buckets[buckets_len-1].get_node_ptr()){
|
||||||
//If one-past the node is inside the bucket then look for the next non-empty bucket
|
//If one-past the node is inside the bucket then look for the next non-empty bucket
|
||||||
//1. get the bucket_impl from the iterator
|
//1. get the bucket_impl from the iterator
|
||||||
const bucket_type &b = static_cast<const bucket_type&>
|
const bucket_type &b = static_cast<const bucket_type&>(*n);
|
||||||
(bucket_type::slist_type::container_from_end_iterator(slist_it_));
|
|
||||||
|
|
||||||
//2. Now just calculate the index b has in the bucket array
|
//2. Now just calculate the index b has in the bucket array
|
||||||
size_type n_bucket = static_cast<size_type>(&b - buckets);
|
std::size_t n_bucket = static_cast<std::size_t>(&b - buckets);
|
||||||
|
|
||||||
//3. Iterate until a non-empty bucket is found
|
//3. Iterate until a non-empty bucket is found
|
||||||
|
slist_node_ptr bucket_nodeptr = buckets->get_node_ptr();
|
||||||
do{
|
do{
|
||||||
if (++n_bucket >= buckets_len){ //bucket overflow, return end() iterator
|
if (++n_bucket >= buckets_len){ //bucket overflow, return end() iterator
|
||||||
slist_it_ = buckets->before_begin();
|
slist_it_ = first_bucket_bbegin;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
bucket_nodeptr = buckets[n_bucket].get_node_ptr();
|
||||||
}
|
}
|
||||||
while (buckets[n_bucket].empty());
|
while (slist_node_algorithms::is_empty(bucket_nodeptr));
|
||||||
slist_it_ = buckets[n_bucket].begin();
|
slist_it_ = siterator(bucket_nodeptr);
|
||||||
|
++slist_it_;
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
//++slist_it_ yield to a valid object
|
//++slist_it_ yield to a valid object
|
||||||
@@ -289,6 +245,134 @@ class hashtable_iterator
|
|||||||
const_bucketvaltraits_ptr traitsptr_;
|
const_bucketvaltraits_ptr traitsptr_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<class BucketValueTraits, bool IsConst>
|
||||||
|
class hashtable_iterator<BucketValueTraits, true, IsConst>
|
||||||
|
{
|
||||||
|
typedef typename BucketValueTraits::value_traits value_traits;
|
||||||
|
typedef typename BucketValueTraits::bucket_traits bucket_traits;
|
||||||
|
|
||||||
|
typedef iiterator< value_traits, IsConst
|
||||||
|
, std::forward_iterator_tag> types_t;
|
||||||
|
public:
|
||||||
|
typedef typename types_t::iterator_type::difference_type difference_type;
|
||||||
|
typedef typename types_t::iterator_type::value_type value_type;
|
||||||
|
typedef typename types_t::iterator_type::pointer pointer;
|
||||||
|
typedef typename types_t::iterator_type::reference reference;
|
||||||
|
typedef typename types_t::iterator_type::iterator_category iterator_category;
|
||||||
|
|
||||||
|
private:
|
||||||
|
typedef typename value_traits::node_traits node_traits;
|
||||||
|
typedef typename node_traits::node_ptr node_ptr;
|
||||||
|
typedef typename BucketValueTraits::bucket_type bucket_type;
|
||||||
|
typedef typename BucketValueTraits::bucket_ptr bucket_ptr;
|
||||||
|
typedef typename bucket_type::node_traits slist_node_traits;
|
||||||
|
typedef linear_slist_algorithms<slist_node_traits> slist_node_algorithms;
|
||||||
|
typedef typename slist_node_traits::node_ptr slist_node_ptr;
|
||||||
|
typedef trivial_value_traits
|
||||||
|
<slist_node_traits, normal_link> slist_value_traits;
|
||||||
|
typedef slist_iterator<slist_value_traits, false> siterator;
|
||||||
|
typedef slist_iterator<slist_value_traits, true> const_siterator;
|
||||||
|
|
||||||
|
static const bool stateful_value_traits =
|
||||||
|
detail::is_stateful_value_traits<value_traits>::value;
|
||||||
|
|
||||||
|
typedef typename pointer_traits
|
||||||
|
<pointer>::template rebind_pointer
|
||||||
|
< const value_traits >::type const_value_traits_ptr;
|
||||||
|
class nat;
|
||||||
|
typedef typename
|
||||||
|
detail::if_c< IsConst
|
||||||
|
, hashtable_iterator<BucketValueTraits, true, false>
|
||||||
|
, nat>::type nonconst_iterator;
|
||||||
|
|
||||||
|
BOOST_INTRUSIVE_FORCEINLINE static node_ptr downcast_bucket(slist_node_ptr p)
|
||||||
|
{
|
||||||
|
return pointer_traits<node_ptr>::
|
||||||
|
pointer_to(static_cast<typename node_traits::node&>(*p));
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
BOOST_INTRUSIVE_FORCEINLINE hashtable_iterator ()
|
||||||
|
: slist_it_() //Value initialization to achieve "null iterators" (N3644)
|
||||||
|
, members_()
|
||||||
|
{}
|
||||||
|
|
||||||
|
BOOST_INTRUSIVE_FORCEINLINE explicit hashtable_iterator(siterator ptr, bucket_ptr bp, const_value_traits_ptr traits_ptr)
|
||||||
|
: slist_it_ (ptr)
|
||||||
|
, members_ (bp, traits_ptr)
|
||||||
|
{}
|
||||||
|
|
||||||
|
BOOST_INTRUSIVE_FORCEINLINE hashtable_iterator(const hashtable_iterator &other)
|
||||||
|
: slist_it_(other.slist_it()), members_(other.get_bucket_ptr(), other.get_value_traits())
|
||||||
|
{}
|
||||||
|
|
||||||
|
BOOST_INTRUSIVE_FORCEINLINE hashtable_iterator(const nonconst_iterator &other)
|
||||||
|
: slist_it_(other.slist_it()), members_(other.get_bucket_ptr(), other.get_value_traits())
|
||||||
|
{}
|
||||||
|
|
||||||
|
BOOST_INTRUSIVE_FORCEINLINE const siterator &slist_it() const
|
||||||
|
{ return slist_it_; }
|
||||||
|
|
||||||
|
BOOST_INTRUSIVE_FORCEINLINE hashtable_iterator<BucketValueTraits, true, false> unconst() const
|
||||||
|
{ return hashtable_iterator<BucketValueTraits, true, false>(this->slist_it(), members_.nodeptr_, members_.get_ptr()); }
|
||||||
|
|
||||||
|
BOOST_INTRUSIVE_FORCEINLINE hashtable_iterator& operator++()
|
||||||
|
{ this->increment(); return *this; }
|
||||||
|
|
||||||
|
BOOST_INTRUSIVE_FORCEINLINE hashtable_iterator &operator=(const hashtable_iterator &other)
|
||||||
|
{ slist_it_ = other.slist_it(); members_ = other.members_; return *this; }
|
||||||
|
|
||||||
|
BOOST_INTRUSIVE_FORCEINLINE hashtable_iterator operator++(int)
|
||||||
|
{
|
||||||
|
hashtable_iterator result (*this);
|
||||||
|
this->increment();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_INTRUSIVE_FORCEINLINE friend bool operator== (const hashtable_iterator& i, const hashtable_iterator& i2)
|
||||||
|
{ return i.slist_it_ == i2.slist_it_; }
|
||||||
|
|
||||||
|
BOOST_INTRUSIVE_FORCEINLINE friend bool operator!= (const hashtable_iterator& i, const hashtable_iterator& i2)
|
||||||
|
{ return !(i == i2); }
|
||||||
|
|
||||||
|
BOOST_INTRUSIVE_FORCEINLINE reference operator*() const
|
||||||
|
{ return *this->operator ->(); }
|
||||||
|
|
||||||
|
BOOST_INTRUSIVE_FORCEINLINE pointer operator->() const
|
||||||
|
{ return this->operator_arrow(detail::bool_<stateful_value_traits>()); }
|
||||||
|
|
||||||
|
BOOST_INTRUSIVE_FORCEINLINE const_value_traits_ptr get_value_traits() const
|
||||||
|
{ return members_.get_ptr(); }
|
||||||
|
|
||||||
|
BOOST_INTRUSIVE_FORCEINLINE bucket_ptr get_bucket_ptr() const
|
||||||
|
{ return members_.nodeptr_; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
BOOST_INTRUSIVE_FORCEINLINE pointer operator_arrow(detail::false_) const
|
||||||
|
{ return value_traits::to_value_ptr(downcast_bucket(slist_it_.pointed_node())); }
|
||||||
|
|
||||||
|
BOOST_INTRUSIVE_FORCEINLINE pointer operator_arrow(detail::true_) const
|
||||||
|
{ return this->get_value_traits()->to_value_ptr(downcast_bucket(slist_it_.pointed_node())); }
|
||||||
|
|
||||||
|
void increment()
|
||||||
|
{
|
||||||
|
++slist_it_;
|
||||||
|
if (slist_it_ == siterator()){
|
||||||
|
slist_node_ptr bucket_nodeptr;
|
||||||
|
do {
|
||||||
|
++members_.nodeptr_;
|
||||||
|
bucket_nodeptr = members_.nodeptr_->get_node_ptr();
|
||||||
|
}while(slist_node_algorithms::is_empty(bucket_nodeptr));
|
||||||
|
slist_it_ = siterator(slist_node_traits::get_next(bucket_nodeptr));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
siterator slist_it_;
|
||||||
|
iiterator_members<bucket_ptr, const_value_traits_ptr, stateful_value_traits> members_;
|
||||||
|
};
|
||||||
|
|
||||||
} //namespace intrusive {
|
} //namespace intrusive {
|
||||||
} //namespace boost {
|
} //namespace boost {
|
||||||
|
|
||||||
|
File diff suppressed because it is too large
Load Diff
@@ -570,6 +570,7 @@ template
|
|||||||
, class O8 = void
|
, class O8 = void
|
||||||
, class O9 = void
|
, class O9 = void
|
||||||
, class O10 = void
|
, class O10 = void
|
||||||
|
, class O11 = void
|
||||||
>
|
>
|
||||||
#else
|
#else
|
||||||
template<class T, class ...Options>
|
template<class T, class ...Options>
|
||||||
@@ -589,6 +590,7 @@ template
|
|||||||
, class O8 = void
|
, class O8 = void
|
||||||
, class O9 = void
|
, class O9 = void
|
||||||
, class O10 = void
|
, class O10 = void
|
||||||
|
, class O11 = void
|
||||||
>
|
>
|
||||||
#else
|
#else
|
||||||
template<class T, class ...Options>
|
template<class T, class ...Options>
|
||||||
|
@@ -241,6 +241,11 @@ BOOST_INTRUSIVE_OPTION_CONSTANT(compare_hash, bool, Enabled, compare_hash)
|
|||||||
//!(rehashing the whole bucket array) is not admisible.
|
//!(rehashing the whole bucket array) is not admisible.
|
||||||
BOOST_INTRUSIVE_OPTION_CONSTANT(incremental, bool, Enabled, incremental)
|
BOOST_INTRUSIVE_OPTION_CONSTANT(incremental, bool, Enabled, incremental)
|
||||||
|
|
||||||
|
//!This option setter specifies if the buckets (which form a singly linked lists of nodes)
|
||||||
|
//!are linear (true) or circular (false, default value). Linear buckets can improve performance
|
||||||
|
//!in some cases, but the container loses some features like obtaining an iterator from a value.
|
||||||
|
BOOST_INTRUSIVE_OPTION_CONSTANT(linear_buckets, bool, Enabled, linear_buckets)
|
||||||
|
|
||||||
/// @cond
|
/// @cond
|
||||||
|
|
||||||
struct hook_defaults
|
struct hook_defaults
|
||||||
|
@@ -28,8 +28,13 @@ namespace intrusive {
|
|||||||
|
|
||||||
/// @cond
|
/// @cond
|
||||||
|
|
||||||
template<class U>
|
namespace adldft {
|
||||||
void priority_order();
|
|
||||||
|
template<class T, class U>
|
||||||
|
BOOST_INTRUSIVE_FORCEINLINE bool priority_order(const T &t, const U &u)
|
||||||
|
{ return t < u; }
|
||||||
|
|
||||||
|
} //namespace adldft {
|
||||||
|
|
||||||
/// @endcond
|
/// @endcond
|
||||||
|
|
||||||
@@ -43,6 +48,7 @@ struct priority_compare
|
|||||||
|
|
||||||
BOOST_INTRUSIVE_FORCEINLINE bool operator()(const T &val, const T &val2) const
|
BOOST_INTRUSIVE_FORCEINLINE bool operator()(const T &val, const T &val2) const
|
||||||
{
|
{
|
||||||
|
using adldft::priority_order;
|
||||||
return priority_order(val, val2);
|
return priority_order(val, val2);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -53,6 +59,7 @@ struct priority_compare<void>
|
|||||||
template<class T, class U>
|
template<class T, class U>
|
||||||
BOOST_INTRUSIVE_FORCEINLINE bool operator()(const T &t, const U &u) const
|
BOOST_INTRUSIVE_FORCEINLINE bool operator()(const T &t, const U &u) const
|
||||||
{
|
{
|
||||||
|
using adldft::priority_order;
|
||||||
return priority_order(t, u);
|
return priority_order(t, u);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@@ -67,7 +67,9 @@ template<class T, class ...Options>
|
|||||||
template<class ValueTraits, class VoidOrKeyOfValue, class VoidOrKeyHash, class VoidOrKeyEqual, class SizeType, class BucketTraits, std::size_t BoolFlags>
|
template<class ValueTraits, class VoidOrKeyOfValue, class VoidOrKeyHash, class VoidOrKeyEqual, class SizeType, class BucketTraits, std::size_t BoolFlags>
|
||||||
#endif
|
#endif
|
||||||
class unordered_set_impl
|
class unordered_set_impl
|
||||||
|
#ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED
|
||||||
: public hashtable_impl<ValueTraits, VoidOrKeyOfValue, VoidOrKeyHash, VoidOrKeyEqual, BucketTraits, SizeType, BoolFlags|hash_bool_flags::unique_keys_pos>
|
: public hashtable_impl<ValueTraits, VoidOrKeyOfValue, VoidOrKeyHash, VoidOrKeyEqual, BucketTraits, SizeType, BoolFlags|hash_bool_flags::unique_keys_pos>
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
/// @cond
|
/// @cond
|
||||||
private:
|
private:
|
||||||
@@ -115,7 +117,6 @@ class unordered_set_impl
|
|||||||
typedef typename implementation_defined::node node;
|
typedef typename implementation_defined::node node;
|
||||||
typedef typename implementation_defined::node_ptr node_ptr;
|
typedef typename implementation_defined::node_ptr node_ptr;
|
||||||
typedef typename implementation_defined::const_node_ptr const_node_ptr;
|
typedef typename implementation_defined::const_node_ptr const_node_ptr;
|
||||||
typedef typename implementation_defined::node_algorithms node_algorithms;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
@@ -420,6 +421,7 @@ template<class T, class O1 = void, class O2 = void
|
|||||||
, class O5 = void, class O6 = void
|
, class O5 = void, class O6 = void
|
||||||
, class O7 = void, class O8 = void
|
, class O7 = void, class O8 = void
|
||||||
, class O9 = void, class O10= void
|
, class O9 = void, class O10= void
|
||||||
|
, class O11 = void
|
||||||
>
|
>
|
||||||
#endif
|
#endif
|
||||||
struct make_unordered_set
|
struct make_unordered_set
|
||||||
@@ -428,7 +430,7 @@ struct make_unordered_set
|
|||||||
typedef typename pack_options
|
typedef typename pack_options
|
||||||
< hashtable_defaults,
|
< hashtable_defaults,
|
||||||
#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
|
#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
|
||||||
O1, O2, O3, O4, O5, O6, O7, O8, O9, O10
|
O1, O2, O3, O4, O5, O6, O7, O8, O9, O10, O11
|
||||||
#else
|
#else
|
||||||
Options...
|
Options...
|
||||||
#endif
|
#endif
|
||||||
@@ -438,7 +440,7 @@ struct make_unordered_set
|
|||||||
<T, typename packed_options::proto_value_traits>::type value_traits;
|
<T, typename packed_options::proto_value_traits>::type value_traits;
|
||||||
|
|
||||||
typedef typename make_bucket_traits
|
typedef typename make_bucket_traits
|
||||||
<T, true, packed_options>::type bucket_traits;
|
<T, packed_options>::type bucket_traits;
|
||||||
|
|
||||||
typedef unordered_set_impl
|
typedef unordered_set_impl
|
||||||
< value_traits
|
< value_traits
|
||||||
@@ -453,6 +455,7 @@ struct make_unordered_set
|
|||||||
| (std::size_t(packed_options::cache_begin)*hash_bool_flags::cache_begin_pos)
|
| (std::size_t(packed_options::cache_begin)*hash_bool_flags::cache_begin_pos)
|
||||||
| (std::size_t(packed_options::compare_hash)*hash_bool_flags::compare_hash_pos)
|
| (std::size_t(packed_options::compare_hash)*hash_bool_flags::compare_hash_pos)
|
||||||
| (std::size_t(packed_options::incremental)*hash_bool_flags::incremental_pos)
|
| (std::size_t(packed_options::incremental)*hash_bool_flags::incremental_pos)
|
||||||
|
| (std::size_t(packed_options::linear_buckets)*hash_bool_flags::linear_buckets_pos)
|
||||||
> implementation_defined;
|
> implementation_defined;
|
||||||
|
|
||||||
/// @endcond
|
/// @endcond
|
||||||
@@ -462,27 +465,26 @@ struct make_unordered_set
|
|||||||
#ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED
|
#ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED
|
||||||
|
|
||||||
#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
|
#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
|
||||||
template<class T, class O1, class O2, class O3, class O4, class O5, class O6, class O7, class O8, class O9, class O10>
|
template<class T, class O1, class O2, class O3, class O4, class O5, class O6, class O7, class O8, class O9, class O10, class O11>
|
||||||
#else
|
#else
|
||||||
template<class T, class ...Options>
|
template<class T, class ...Options>
|
||||||
#endif
|
#endif
|
||||||
class unordered_set
|
class unordered_set
|
||||||
: public make_unordered_set<T,
|
: public make_unordered_set<T,
|
||||||
#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
|
#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
|
||||||
O1, O2, O3, O4, O5, O6, O7, O8, O9, O10
|
O1, O2, O3, O4, O5, O6, O7, O8, O9, O10, O11
|
||||||
#else
|
#else
|
||||||
Options...
|
Options...
|
||||||
#endif
|
#endif
|
||||||
>::type
|
>::type
|
||||||
{
|
{
|
||||||
typedef typename make_unordered_set
|
typedef typename make_unordered_set<T,
|
||||||
<T,
|
|
||||||
#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
|
#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
|
||||||
O1, O2, O3, O4, O5, O6, O7, O8, O9, O10
|
O1, O2, O3, O4, O5, O6, O7, O8, O9, O10, O11
|
||||||
#else
|
#else
|
||||||
Options...
|
Options...
|
||||||
#endif
|
#endif
|
||||||
>::type Base;
|
>::type Base;
|
||||||
|
|
||||||
//Assert if passed value traits are compatible with the type
|
//Assert if passed value traits are compatible with the type
|
||||||
BOOST_STATIC_ASSERT((detail::is_same<typename Base::value_traits::value_type, T>::value));
|
BOOST_STATIC_ASSERT((detail::is_same<typename Base::value_traits::value_type, T>::value));
|
||||||
@@ -526,11 +528,11 @@ class unordered_set
|
|||||||
|
|
||||||
template <class Cloner, class Disposer>
|
template <class Cloner, class Disposer>
|
||||||
BOOST_INTRUSIVE_FORCEINLINE void clone_from(const unordered_set &src, Cloner cloner, Disposer disposer)
|
BOOST_INTRUSIVE_FORCEINLINE void clone_from(const unordered_set &src, Cloner cloner, Disposer disposer)
|
||||||
{ Base::clone_from(src, cloner, disposer); }
|
{ this->Base::clone_from(src, cloner, disposer); }
|
||||||
|
|
||||||
template <class Cloner, class Disposer>
|
template <class Cloner, class Disposer>
|
||||||
BOOST_INTRUSIVE_FORCEINLINE void clone_from(BOOST_RV_REF(unordered_set) src, Cloner cloner, Disposer disposer)
|
BOOST_INTRUSIVE_FORCEINLINE void clone_from(BOOST_RV_REF(unordered_set) src, Cloner cloner, Disposer disposer)
|
||||||
{ Base::clone_from(BOOST_MOVE_BASE(Base, src), cloner, disposer); }
|
{ this->Base::clone_from(BOOST_MOVE_BASE(Base, src), cloner, disposer); }
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -577,7 +579,9 @@ template<class T, class ...Options>
|
|||||||
template<class ValueTraits, class VoidOrKeyOfValue, class VoidOrKeyHash, class VoidOrKeyEqual, class SizeType, class BucketTraits, std::size_t BoolFlags>
|
template<class ValueTraits, class VoidOrKeyOfValue, class VoidOrKeyHash, class VoidOrKeyEqual, class SizeType, class BucketTraits, std::size_t BoolFlags>
|
||||||
#endif
|
#endif
|
||||||
class unordered_multiset_impl
|
class unordered_multiset_impl
|
||||||
|
#ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED
|
||||||
: public hashtable_impl<ValueTraits, VoidOrKeyOfValue, VoidOrKeyHash, VoidOrKeyEqual, BucketTraits, SizeType, BoolFlags>
|
: public hashtable_impl<ValueTraits, VoidOrKeyOfValue, VoidOrKeyHash, VoidOrKeyEqual, BucketTraits, SizeType, BoolFlags>
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
/// @cond
|
/// @cond
|
||||||
private:
|
private:
|
||||||
@@ -613,7 +617,6 @@ class unordered_multiset_impl
|
|||||||
typedef typename implementation_defined::node node;
|
typedef typename implementation_defined::node node;
|
||||||
typedef typename implementation_defined::node_ptr node_ptr;
|
typedef typename implementation_defined::node_ptr node_ptr;
|
||||||
typedef typename implementation_defined::const_node_ptr const_node_ptr;
|
typedef typename implementation_defined::const_node_ptr const_node_ptr;
|
||||||
typedef typename implementation_defined::node_algorithms node_algorithms;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
@@ -872,6 +875,7 @@ template<class T, class O1 = void, class O2 = void
|
|||||||
, class O5 = void, class O6 = void
|
, class O5 = void, class O6 = void
|
||||||
, class O7 = void, class O8 = void
|
, class O7 = void, class O8 = void
|
||||||
, class O9 = void, class O10= void
|
, class O9 = void, class O10= void
|
||||||
|
, class O11 = void
|
||||||
>
|
>
|
||||||
#endif
|
#endif
|
||||||
struct make_unordered_multiset
|
struct make_unordered_multiset
|
||||||
@@ -880,7 +884,7 @@ struct make_unordered_multiset
|
|||||||
typedef typename pack_options
|
typedef typename pack_options
|
||||||
< hashtable_defaults,
|
< hashtable_defaults,
|
||||||
#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
|
#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
|
||||||
O1, O2, O3, O4, O5, O6, O7, O8, O9, O10
|
O1, O2, O3, O4, O5, O6, O7, O8, O9, O10, O11
|
||||||
#else
|
#else
|
||||||
Options...
|
Options...
|
||||||
#endif
|
#endif
|
||||||
@@ -890,7 +894,7 @@ struct make_unordered_multiset
|
|||||||
<T, typename packed_options::proto_value_traits>::type value_traits;
|
<T, typename packed_options::proto_value_traits>::type value_traits;
|
||||||
|
|
||||||
typedef typename make_bucket_traits
|
typedef typename make_bucket_traits
|
||||||
<T, true, packed_options>::type bucket_traits;
|
<T, packed_options>::type bucket_traits;
|
||||||
|
|
||||||
typedef unordered_multiset_impl
|
typedef unordered_multiset_impl
|
||||||
< value_traits
|
< value_traits
|
||||||
@@ -905,6 +909,7 @@ struct make_unordered_multiset
|
|||||||
| (std::size_t(packed_options::cache_begin)*hash_bool_flags::cache_begin_pos)
|
| (std::size_t(packed_options::cache_begin)*hash_bool_flags::cache_begin_pos)
|
||||||
| (std::size_t(packed_options::compare_hash)*hash_bool_flags::compare_hash_pos)
|
| (std::size_t(packed_options::compare_hash)*hash_bool_flags::compare_hash_pos)
|
||||||
| (std::size_t(packed_options::incremental)*hash_bool_flags::incremental_pos)
|
| (std::size_t(packed_options::incremental)*hash_bool_flags::incremental_pos)
|
||||||
|
| (std::size_t(packed_options::linear_buckets)*hash_bool_flags::linear_buckets_pos)
|
||||||
> implementation_defined;
|
> implementation_defined;
|
||||||
|
|
||||||
/// @endcond
|
/// @endcond
|
||||||
@@ -914,14 +919,14 @@ struct make_unordered_multiset
|
|||||||
#ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED
|
#ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED
|
||||||
|
|
||||||
#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
|
#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
|
||||||
template<class T, class O1, class O2, class O3, class O4, class O5, class O6, class O7, class O8, class O9, class O10>
|
template<class T, class O1, class O2, class O3, class O4, class O5, class O6, class O7, class O8, class O9, class O10, class O11>
|
||||||
#else
|
#else
|
||||||
template<class T, class ...Options>
|
template<class T, class ...Options>
|
||||||
#endif
|
#endif
|
||||||
class unordered_multiset
|
class unordered_multiset
|
||||||
: public make_unordered_multiset<T,
|
: public make_unordered_multiset<T,
|
||||||
#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
|
#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
|
||||||
O1, O2, O3, O4, O5, O6, O7, O8, O9, O10
|
O1, O2, O3, O4, O5, O6, O7, O8, O9, O10, O11
|
||||||
#else
|
#else
|
||||||
Options...
|
Options...
|
||||||
#endif
|
#endif
|
||||||
@@ -977,11 +982,11 @@ class unordered_multiset
|
|||||||
|
|
||||||
template <class Cloner, class Disposer>
|
template <class Cloner, class Disposer>
|
||||||
BOOST_INTRUSIVE_FORCEINLINE void clone_from(const unordered_multiset &src, Cloner cloner, Disposer disposer)
|
BOOST_INTRUSIVE_FORCEINLINE void clone_from(const unordered_multiset &src, Cloner cloner, Disposer disposer)
|
||||||
{ Base::clone_from(src, cloner, disposer); }
|
{ this->Base::clone_from(src, cloner, disposer); }
|
||||||
|
|
||||||
template <class Cloner, class Disposer>
|
template <class Cloner, class Disposer>
|
||||||
BOOST_INTRUSIVE_FORCEINLINE void clone_from(BOOST_RV_REF(unordered_multiset) src, Cloner cloner, Disposer disposer)
|
BOOST_INTRUSIVE_FORCEINLINE void clone_from(BOOST_RV_REF(unordered_multiset) src, Cloner cloner, Disposer disposer)
|
||||||
{ Base::clone_from(BOOST_MOVE_BASE(Base, src), cloner, disposer); }
|
{ this->Base::clone_from(BOOST_MOVE_BASE(Base, src), cloner, disposer); }
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@@ -108,10 +108,10 @@ struct unordered_group_adapter
|
|||||||
typedef typename NodeTraits::node_ptr node_ptr;
|
typedef typename NodeTraits::node_ptr node_ptr;
|
||||||
typedef typename NodeTraits::const_node_ptr const_node_ptr;
|
typedef typename NodeTraits::const_node_ptr const_node_ptr;
|
||||||
|
|
||||||
static node_ptr get_next(const_node_ptr n)
|
BOOST_INTRUSIVE_FORCEINLINE static node_ptr get_next(const_node_ptr n)
|
||||||
{ return NodeTraits::get_prev_in_group(n); }
|
{ return NodeTraits::get_prev_in_group(n); }
|
||||||
|
|
||||||
static void set_next(node_ptr n, node_ptr next)
|
BOOST_INTRUSIVE_FORCEINLINE static void set_next(node_ptr n, node_ptr next)
|
||||||
{ NodeTraits::set_prev_in_group(n, next); }
|
{ NodeTraits::set_prev_in_group(n, next); }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -22,8 +22,6 @@
|
|||||||
#include <boost/intrusive/link_mode.hpp>
|
#include <boost/intrusive/link_mode.hpp>
|
||||||
|
|
||||||
|
|
||||||
namespace boost {
|
|
||||||
namespace intrusive {
|
|
||||||
|
|
||||||
struct BPtr_Value
|
struct BPtr_Value
|
||||||
{
|
{
|
||||||
@@ -210,6 +208,8 @@ struct ValueContainer< BPtr_Value >
|
|||||||
typedef bounded_reference_cont< BPtr_Value > type;
|
typedef bounded_reference_cont< BPtr_Value > type;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
namespace boost {
|
||||||
|
namespace intrusive {
|
||||||
namespace test{
|
namespace test{
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
|
@@ -14,9 +14,6 @@
|
|||||||
|
|
||||||
#include <boost/functional/hash/hash.hpp>
|
#include <boost/functional/hash/hash.hpp>
|
||||||
|
|
||||||
namespace boost{
|
|
||||||
namespace intrusive{
|
|
||||||
|
|
||||||
struct int_holder
|
struct int_holder
|
||||||
{
|
{
|
||||||
explicit int_holder(int value = 0)
|
explicit int_holder(int value = 0)
|
||||||
@@ -111,7 +108,4 @@ struct int_priority_of_value
|
|||||||
{ return tv.int_value(); }
|
{ return tv.int_value(); }
|
||||||
};
|
};
|
||||||
|
|
||||||
} //namespace boost{
|
|
||||||
} //namespace intrusive{
|
|
||||||
|
|
||||||
#endif //BOOST_INTRUSIVE_DETAIL_INT_HOLDER_HPP
|
#endif //BOOST_INTRUSIVE_DETAIL_INT_HOLDER_HPP
|
||||||
|
@@ -22,9 +22,6 @@
|
|||||||
#include <boost/intrusive/detail/get_value_traits.hpp>
|
#include <boost/intrusive/detail/get_value_traits.hpp>
|
||||||
#include <boost/container/vector.hpp>
|
#include <boost/container/vector.hpp>
|
||||||
|
|
||||||
namespace boost{
|
|
||||||
namespace intrusive{
|
|
||||||
|
|
||||||
struct testvalue_filler
|
struct testvalue_filler
|
||||||
{
|
{
|
||||||
void *dummy_[3];
|
void *dummy_[3];
|
||||||
@@ -134,35 +131,48 @@ struct testvalue
|
|||||||
boost::hash<int> hasher;
|
boost::hash<int> hasher;
|
||||||
return hasher((&t)->int_value());
|
return hasher((&t)->int_value());
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
|
static std::size_t priority_hash(const testvalue &t)
|
||||||
|
{ return boost::hash<int>()((&t)->int_value()); }
|
||||||
|
|
||||||
|
static std::size_t priority_hash(int i)
|
||||||
|
{ return boost::hash<int>()(i); }
|
||||||
|
|
||||||
|
template <class T, class U>
|
||||||
|
static bool priority_order_impl(const T& t1, const U& t2)
|
||||||
|
{
|
||||||
|
std::size_t hash1 = (priority_hash)(t1);
|
||||||
|
boost::hash_combine(hash1, -hash1);
|
||||||
|
std::size_t hash2 = (priority_hash)(t2);
|
||||||
|
boost::hash_combine(hash2, -hash2);
|
||||||
|
return hash1 < hash2;
|
||||||
|
}
|
||||||
|
|
||||||
|
friend bool priority_order(const testvalue &t1, int t2)
|
||||||
|
{ return (priority_order_impl)(t1, t2); }
|
||||||
|
|
||||||
|
friend bool priority_order(int t1, const testvalue &t2)
|
||||||
|
{ return (priority_order_impl)(t1, t2); }
|
||||||
|
*/
|
||||||
|
template < typename Node_Algorithms >
|
||||||
|
friend void swap_nodes(testvalue& lhs, testvalue& rhs)
|
||||||
|
{ lhs.swap_nodes(rhs); }
|
||||||
|
|
||||||
|
friend std::ostream& operator<<
|
||||||
|
(std::ostream& s, const testvalue& t)
|
||||||
|
{ return s << t.value_.int_value(); }
|
||||||
};
|
};
|
||||||
|
|
||||||
template<class T>
|
/*
|
||||||
std::size_t priority_hash(const T &t)
|
bool priority_order(int t1, int t2)
|
||||||
{ return boost::hash<int>()((&t)->int_value()); }
|
|
||||||
|
|
||||||
std::size_t priority_hash(int i)
|
|
||||||
{ return boost::hash<int>()(i); }
|
|
||||||
|
|
||||||
template <class T, class U>
|
|
||||||
bool priority_order(const T& t1, const U& t2)
|
|
||||||
{
|
{
|
||||||
std::size_t hash1 = (priority_hash)(t1);
|
std::size_t hash1 = boost::hash<int>()(t1);
|
||||||
boost::hash_combine(hash1, -hash1);
|
boost::hash_combine(hash1, &t1);
|
||||||
std::size_t hash2 = (priority_hash)(t2);
|
std::size_t hash2 = boost::hash<int>()(t2);
|
||||||
boost::hash_combine(hash2, -hash2);
|
boost::hash_combine(hash2, &t2);
|
||||||
return hash1 < hash2;
|
return hash1 < hash2;
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
template < typename Node_Algorithms, class Hooks>
|
|
||||||
void swap_nodes(testvalue<Hooks>& lhs, testvalue<Hooks>& rhs)
|
|
||||||
{
|
|
||||||
lhs.swap_nodes(rhs);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class Hooks>
|
|
||||||
std::ostream& operator<<
|
|
||||||
(std::ostream& s, const testvalue<Hooks>& t)
|
|
||||||
{ return s << t.value_.int_value(); }
|
|
||||||
|
|
||||||
struct even_odd
|
struct even_odd
|
||||||
{
|
{
|
||||||
@@ -206,13 +216,14 @@ struct ValueContainer< testvalue<Hooks> >
|
|||||||
template < typename Pointer >
|
template < typename Pointer >
|
||||||
class heap_node_holder
|
class heap_node_holder
|
||||||
{
|
{
|
||||||
typedef typename pointer_traits<Pointer>::element_type element_type;
|
typedef boost::intrusive::pointer_traits<Pointer> ptrtraits_t;
|
||||||
|
typedef typename ptrtraits_t::element_type element_type;
|
||||||
typedef Pointer pointer;
|
typedef Pointer pointer;
|
||||||
typedef typename pointer_rebind<pointer, const element_type>::type const_pointer;
|
typedef typename boost::intrusive::pointer_rebind<pointer, const element_type>::type const_pointer;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
heap_node_holder()
|
heap_node_holder()
|
||||||
: m_ptr(pointer_traits<Pointer>::pointer_to(*new element_type))
|
: m_ptr(ptrtraits_t::pointer_to(*new element_type))
|
||||||
{}
|
{}
|
||||||
|
|
||||||
~heap_node_holder()
|
~heap_node_holder()
|
||||||
@@ -235,50 +246,38 @@ struct testvalue_traits
|
|||||||
typedef testvalue< Hooks > value_type;
|
typedef testvalue< Hooks > value_type;
|
||||||
|
|
||||||
//base
|
//base
|
||||||
typedef typename detail::get_base_value_traits
|
typedef typename boost::intrusive::detail::get_base_value_traits
|
||||||
< value_type
|
< value_type
|
||||||
, typename Hooks::base_hook_type
|
, typename Hooks::base_hook_type
|
||||||
>::type base_value_traits;
|
>::type base_value_traits;
|
||||||
//auto-base
|
//auto-base
|
||||||
typedef typename detail::get_base_value_traits
|
typedef typename boost::intrusive::detail::get_base_value_traits
|
||||||
< value_type
|
< value_type
|
||||||
, typename Hooks::auto_base_hook_type
|
, typename Hooks::auto_base_hook_type
|
||||||
>::type auto_base_value_traits;
|
>::type auto_base_value_traits;
|
||||||
//member
|
//member
|
||||||
typedef typename detail::get_member_value_traits
|
typedef typename boost::intrusive::detail::get_member_value_traits
|
||||||
< member_hook
|
< boost::intrusive::member_hook
|
||||||
< value_type
|
< value_type
|
||||||
, typename Hooks::member_hook_type
|
, typename Hooks::member_hook_type
|
||||||
, &value_type::node_
|
, &value_type::node_
|
||||||
>
|
>
|
||||||
>::type member_value_traits;
|
>::type member_value_traits;
|
||||||
//auto-member
|
//auto-member
|
||||||
typedef typename detail::get_member_value_traits
|
typedef typename boost::intrusive::detail::get_member_value_traits
|
||||||
< member_hook
|
< boost::intrusive::member_hook
|
||||||
< value_type
|
< value_type
|
||||||
, typename Hooks::auto_member_hook_type
|
, typename Hooks::auto_member_hook_type
|
||||||
, &value_type::auto_node_
|
, &value_type::auto_node_
|
||||||
>
|
>
|
||||||
>::type auto_member_value_traits;
|
>::type auto_member_value_traits;
|
||||||
//nonmember
|
//nonmember
|
||||||
typedef nonhook_node_member_value_traits
|
typedef boost::intrusive::nonhook_node_member_value_traits
|
||||||
< value_type
|
< value_type
|
||||||
, typename Hooks::nonhook_node_member_type
|
, typename Hooks::nonhook_node_member_type
|
||||||
, &value_type::nhn_member_
|
, &value_type::nhn_member_
|
||||||
, safe_link
|
, boost::intrusive::safe_link
|
||||||
> nonhook_value_traits;
|
> nonhook_value_traits;
|
||||||
};
|
};
|
||||||
|
|
||||||
} //namespace intrusive{
|
|
||||||
} //namespace boost{
|
|
||||||
|
|
||||||
bool priority_order(int t1, int t2)
|
|
||||||
{
|
|
||||||
std::size_t hash1 = boost::hash<int>()(t1);
|
|
||||||
boost::hash_combine(hash1, &t1);
|
|
||||||
std::size_t hash2 = boost::hash<int>()(t2);
|
|
||||||
boost::hash_combine(hash2, &t2);
|
|
||||||
return hash1 < hash2;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@@ -113,8 +113,8 @@ int main()
|
|||||||
Slist my_slist(slist_traits(values, slist_hook_array));
|
Slist my_slist(slist_traits(values, slist_hook_array));
|
||||||
Set my_set (std::less<MyClass>(), rbtree_traits(values, rbtree_hook_array));
|
Set my_set (std::less<MyClass>(), rbtree_traits(values, rbtree_hook_array));
|
||||||
Uset my_uset ( Uset::bucket_traits(buckets, NumElements)
|
Uset my_uset ( Uset::bucket_traits(buckets, NumElements)
|
||||||
, boost::hash<MyClass>()
|
, Uset::hasher()
|
||||||
, std::equal_to<MyClass>()
|
, Uset::key_equal()
|
||||||
, slist_traits(values, uset_hook_array)
|
, slist_traits(values, uset_hook_array)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@@ -240,12 +240,15 @@ void test_common_unordered_and_associative_container(Container & c, Data & d, bo
|
|||||||
//
|
//
|
||||||
//Maximum fallbacks to the highest possible value
|
//Maximum fallbacks to the highest possible value
|
||||||
typename Container::size_type sz = Container::suggested_upper_bucket_count(size_type(-1));
|
typename Container::size_type sz = Container::suggested_upper_bucket_count(size_type(-1));
|
||||||
BOOST_TEST( sz > size_type(-1)/2 );
|
//If size_type is big enough the upper bound is returned
|
||||||
//In the rest of cases the upper bound is returned
|
BOOST_IF_CONSTEXPR(sizeof(size_type) < sizeof(std::size_t)){
|
||||||
sz = Container::suggested_upper_bucket_count(size_type(-1)/2);
|
sz = Container::suggested_upper_bucket_count(size_type(-1)/2);
|
||||||
BOOST_TEST( sz >= size_type(-1)/2 );
|
BOOST_TEST( sz >= size_type(-1)/2 );
|
||||||
|
}
|
||||||
sz = Container::suggested_upper_bucket_count(size_type(-1)/4);
|
sz = Container::suggested_upper_bucket_count(size_type(-1)/4);
|
||||||
BOOST_TEST( sz >= size_type(-1)/4 );
|
BOOST_TEST( sz >= size_type(-1)/4 );
|
||||||
|
sz = Container::suggested_upper_bucket_count(size_type(-1) / 8);
|
||||||
|
BOOST_TEST(sz >= size_type(-1) / 8);
|
||||||
sz = Container::suggested_upper_bucket_count(0);
|
sz = Container::suggested_upper_bucket_count(0);
|
||||||
BOOST_TEST( sz > 0 );
|
BOOST_TEST( sz > 0 );
|
||||||
//
|
//
|
||||||
|
@@ -27,7 +27,8 @@
|
|||||||
|
|
||||||
using namespace boost::intrusive;
|
using namespace boost::intrusive;
|
||||||
|
|
||||||
template < class ValueTraits, bool ConstantTimeSize, bool CacheBegin, bool CompareHash, bool Incremental, bool Map, bool DefaultHolder >
|
template < class ValueTraits, bool ConstantTimeSize, bool CacheBegin, bool CompareHash
|
||||||
|
, bool Incremental, bool Map, bool DefaultHolder, bool LinearBuckets>
|
||||||
struct rebinder
|
struct rebinder
|
||||||
{
|
{
|
||||||
typedef unordered_rebinder_common<ValueTraits, DefaultHolder, Map> common_t;
|
typedef unordered_rebinder_common<ValueTraits, DefaultHolder, Map> common_t;
|
||||||
@@ -45,6 +46,7 @@ struct rebinder
|
|||||||
, cache_begin<CacheBegin>
|
, cache_begin<CacheBegin>
|
||||||
, compare_hash<CompareHash>
|
, compare_hash<CompareHash>
|
||||||
, incremental<Incremental>
|
, incremental<Incremental>
|
||||||
|
, linear_buckets<LinearBuckets>
|
||||||
, typename common_t::holder_opt
|
, typename common_t::holder_opt
|
||||||
, typename common_t::key_of_value_opt
|
, typename common_t::key_of_value_opt
|
||||||
, Option1
|
, Option1
|
||||||
@@ -62,11 +64,11 @@ enum HookType
|
|||||||
NonMember
|
NonMember
|
||||||
};
|
};
|
||||||
|
|
||||||
template<class VoidPointer, bool ConstantTimeSize, bool DefaultHolder, bool Map, HookType Type>
|
template<class VoidPointer, bool ConstantTimeSize, bool DefaultHolder, bool Map, HookType Type, bool LinearBuckets>
|
||||||
class test_main_template;
|
class test_main_template;
|
||||||
|
|
||||||
template<class VoidPointer, bool ConstantTimeSize, bool DefaultHolder, bool Map>
|
template<class VoidPointer, bool ConstantTimeSize, bool DefaultHolder, bool Map, bool LinearBuckets>
|
||||||
class test_main_template<VoidPointer, ConstantTimeSize, DefaultHolder, Map, Base>
|
class test_main_template<VoidPointer, ConstantTimeSize, DefaultHolder, Map, Base, LinearBuckets>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static void execute()
|
static void execute()
|
||||||
@@ -87,13 +89,14 @@ class test_main_template<VoidPointer, ConstantTimeSize, DefaultHolder, Map, Base
|
|||||||
>::type base_hook_t;
|
>::type base_hook_t;
|
||||||
test::test_unordered
|
test::test_unordered
|
||||||
< //cache_begin, compare_hash, incremental
|
< //cache_begin, compare_hash, incremental
|
||||||
rebinder<base_hook_t, ConstantTimeSize, ConstantTimeSize, !ConstantTimeSize, !!ConstantTimeSize, Map, DefaultHolder>
|
rebinder< base_hook_t, ConstantTimeSize, ConstantTimeSize
|
||||||
|
, !ConstantTimeSize, !!ConstantTimeSize, Map, DefaultHolder, LinearBuckets>
|
||||||
>::test_all(data);
|
>::test_all(data);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<class VoidPointer, bool ConstantTimeSize, bool DefaultHolder, bool Map>
|
template<class VoidPointer, bool ConstantTimeSize, bool DefaultHolder, bool Map, bool LinearBuckets>
|
||||||
class test_main_template<VoidPointer, ConstantTimeSize, DefaultHolder, Map, Member>
|
class test_main_template<VoidPointer, ConstantTimeSize, DefaultHolder, Map, Member, LinearBuckets>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static void execute()
|
static void execute()
|
||||||
@@ -114,13 +117,14 @@ class test_main_template<VoidPointer, ConstantTimeSize, DefaultHolder, Map, Memb
|
|||||||
>::type member_hook_t;
|
>::type member_hook_t;
|
||||||
test::test_unordered
|
test::test_unordered
|
||||||
< //cache_begin, compare_hash, incremental
|
< //cache_begin, compare_hash, incremental
|
||||||
rebinder<member_hook_t, ConstantTimeSize, false, !ConstantTimeSize, false, !ConstantTimeSize, DefaultHolder>
|
rebinder <member_hook_t, ConstantTimeSize, false
|
||||||
|
, !ConstantTimeSize, false, !ConstantTimeSize, DefaultHolder, LinearBuckets>
|
||||||
>::test_all(data);
|
>::test_all(data);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<class VoidPointer, bool ConstantTimeSize, bool DefaultHolder, bool Map>
|
template<class VoidPointer, bool ConstantTimeSize, bool DefaultHolder, bool Map, bool LinearBuckets>
|
||||||
class test_main_template<VoidPointer, ConstantTimeSize, DefaultHolder, Map, NonMember>
|
class test_main_template<VoidPointer, ConstantTimeSize, DefaultHolder, Map, NonMember, LinearBuckets>
|
||||||
|
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -137,7 +141,8 @@ class test_main_template<VoidPointer, ConstantTimeSize, DefaultHolder, Map, NonM
|
|||||||
//nonmember
|
//nonmember
|
||||||
test::test_unordered
|
test::test_unordered
|
||||||
< //cache_begin, compare_hash, incremental
|
< //cache_begin, compare_hash, incremental
|
||||||
rebinder<typename testval_traits_t::nonhook_value_traits, ConstantTimeSize, false, false, false, Map, DefaultHolder>
|
rebinder< typename testval_traits_t::nonhook_value_traits
|
||||||
|
, ConstantTimeSize, false, false, false, Map, DefaultHolder, LinearBuckets>
|
||||||
>::test_all(data);
|
>::test_all(data);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -147,21 +152,31 @@ int main()
|
|||||||
//VoidPointer x ConstantTimeSize x Map x DefaultHolder
|
//VoidPointer x ConstantTimeSize x Map x DefaultHolder
|
||||||
|
|
||||||
//void pointer
|
//void pointer
|
||||||
test_main_template<void*, false, false, false, Base>::execute();
|
test_main_template<void*, false, false, false, Base, false>::execute();
|
||||||
test_main_template<void*, false, true, false, Member>::execute();
|
test_main_template<void*, false, true, false, Member, false>::execute();
|
||||||
test_main_template<void*, true, false, false, NonMember>::execute();
|
test_main_template<void*, true, false, false, NonMember, false>::execute();
|
||||||
test_main_template<void*, true, true, false, Base>::execute();
|
test_main_template<void*, true, true, false, Base, false>::execute();
|
||||||
|
test_main_template<void*, false, false, false, Base, true>::execute();
|
||||||
|
test_main_template<void*, false, true, false, Member, true>::execute();
|
||||||
|
test_main_template<void*, true, false, false, NonMember, true>::execute();
|
||||||
|
test_main_template<void*, true, true, false, Base, true>::execute();
|
||||||
|
|
||||||
//smart_ptr
|
//smart_ptr
|
||||||
test_main_template<smart_ptr<void>, false, false, false, Member>::execute();
|
test_main_template<smart_ptr<void>, false, false, false, Member, false>::execute();
|
||||||
test_main_template<smart_ptr<void>, false, true, false, NonMember>::execute();
|
test_main_template<smart_ptr<void>, false, true, false, NonMember, false>::execute();
|
||||||
test_main_template<smart_ptr<void>, true, false, false, Base>::execute();
|
test_main_template<smart_ptr<void>, true, false, false, Base, false>::execute();
|
||||||
test_main_template<smart_ptr<void>, true, true, false, Member>::execute();
|
test_main_template<smart_ptr<void>, true, true, false, Member, false>::execute();
|
||||||
|
test_main_template<smart_ptr<void>, true, true, false, Base, true>::execute();
|
||||||
|
|
||||||
|
test_main_template<smart_ptr<void>, false, false, false, Member, true>::execute();
|
||||||
|
test_main_template<smart_ptr<void>, false, true, false, NonMember, true>::execute();
|
||||||
|
test_main_template<smart_ptr<void>, true, false, false, Base, true>::execute();
|
||||||
|
|
||||||
////bounded_ptr (bool ConstantTimeSize, bool Map)
|
////bounded_ptr (bool ConstantTimeSize, bool Map)
|
||||||
//test_main_template_bptr< false, false >::execute();
|
//test_main_template_bptr< false, false >::execute();
|
||||||
//test_main_template_bptr< false, true >::execute();
|
//test_main_template_bptr< false, true >::execute();
|
||||||
//test_main_template_bptr< true, false >::execute();
|
//test_main_template_bptr< true, false >::execute();
|
||||||
//test_main_template_bptr< true, true >::execute();
|
//test_main_template_bptr< true, true >::execute();
|
||||||
|
|
||||||
return boost::report_errors();
|
return boost::report_errors();
|
||||||
}
|
}
|
||||||
|
@@ -25,7 +25,8 @@
|
|||||||
|
|
||||||
using namespace boost::intrusive;
|
using namespace boost::intrusive;
|
||||||
|
|
||||||
template < class ValueTraits, bool ConstantTimeSize, bool CacheBegin, bool CompareHash, bool Incremental, bool Map, bool DefaultHolder >
|
template < class ValueTraits, bool ConstantTimeSize, bool CacheBegin, bool CompareHash
|
||||||
|
, bool Incremental, bool Map, bool DefaultHolder, bool LinearBuckets >
|
||||||
struct rebinder
|
struct rebinder
|
||||||
{
|
{
|
||||||
typedef unordered_rebinder_common<ValueTraits, DefaultHolder, Map> common_t;
|
typedef unordered_rebinder_common<ValueTraits, DefaultHolder, Map> common_t;
|
||||||
@@ -43,6 +44,7 @@ struct rebinder
|
|||||||
, cache_begin<CacheBegin>
|
, cache_begin<CacheBegin>
|
||||||
, compare_hash<CompareHash>
|
, compare_hash<CompareHash>
|
||||||
, incremental<Incremental>
|
, incremental<Incremental>
|
||||||
|
, linear_buckets<LinearBuckets>
|
||||||
, typename common_t::holder_opt
|
, typename common_t::holder_opt
|
||||||
, typename common_t::key_of_value_opt
|
, typename common_t::key_of_value_opt
|
||||||
, size_type<unsigned short>
|
, size_type<unsigned short>
|
||||||
@@ -61,11 +63,11 @@ enum HookType
|
|||||||
NonMember
|
NonMember
|
||||||
};
|
};
|
||||||
|
|
||||||
template<class VoidPointer, bool ConstantTimeSize, bool DefaultHolder, bool Map, HookType Type>
|
template<class VoidPointer, bool ConstantTimeSize, bool DefaultHolder, bool Map, HookType Type, bool LinearBuckets>
|
||||||
class test_main_template;
|
class test_main_template;
|
||||||
|
|
||||||
template<class VoidPointer, bool ConstantTimeSize, bool DefaultHolder, bool Map>
|
template<class VoidPointer, bool ConstantTimeSize, bool DefaultHolder, bool Map, bool LinearBuckets>
|
||||||
class test_main_template<VoidPointer, ConstantTimeSize, DefaultHolder, Map, Base>
|
class test_main_template<VoidPointer, ConstantTimeSize, DefaultHolder, Map, Base, LinearBuckets>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static void execute()
|
static void execute()
|
||||||
@@ -86,13 +88,14 @@ class test_main_template<VoidPointer, ConstantTimeSize, DefaultHolder, Map, Base
|
|||||||
>::type base_hook_t;
|
>::type base_hook_t;
|
||||||
test::test_unordered
|
test::test_unordered
|
||||||
< //cache_begin, compare_hash, incremental
|
< //cache_begin, compare_hash, incremental
|
||||||
rebinder<base_hook_t, ConstantTimeSize, ConstantTimeSize, !ConstantTimeSize, !!ConstantTimeSize, Map, DefaultHolder>
|
rebinder< base_hook_t, ConstantTimeSize, ConstantTimeSize
|
||||||
|
, !ConstantTimeSize, !!ConstantTimeSize, Map, DefaultHolder, LinearBuckets>
|
||||||
>::test_all(data);
|
>::test_all(data);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<class VoidPointer, bool ConstantTimeSize, bool DefaultHolder, bool Map>
|
template<class VoidPointer, bool ConstantTimeSize, bool DefaultHolder, bool Map, bool LinearBuckets>
|
||||||
class test_main_template<VoidPointer, ConstantTimeSize, DefaultHolder, Map, Member>
|
class test_main_template<VoidPointer, ConstantTimeSize, DefaultHolder, Map, Member, LinearBuckets>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static void execute()
|
static void execute()
|
||||||
@@ -113,13 +116,13 @@ class test_main_template<VoidPointer, ConstantTimeSize, DefaultHolder, Map, Memb
|
|||||||
>::type member_hook_t;
|
>::type member_hook_t;
|
||||||
test::test_unordered
|
test::test_unordered
|
||||||
< //cache_begin, compare_hash, incremental
|
< //cache_begin, compare_hash, incremental
|
||||||
rebinder<member_hook_t, ConstantTimeSize, false, !ConstantTimeSize, false, !ConstantTimeSize, DefaultHolder>
|
rebinder<member_hook_t, ConstantTimeSize, false, !ConstantTimeSize, false, !ConstantTimeSize, DefaultHolder, LinearBuckets>
|
||||||
>::test_all(data);
|
>::test_all(data);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<class VoidPointer, bool ConstantTimeSize, bool DefaultHolder, bool Map>
|
template<class VoidPointer, bool ConstantTimeSize, bool DefaultHolder, bool Map, bool LinearBuckets>
|
||||||
class test_main_template<VoidPointer, ConstantTimeSize, DefaultHolder, Map, NonMember>
|
class test_main_template<VoidPointer, ConstantTimeSize, DefaultHolder, Map, NonMember, LinearBuckets>
|
||||||
|
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -136,7 +139,7 @@ class test_main_template<VoidPointer, ConstantTimeSize, DefaultHolder, Map, NonM
|
|||||||
//nonmember
|
//nonmember
|
||||||
test::test_unordered
|
test::test_unordered
|
||||||
< //cache_begin, compare_hash, incremental
|
< //cache_begin, compare_hash, incremental
|
||||||
rebinder<typename testval_traits_t::nonhook_value_traits, ConstantTimeSize, false, false, false, Map, DefaultHolder>
|
rebinder<typename testval_traits_t::nonhook_value_traits, ConstantTimeSize, false, false, false, Map, DefaultHolder, LinearBuckets>
|
||||||
>::test_all(data);
|
>::test_all(data);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -146,16 +149,25 @@ int main()
|
|||||||
//VoidPointer x ConstantTimeSize x Map x DefaultHolder
|
//VoidPointer x ConstantTimeSize x Map x DefaultHolder
|
||||||
|
|
||||||
//void pointer
|
//void pointer
|
||||||
test_main_template<void*, false, false, false, Base>::execute();
|
test_main_template<void*, false, false, false, Base, false>::execute();
|
||||||
test_main_template<void*, false, true, false, Member>::execute();
|
test_main_template<void*, false, true, false, Member, false>::execute();
|
||||||
test_main_template<void*, true, false, false, NonMember>::execute();
|
test_main_template<void*, true, false, false, NonMember, false>::execute();
|
||||||
test_main_template<void*, true, true, false, Base>::execute();
|
test_main_template<void*, true, true, false, Base, false>::execute();
|
||||||
|
|
||||||
|
test_main_template<void*, false, false, false, Base, true>::execute();
|
||||||
|
test_main_template<void*, false, true, false, Member, true>::execute();
|
||||||
|
test_main_template<void*, true, false, false, NonMember, true>::execute();
|
||||||
|
test_main_template<void*, true, true, false, Base, true>::execute();
|
||||||
|
|
||||||
//smart_ptr
|
//smart_ptr
|
||||||
test_main_template<smart_ptr<void>, false, false, false, Member>::execute();
|
test_main_template<smart_ptr<void>, false, false, false, Member, false>::execute();
|
||||||
test_main_template<smart_ptr<void>, false, true, false, NonMember>::execute();
|
test_main_template<smart_ptr<void>, false, true, false, NonMember, false>::execute();
|
||||||
test_main_template<smart_ptr<void>, true, false, false, Base>::execute();
|
test_main_template<smart_ptr<void>, true, false, false, Base, false>::execute();
|
||||||
test_main_template<smart_ptr<void>, true, true, false, Member>::execute();
|
test_main_template<smart_ptr<void>, true, true, false, Member, false>::execute();
|
||||||
|
|
||||||
|
test_main_template<smart_ptr<void>, false, false, false, Member, true>::execute();
|
||||||
|
test_main_template<smart_ptr<void>, false, true, false, NonMember, true>::execute();
|
||||||
|
test_main_template<smart_ptr<void>, true, false, false, Base, true>::execute();
|
||||||
|
|
||||||
////bounded_ptr (bool ConstantTimeSize, bool Map)
|
////bounded_ptr (bool ConstantTimeSize, bool Map)
|
||||||
//test_main_template_bptr< false, false >::execute();
|
//test_main_template_bptr< false, false >::execute();
|
||||||
|
@@ -50,12 +50,15 @@ void test_unordered<ContainerDefiner>::test_all (value_cont_type& values)
|
|||||||
{
|
{
|
||||||
typedef typename ContainerDefiner::template container
|
typedef typename ContainerDefiner::template container
|
||||||
<>::type unordered_type;
|
<>::type unordered_type;
|
||||||
|
const std::size_t ExtraBuckets = unordered_type::bucket_overhead;
|
||||||
|
|
||||||
typedef typename unordered_type::bucket_traits bucket_traits;
|
typedef typename unordered_type::bucket_traits bucket_traits;
|
||||||
typedef typename unordered_type::bucket_ptr bucket_ptr;
|
typedef typename unordered_type::bucket_ptr bucket_ptr;
|
||||||
|
|
||||||
{
|
{
|
||||||
typename unordered_type::bucket_type buckets [BucketSize];
|
typename unordered_type::bucket_type buckets [BucketSize + ExtraBuckets];
|
||||||
unordered_type testset
|
unordered_type testset
|
||||||
(bucket_traits(pointer_traits<bucket_ptr>::pointer_to(buckets[0]), BucketSize));
|
(bucket_traits(pointer_traits<bucket_ptr>::pointer_to(buckets[0]), sizeof(buckets)/sizeof(*buckets)));
|
||||||
testset.insert(values.begin(), values.end());
|
testset.insert(values.begin(), values.end());
|
||||||
test::test_container(testset);
|
test::test_container(testset);
|
||||||
testset.clear();
|
testset.clear();
|
||||||
@@ -74,9 +77,9 @@ void test_unordered<ContainerDefiner>::test_all (value_cont_type& values)
|
|||||||
value_cont_type vals(BucketSize);
|
value_cont_type vals(BucketSize);
|
||||||
for (std::size_t i = 0; i < BucketSize; ++i)
|
for (std::size_t i = 0; i < BucketSize; ++i)
|
||||||
(&vals[i])->value_ = (int)i;
|
(&vals[i])->value_ = (int)i;
|
||||||
typename unordered_type::bucket_type buckets [BucketSize];
|
typename unordered_type::bucket_type buckets[BucketSize + ExtraBuckets];
|
||||||
unordered_type testset(bucket_traits(
|
unordered_type testset(bucket_traits(
|
||||||
pointer_traits<bucket_ptr>::pointer_to(buckets[0]), BucketSize));
|
pointer_traits<bucket_ptr>::pointer_to(buckets[0]), sizeof(buckets)/sizeof(*buckets)));
|
||||||
testset.insert(vals.begin(), vals.end());
|
testset.insert(vals.begin(), vals.end());
|
||||||
test::test_iterator_forward(testset);
|
test::test_iterator_forward(testset);
|
||||||
}
|
}
|
||||||
@@ -95,6 +98,8 @@ void test_unordered<ContainerDefiner>::test_impl()
|
|||||||
{
|
{
|
||||||
typedef typename ContainerDefiner::template container
|
typedef typename ContainerDefiner::template container
|
||||||
<>::type unordered_type;
|
<>::type unordered_type;
|
||||||
|
const std::size_t ExtraBuckets = unordered_type::bucket_overhead;
|
||||||
|
|
||||||
typedef typename unordered_type::bucket_traits bucket_traits;
|
typedef typename unordered_type::bucket_traits bucket_traits;
|
||||||
typedef typename unordered_type::bucket_ptr bucket_ptr;
|
typedef typename unordered_type::bucket_ptr bucket_ptr;
|
||||||
|
|
||||||
@@ -102,9 +107,9 @@ void test_unordered<ContainerDefiner>::test_impl()
|
|||||||
for (std::size_t i = 0u; i < 5u; ++i)
|
for (std::size_t i = 0u; i < 5u; ++i)
|
||||||
values[i].value_ = (int)i;
|
values[i].value_ = (int)i;
|
||||||
|
|
||||||
typename unordered_type::bucket_type buckets [BucketSize];
|
typename unordered_type::bucket_type buckets[BucketSize + ExtraBuckets];
|
||||||
unordered_type testset(bucket_traits(
|
unordered_type testset(bucket_traits(
|
||||||
pointer_traits<bucket_ptr>::pointer_to(buckets[0]), BucketSize));
|
pointer_traits<bucket_ptr>::pointer_to(buckets[0]), sizeof(buckets)/sizeof(*buckets)));
|
||||||
|
|
||||||
for (std::size_t i = 0u; i < 5u; ++i)
|
for (std::size_t i = 0u; i < 5u; ++i)
|
||||||
testset.insert (values[i]);
|
testset.insert (values[i]);
|
||||||
@@ -123,13 +128,15 @@ void test_unordered<ContainerDefiner>::test_sort(value_cont_type& values)
|
|||||||
{
|
{
|
||||||
typedef typename ContainerDefiner::template container
|
typedef typename ContainerDefiner::template container
|
||||||
<>::type unordered_type;
|
<>::type unordered_type;
|
||||||
|
const std::size_t ExtraBuckets = unordered_type::bucket_overhead;
|
||||||
|
|
||||||
typedef typename unordered_type::bucket_traits bucket_traits;
|
typedef typename unordered_type::bucket_traits bucket_traits;
|
||||||
typedef typename unordered_type::bucket_ptr bucket_ptr;
|
typedef typename unordered_type::bucket_ptr bucket_ptr;
|
||||||
|
|
||||||
typename unordered_type::bucket_type buckets [BucketSize];
|
typename unordered_type::bucket_type buckets[BucketSize + ExtraBuckets];
|
||||||
unordered_type testset1
|
unordered_type testset1
|
||||||
(values.begin(), values.end(), bucket_traits
|
(values.begin(), values.end(), bucket_traits
|
||||||
(pointer_traits<bucket_ptr>::pointer_to(buckets[0]), BucketSize));
|
(pointer_traits<bucket_ptr>::pointer_to(buckets[0]), sizeof(buckets)/sizeof(*buckets)));
|
||||||
|
|
||||||
if(unordered_type::incremental){
|
if(unordered_type::incremental){
|
||||||
{ int init_values [] = { 4, 5, 1, 2, 2, 3 };
|
{ int init_values [] = { 4, 5, 1, 2, 2, 3 };
|
||||||
@@ -147,16 +154,16 @@ void test_unordered<ContainerDefiner>::test_sort(value_cont_type& values)
|
|||||||
template<class ContainerDefiner>
|
template<class ContainerDefiner>
|
||||||
void test_unordered<ContainerDefiner>::test_insert(value_cont_type& values, detail::false_) //not multikey
|
void test_unordered<ContainerDefiner>::test_insert(value_cont_type& values, detail::false_) //not multikey
|
||||||
{
|
{
|
||||||
|
|
||||||
typedef typename ContainerDefiner::template container
|
typedef typename ContainerDefiner::template container
|
||||||
<>::type unordered_set_type;
|
<>::type unordered_set_type;
|
||||||
typedef typename unordered_set_type::bucket_traits bucket_traits;
|
typedef typename unordered_set_type::bucket_traits bucket_traits;
|
||||||
typedef typename unordered_set_type::key_of_value key_of_value;
|
typedef typename unordered_set_type::key_of_value key_of_value;
|
||||||
|
|
||||||
typename unordered_set_type::bucket_type buckets [BucketSize];
|
const std::size_t ExtraBuckets = unordered_set_type::bucket_overhead;
|
||||||
|
typename unordered_set_type::bucket_type buckets[BucketSize + ExtraBuckets];
|
||||||
unordered_set_type testset(bucket_traits(
|
unordered_set_type testset(bucket_traits(
|
||||||
pointer_traits<typename unordered_set_type::bucket_ptr>::
|
pointer_traits<typename unordered_set_type::bucket_ptr>::
|
||||||
pointer_to(buckets[0]), BucketSize));
|
pointer_to(buckets[0]), sizeof(buckets)/sizeof(*buckets)));
|
||||||
testset.insert(&values[0] + 2, &values[0] + 5);
|
testset.insert(&values[0] + 2, &values[0] + 5);
|
||||||
|
|
||||||
typename unordered_set_type::insert_commit_data commit_data;
|
typename unordered_set_type::insert_commit_data commit_data;
|
||||||
@@ -206,15 +213,16 @@ void test_unordered<ContainerDefiner>::test_insert(value_cont_type& values, deta
|
|||||||
{
|
{
|
||||||
typedef typename ContainerDefiner::template container
|
typedef typename ContainerDefiner::template container
|
||||||
<>::type unordered_type;
|
<>::type unordered_type;
|
||||||
|
const std::size_t ExtraBuckets = unordered_type::bucket_overhead;
|
||||||
|
|
||||||
typedef typename unordered_type::bucket_traits bucket_traits;
|
typedef typename unordered_type::bucket_traits bucket_traits;
|
||||||
typedef typename unordered_type::bucket_ptr bucket_ptr;
|
typedef typename unordered_type::bucket_ptr bucket_ptr;
|
||||||
typedef typename unordered_type::iterator iterator;
|
typedef typename unordered_type::iterator iterator;
|
||||||
typedef typename unordered_type::key_type key_type;
|
typedef typename unordered_type::key_type key_type;
|
||||||
{
|
{
|
||||||
typename unordered_type::bucket_type buckets [BucketSize];
|
typename unordered_type::bucket_type buckets[BucketSize + ExtraBuckets];
|
||||||
unordered_type testset(bucket_traits(
|
unordered_type testset(bucket_traits(
|
||||||
pointer_traits<bucket_ptr>::pointer_to(buckets[0]), BucketSize));
|
pointer_traits<bucket_ptr>::pointer_to(buckets[0]), sizeof(buckets)/sizeof(*buckets)));
|
||||||
|
|
||||||
testset.insert(&values[0] + 2, &values[0] + 5);
|
testset.insert(&values[0] + 2, &values[0] + 5);
|
||||||
|
|
||||||
@@ -251,9 +259,9 @@ void test_unordered<ContainerDefiner>::test_insert(value_cont_type& values, deta
|
|||||||
BOOST_TEST (testset.empty() == true);
|
BOOST_TEST (testset.empty() == true);
|
||||||
|
|
||||||
//Now with a single bucket
|
//Now with a single bucket
|
||||||
typename unordered_type::bucket_type single_bucket[1];
|
typename unordered_type::bucket_type single_bucket[1u + ExtraBuckets];
|
||||||
unordered_type testset2(bucket_traits(
|
unordered_type testset2(bucket_traits(
|
||||||
pointer_traits<bucket_ptr>::pointer_to(single_bucket[0]), 1));
|
pointer_traits<bucket_ptr>::pointer_to(single_bucket[0]), sizeof(single_bucket)/sizeof(*single_bucket)));
|
||||||
testset2.insert(&values[0], &values[0] + values.size());
|
testset2.insert(&values[0], &values[0] + values.size());
|
||||||
BOOST_TEST (testset2.erase(key_type(5)) == 1);
|
BOOST_TEST (testset2.erase(key_type(5)) == 1);
|
||||||
BOOST_TEST (testset2.erase(key_type(2)) == 2);
|
BOOST_TEST (testset2.erase(key_type(2)) == 2);
|
||||||
@@ -294,9 +302,9 @@ void test_unordered<ContainerDefiner>::test_insert(value_cont_type& values, deta
|
|||||||
BOOST_TEST (testset.empty() == true);
|
BOOST_TEST (testset.empty() == true);
|
||||||
|
|
||||||
//Now with a single bucket
|
//Now with a single bucket
|
||||||
typename unordered_type::bucket_type single_bucket[1];
|
typename unordered_type::bucket_type single_bucket[1u + ExtraBuckets];
|
||||||
unordered_type testset2(bucket_traits(
|
unordered_type testset2(bucket_traits(
|
||||||
pointer_traits<bucket_ptr>::pointer_to(single_bucket[0]), 1));
|
pointer_traits<bucket_ptr>::pointer_to(single_bucket[0]), sizeof(single_bucket)/sizeof(*single_bucket)));
|
||||||
testset2.insert(&values[0], &values[0] + values.size());
|
testset2.insert(&values[0], &values[0] + values.size());
|
||||||
BOOST_TEST (testset2.erase(key_type(5)) == 1);
|
BOOST_TEST (testset2.erase(key_type(5)) == 1);
|
||||||
BOOST_TEST (testset2.erase(key_type(2)) == 2);
|
BOOST_TEST (testset2.erase(key_type(2)) == 2);
|
||||||
@@ -310,13 +318,13 @@ void test_unordered<ContainerDefiner>::test_insert(value_cont_type& values, deta
|
|||||||
//Now erase just one per loop
|
//Now erase just one per loop
|
||||||
const int random_init[] = { 3, 2, 4, 1, 5, 2, 2 };
|
const int random_init[] = { 3, 2, 4, 1, 5, 2, 2 };
|
||||||
const std::size_t random_size = sizeof(random_init)/sizeof(random_init[0]);
|
const std::size_t random_size = sizeof(random_init)/sizeof(random_init[0]);
|
||||||
typename unordered_type::bucket_type single_bucket[1];
|
typename unordered_type::bucket_type single_bucket[1u + ExtraBuckets];
|
||||||
for(std::size_t i = 0u, max = random_size; i != max; ++i){
|
for(std::size_t i = 0u, max = random_size; i != max; ++i){
|
||||||
value_cont_type data (random_size);
|
value_cont_type data (random_size);
|
||||||
for (std::size_t j = 0; j < random_size; ++j)
|
for (std::size_t j = 0; j < random_size; ++j)
|
||||||
data[j].value_ = random_init[j];
|
data[j].value_ = random_init[j];
|
||||||
unordered_type testset_new(bucket_traits(
|
unordered_type testset_new(bucket_traits(
|
||||||
pointer_traits<bucket_ptr>::pointer_to(single_bucket[0]), 1));
|
pointer_traits<bucket_ptr>::pointer_to(single_bucket[0]), sizeof(single_bucket)/sizeof(*single_bucket)));
|
||||||
testset_new.insert(&data[0], &data[0]+max);
|
testset_new.insert(&data[0], &data[0]+max);
|
||||||
testset_new.erase(testset_new.iterator_to(data[i]));
|
testset_new.erase(testset_new.iterator_to(data[i]));
|
||||||
BOOST_TEST (testset_new.size() == (max -1));
|
BOOST_TEST (testset_new.size() == (max -1));
|
||||||
@@ -327,16 +335,14 @@ void test_unordered<ContainerDefiner>::test_insert(value_cont_type& values, deta
|
|||||||
const std::size_t LoadFactor = 3;
|
const std::size_t LoadFactor = 3;
|
||||||
const std::size_t NumIterations = BucketSize*LoadFactor;
|
const std::size_t NumIterations = BucketSize*LoadFactor;
|
||||||
value_cont_type random_init(NumIterations);//Preserve memory
|
value_cont_type random_init(NumIterations);//Preserve memory
|
||||||
value_cont_type set_tester;
|
|
||||||
set_tester.reserve(NumIterations);
|
|
||||||
|
|
||||||
//Initialize values
|
//Initialize values
|
||||||
for (std::size_t i = 0u; i < NumIterations; ++i){
|
for (std::size_t i = 0u; i < NumIterations; ++i){
|
||||||
random_init[i].value_ = (int)i*2;//(i/LoadFactor)*LoadFactor;
|
random_init[i].value_ = (int)i*2;
|
||||||
}
|
}
|
||||||
|
|
||||||
typename unordered_type::bucket_type buckets [BucketSize];
|
typename unordered_type::bucket_type buckets[BucketSize + ExtraBuckets];
|
||||||
bucket_traits btraits(pointer_traits<bucket_ptr>::pointer_to(buckets[0]), BucketSize);
|
bucket_traits btraits(pointer_traits<bucket_ptr>::pointer_to(buckets[0]), sizeof(buckets)/sizeof(*buckets));
|
||||||
|
|
||||||
for(std::size_t initial_pos = 0; initial_pos != (NumIterations+1u); ++initial_pos){
|
for(std::size_t initial_pos = 0; initial_pos != (NumIterations+1u); ++initial_pos){
|
||||||
for(std::size_t final_pos = initial_pos; final_pos != (NumIterations+1); ++final_pos){
|
for(std::size_t final_pos = initial_pos; final_pos != (NumIterations+1); ++final_pos){
|
||||||
@@ -370,20 +376,25 @@ void test_unordered<ContainerDefiner>::test_insert(value_cont_type& values, deta
|
|||||||
//Now test...
|
//Now test...
|
||||||
BOOST_TEST ((random_init.size() - erased_cnt) == testset.size());
|
BOOST_TEST ((random_init.size() - erased_cnt) == testset.size());
|
||||||
|
|
||||||
//Create an ordered copy of the intrusive container
|
//for non-linear buckets is_linked is a reliable marker for a node
|
||||||
set_tester.insert(set_tester.end(), testset.begin(), testset.end());
|
//inserted in a hash map, but not for linear buckets, which are null-ended
|
||||||
std::sort(set_tester.begin(), set_tester.end());
|
BOOST_IF_CONSTEXPR(!unordered_type::linear_buckets){
|
||||||
{
|
value_cont_type set_tester;
|
||||||
typename value_cont_type::iterator it = set_tester.begin(), itend = set_tester.end();
|
set_tester.reserve(NumIterations);
|
||||||
typename value_cont_type::iterator random_init_it(random_init.begin());
|
//Create an ordered copy of the intrusive container
|
||||||
for( ; it != itend; ++it){
|
set_tester.insert(set_tester.end(), testset.begin(), testset.end());
|
||||||
while(!random_init_it->is_linked())
|
std::sort(set_tester.begin(), set_tester.end());
|
||||||
|
{
|
||||||
|
typename value_cont_type::iterator it = set_tester.begin(), itend = set_tester.end();
|
||||||
|
typename value_cont_type::iterator random_init_it(random_init.begin());
|
||||||
|
for( ; it != itend; ++it){
|
||||||
|
while(!random_init_it->is_linked())
|
||||||
|
++random_init_it;
|
||||||
|
BOOST_TEST(*it == *random_init_it);
|
||||||
++random_init_it;
|
++random_init_it;
|
||||||
BOOST_TEST(*it == *random_init_it);
|
}
|
||||||
++random_init_it;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
set_tester.clear();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -395,16 +406,17 @@ void test_unordered<ContainerDefiner>::test_swap(value_cont_type& values)
|
|||||||
{
|
{
|
||||||
typedef typename ContainerDefiner::template container
|
typedef typename ContainerDefiner::template container
|
||||||
<>::type unordered_type;
|
<>::type unordered_type;
|
||||||
|
const std::size_t ExtraBuckets = unordered_type::bucket_overhead;
|
||||||
|
|
||||||
typedef typename unordered_type::bucket_traits bucket_traits;
|
typedef typename unordered_type::bucket_traits bucket_traits;
|
||||||
typedef typename unordered_type::bucket_ptr bucket_ptr;
|
typedef typename unordered_type::bucket_ptr bucket_ptr;
|
||||||
typename unordered_type::bucket_type buckets [BucketSize];
|
typename unordered_type::bucket_type buckets[BucketSize + ExtraBuckets];
|
||||||
|
|
||||||
typename unordered_type::bucket_type buckets2 [BucketSize];
|
typename unordered_type::bucket_type buckets2[BucketSize + ExtraBuckets];
|
||||||
unordered_type testset1(&values[0], &values[0] + 2,
|
unordered_type testset1(&values[0], &values[0] + 2,
|
||||||
bucket_traits(pointer_traits<bucket_ptr>::pointer_to(buckets[0]), BucketSize));
|
bucket_traits(pointer_traits<bucket_ptr>::pointer_to(buckets[0]), sizeof(buckets)/sizeof(*buckets)));
|
||||||
unordered_type testset2(bucket_traits(
|
unordered_type testset2(bucket_traits(
|
||||||
pointer_traits<bucket_ptr>::pointer_to(buckets2[0]), BucketSize));
|
pointer_traits<bucket_ptr>::pointer_to(buckets2[0]), sizeof(buckets2)/sizeof(*buckets2)));
|
||||||
|
|
||||||
testset2.insert (&values[0] + 2, &values[0] + 6);
|
testset2.insert (&values[0] + 2, &values[0] + 6);
|
||||||
testset1.swap (testset2);
|
testset1.swap (testset2);
|
||||||
@@ -443,14 +455,16 @@ void test_unordered<ContainerDefiner>::test_rehash(value_cont_type& values, deta
|
|||||||
typedef typename ContainerDefiner::template container
|
typedef typename ContainerDefiner::template container
|
||||||
<>::type unordered_type;
|
<>::type unordered_type;
|
||||||
|
|
||||||
|
const std::size_t ExtraBuckets = unordered_type::bucket_overhead;
|
||||||
|
|
||||||
typedef typename unordered_type::bucket_traits bucket_traits;
|
typedef typename unordered_type::bucket_traits bucket_traits;
|
||||||
typedef typename unordered_type::bucket_ptr bucket_ptr;
|
typedef typename unordered_type::bucket_ptr bucket_ptr;
|
||||||
//Build a uset
|
//Build a uset
|
||||||
typename unordered_type::bucket_type buckets1 [BucketSize];
|
typename unordered_type::bucket_type buckets1[BucketSize + ExtraBuckets];
|
||||||
typename unordered_type::bucket_type buckets2 [BucketSize*2];
|
typename unordered_type::bucket_type buckets2[BucketSize*2u + ExtraBuckets];
|
||||||
unordered_type testset1(&values[0], &values[0] + values.size(),
|
unordered_type testset1(&values[0], &values[0] + values.size(),
|
||||||
bucket_traits(pointer_traits<bucket_ptr>::
|
bucket_traits(pointer_traits<bucket_ptr>::
|
||||||
pointer_to(buckets1[0]), BucketSize));
|
pointer_to(buckets1[0]), sizeof(buckets1)/sizeof(*buckets1)));
|
||||||
//Test current state
|
//Test current state
|
||||||
BOOST_TEST(testset1.split_count() == BucketSize/2);
|
BOOST_TEST(testset1.split_count() == BucketSize/2);
|
||||||
{ int init_values [] = { 4, 5, 1, 2, 2, 3 };
|
{ int init_values [] = { 4, 5, 1, 2, 2, 3 };
|
||||||
@@ -478,8 +492,8 @@ void test_unordered<ContainerDefiner>::test_rehash(value_cont_type& values, deta
|
|||||||
//
|
//
|
||||||
//This incremental rehash should fail because the new size is not twice the original
|
//This incremental rehash should fail because the new size is not twice the original
|
||||||
BOOST_TEST(testset1.incremental_rehash(bucket_traits(
|
BOOST_TEST(testset1.incremental_rehash(bucket_traits(
|
||||||
pointer_traits<bucket_ptr>::
|
pointer_traits<bucket_ptr>::pointer_to(buckets1[0])
|
||||||
pointer_to(buckets1[0]), BucketSize)) == false);
|
, sizeof(buckets1)/sizeof(*buckets1))) == false);
|
||||||
BOOST_TEST(testset1.split_count() == BucketSize);
|
BOOST_TEST(testset1.split_count() == BucketSize);
|
||||||
{ int init_values [] = { 1, 2, 2, 3, 4, 5 };
|
{ int init_values [] = { 1, 2, 2, 3, 4, 5 };
|
||||||
TEST_INTRUSIVE_SEQUENCE_MAYBEUNIQUE( init_values, testset1 ); }
|
TEST_INTRUSIVE_SEQUENCE_MAYBEUNIQUE( init_values, testset1 ); }
|
||||||
@@ -490,7 +504,8 @@ void test_unordered<ContainerDefiner>::test_rehash(value_cont_type& values, deta
|
|||||||
//This incremental rehash should fail because the new size is not twice the original
|
//This incremental rehash should fail because the new size is not twice the original
|
||||||
BOOST_TEST(testset1.incremental_rehash(bucket_traits(
|
BOOST_TEST(testset1.incremental_rehash(bucket_traits(
|
||||||
pointer_traits<bucket_ptr>::
|
pointer_traits<bucket_ptr>::
|
||||||
pointer_to(buckets2[0]), BucketSize)) == false);
|
pointer_to(buckets2[0])
|
||||||
|
, BucketSize + ExtraBuckets)) == false);
|
||||||
BOOST_TEST(testset1.split_count() == BucketSize);
|
BOOST_TEST(testset1.split_count() == BucketSize);
|
||||||
{ int init_values [] = { 1, 2, 2, 3, 4, 5 };
|
{ int init_values [] = { 1, 2, 2, 3, 4, 5 };
|
||||||
TEST_INTRUSIVE_SEQUENCE_MAYBEUNIQUE( init_values, testset1 ); }
|
TEST_INTRUSIVE_SEQUENCE_MAYBEUNIQUE( init_values, testset1 ); }
|
||||||
@@ -499,7 +514,8 @@ void test_unordered<ContainerDefiner>::test_rehash(value_cont_type& values, deta
|
|||||||
//and split_count is the same as the old bucket count
|
//and split_count is the same as the old bucket count
|
||||||
BOOST_TEST(testset1.incremental_rehash(bucket_traits(
|
BOOST_TEST(testset1.incremental_rehash(bucket_traits(
|
||||||
pointer_traits<bucket_ptr>::
|
pointer_traits<bucket_ptr>::
|
||||||
pointer_to(buckets2[0]), BucketSize*2)) == true);
|
pointer_to(buckets2[0])
|
||||||
|
, sizeof(buckets2)/sizeof(*buckets2))) == true);
|
||||||
BOOST_TEST(testset1.split_count() == BucketSize);
|
BOOST_TEST(testset1.split_count() == BucketSize);
|
||||||
{ int init_values [] = { 1, 2, 2, 3, 4, 5 };
|
{ int init_values [] = { 1, 2, 2, 3, 4, 5 };
|
||||||
TEST_INTRUSIVE_SEQUENCE_MAYBEUNIQUE( init_values, testset1 ); }
|
TEST_INTRUSIVE_SEQUENCE_MAYBEUNIQUE( init_values, testset1 ); }
|
||||||
@@ -508,7 +524,8 @@ void test_unordered<ContainerDefiner>::test_rehash(value_cont_type& values, deta
|
|||||||
//and split_count is the same as the new bucket count
|
//and split_count is the same as the new bucket count
|
||||||
BOOST_TEST(testset1.incremental_rehash(bucket_traits(
|
BOOST_TEST(testset1.incremental_rehash(bucket_traits(
|
||||||
pointer_traits<bucket_ptr>::
|
pointer_traits<bucket_ptr>::
|
||||||
pointer_to(buckets1[0]), BucketSize)) == true);
|
pointer_to(buckets1[0])
|
||||||
|
, sizeof(buckets1)/sizeof(*buckets1))) == true);
|
||||||
BOOST_TEST(testset1.split_count() == BucketSize);
|
BOOST_TEST(testset1.split_count() == BucketSize);
|
||||||
{ int init_values [] = { 1, 2, 2, 3, 4, 5 };
|
{ int init_values [] = { 1, 2, 2, 3, 4, 5 };
|
||||||
TEST_INTRUSIVE_SEQUENCE_MAYBEUNIQUE( init_values, testset1 ); }
|
TEST_INTRUSIVE_SEQUENCE_MAYBEUNIQUE( init_values, testset1 ); }
|
||||||
@@ -516,7 +533,8 @@ void test_unordered<ContainerDefiner>::test_rehash(value_cont_type& values, deta
|
|||||||
//Shrink rehash
|
//Shrink rehash
|
||||||
testset1.rehash(bucket_traits(
|
testset1.rehash(bucket_traits(
|
||||||
pointer_traits<bucket_ptr>::
|
pointer_traits<bucket_ptr>::
|
||||||
pointer_to(buckets1[0]), 4));
|
pointer_to(buckets1[0])
|
||||||
|
, (sizeof(buckets1) / sizeof(*buckets1)- ExtraBuckets) / 2u + ExtraBuckets));
|
||||||
BOOST_TEST (testset1.incremental_rehash() == false);
|
BOOST_TEST (testset1.incremental_rehash() == false);
|
||||||
{ int init_values [] = { 4, 5, 1, 2, 2, 3 };
|
{ int init_values [] = { 4, 5, 1, 2, 2, 3 };
|
||||||
TEST_INTRUSIVE_SEQUENCE_MAYBEUNIQUE( init_values, testset1 ); }
|
TEST_INTRUSIVE_SEQUENCE_MAYBEUNIQUE( init_values, testset1 ); }
|
||||||
@@ -524,7 +542,8 @@ void test_unordered<ContainerDefiner>::test_rehash(value_cont_type& values, deta
|
|||||||
//Shrink rehash again
|
//Shrink rehash again
|
||||||
testset1.rehash(bucket_traits(
|
testset1.rehash(bucket_traits(
|
||||||
pointer_traits<bucket_ptr>::
|
pointer_traits<bucket_ptr>::
|
||||||
pointer_to(buckets1[0]), 2));
|
pointer_to(buckets1[0])
|
||||||
|
, (sizeof(buckets1) / sizeof(*buckets1) - ExtraBuckets) / 4u + ExtraBuckets));
|
||||||
BOOST_TEST (testset1.incremental_rehash() == false);
|
BOOST_TEST (testset1.incremental_rehash() == false);
|
||||||
{ int init_values [] = { 2, 2, 4, 3, 5, 1 };
|
{ int init_values [] = { 2, 2, 4, 3, 5, 1 };
|
||||||
TEST_INTRUSIVE_SEQUENCE_MAYBEUNIQUE( init_values, testset1 ); }
|
TEST_INTRUSIVE_SEQUENCE_MAYBEUNIQUE( init_values, testset1 ); }
|
||||||
@@ -532,7 +551,11 @@ void test_unordered<ContainerDefiner>::test_rehash(value_cont_type& values, deta
|
|||||||
//Growing rehash
|
//Growing rehash
|
||||||
testset1.rehash(bucket_traits(
|
testset1.rehash(bucket_traits(
|
||||||
pointer_traits<bucket_ptr>::
|
pointer_traits<bucket_ptr>::
|
||||||
pointer_to(buckets1[0]), BucketSize));
|
pointer_to(buckets1[0])
|
||||||
|
, sizeof(buckets1)/sizeof(*buckets1)));
|
||||||
|
|
||||||
|
{ int init_values [] = { 1, 2, 2, 3, 4, 5 };
|
||||||
|
TEST_INTRUSIVE_SEQUENCE_MAYBEUNIQUE( init_values, testset1 ); }
|
||||||
|
|
||||||
//Full rehash (no effects)
|
//Full rehash (no effects)
|
||||||
testset1.full_rehash();
|
testset1.full_rehash();
|
||||||
@@ -571,39 +594,40 @@ void test_unordered<ContainerDefiner>::test_rehash(value_cont_type& values, deta
|
|||||||
{
|
{
|
||||||
typedef typename ContainerDefiner::template container
|
typedef typename ContainerDefiner::template container
|
||||||
<>::type unordered_type;
|
<>::type unordered_type;
|
||||||
|
const std::size_t ExtraBuckets = unordered_type::bucket_overhead;
|
||||||
|
|
||||||
typedef typename unordered_type::bucket_traits bucket_traits;
|
typedef typename unordered_type::bucket_traits bucket_traits;
|
||||||
typedef typename unordered_type::bucket_ptr bucket_ptr;
|
typedef typename unordered_type::bucket_ptr bucket_ptr;
|
||||||
|
|
||||||
typename unordered_type::bucket_type buckets1 [BucketSize];
|
typename unordered_type::bucket_type buckets1[BucketSize + ExtraBuckets];
|
||||||
typename unordered_type::bucket_type buckets2 [2];
|
typename unordered_type::bucket_type buckets2 [2 + ExtraBuckets];
|
||||||
typename unordered_type::bucket_type buckets3 [BucketSize*2];
|
typename unordered_type::bucket_type buckets3[BucketSize*2 + ExtraBuckets];
|
||||||
|
|
||||||
unordered_type testset1(&values[0], &values[0] + 6, bucket_traits(
|
unordered_type testset1(&values[0], &values[0] + 6, bucket_traits(
|
||||||
pointer_traits<bucket_ptr>::
|
pointer_traits<bucket_ptr>::
|
||||||
pointer_to(buckets1[0]), BucketSize));
|
pointer_to(buckets1[0]), sizeof(buckets1)/sizeof(*buckets1)));
|
||||||
{ int init_values [] = { 1, 2, 2, 3, 4, 5 };
|
{ int init_values [] = { 1, 2, 2, 3, 4, 5 };
|
||||||
TEST_INTRUSIVE_SEQUENCE_MAYBEUNIQUE( init_values, testset1 ); }
|
TEST_INTRUSIVE_SEQUENCE_MAYBEUNIQUE( init_values, testset1 ); }
|
||||||
|
|
||||||
testset1.rehash(bucket_traits(
|
testset1.rehash(bucket_traits(
|
||||||
pointer_traits<bucket_ptr>::pointer_to(buckets2[0]), 2));
|
pointer_traits<bucket_ptr>::pointer_to(buckets2[0]), BucketSize/4 + ExtraBuckets));
|
||||||
{ int init_values [] = { 4, 2, 2, 5, 3, 1 };
|
{ int init_values [] = { 4, 2, 2, 5, 3, 1 };
|
||||||
TEST_INTRUSIVE_SEQUENCE_MAYBEUNIQUE( init_values, testset1 ); }
|
TEST_INTRUSIVE_SEQUENCE_MAYBEUNIQUE( init_values, testset1 ); }
|
||||||
|
|
||||||
testset1.rehash(bucket_traits(
|
testset1.rehash(bucket_traits(
|
||||||
pointer_traits<bucket_ptr>::pointer_to(buckets3[0]), BucketSize*2));
|
pointer_traits<bucket_ptr>::pointer_to(buckets3[0]), sizeof(buckets3) / sizeof(*buckets3)));
|
||||||
{ int init_values [] = { 1, 2, 2, 3, 4, 5 };
|
{ int init_values [] = { 1, 2, 2, 3, 4, 5 };
|
||||||
TEST_INTRUSIVE_SEQUENCE_MAYBEUNIQUE( init_values, testset1 ); }
|
TEST_INTRUSIVE_SEQUENCE_MAYBEUNIQUE( init_values, testset1 ); }
|
||||||
|
|
||||||
//Now rehash reducing the buckets
|
//Now rehash reducing the buckets
|
||||||
testset1.rehash(bucket_traits(
|
testset1.rehash(bucket_traits(
|
||||||
pointer_traits<bucket_ptr>::pointer_to(buckets3[0]), 2));
|
pointer_traits<bucket_ptr>::pointer_to(buckets3[0]), BucketSize / 4 + ExtraBuckets));
|
||||||
{ int init_values [] = { 4, 2, 2, 5, 3, 1 };
|
{ int init_values [] = { 4, 2, 2, 5, 3, 1 };
|
||||||
TEST_INTRUSIVE_SEQUENCE_MAYBEUNIQUE( init_values, testset1 ); }
|
TEST_INTRUSIVE_SEQUENCE_MAYBEUNIQUE( init_values, testset1 ); }
|
||||||
|
|
||||||
//Now rehash increasing the buckets
|
//Now rehash increasing the buckets
|
||||||
testset1.rehash(bucket_traits(
|
testset1.rehash(bucket_traits(
|
||||||
pointer_traits<bucket_ptr>::pointer_to(buckets3[0]), BucketSize*2));
|
pointer_traits<bucket_ptr>::pointer_to(buckets3[0]), sizeof(buckets3) / sizeof(*buckets3)));
|
||||||
{ int init_values [] = { 1, 2, 2, 3, 4, 5 };
|
{ int init_values [] = { 1, 2, 2, 3, 4, 5 };
|
||||||
TEST_INTRUSIVE_SEQUENCE_MAYBEUNIQUE( init_values, testset1 ); }
|
TEST_INTRUSIVE_SEQUENCE_MAYBEUNIQUE( init_values, testset1 ); }
|
||||||
|
|
||||||
@@ -625,10 +649,11 @@ void test_unordered<ContainerDefiner>::test_find(value_cont_type& values)
|
|||||||
typedef typename unordered_type::bucket_ptr bucket_ptr;
|
typedef typename unordered_type::bucket_ptr bucket_ptr;
|
||||||
typedef typename unordered_type::key_of_value key_of_value;
|
typedef typename unordered_type::key_of_value key_of_value;
|
||||||
const bool is_multikey = boost::intrusive::test::is_multikey_true<unordered_type>::value;
|
const bool is_multikey = boost::intrusive::test::is_multikey_true<unordered_type>::value;
|
||||||
|
const std::size_t ExtraBuckets = unordered_type::bucket_overhead;
|
||||||
|
|
||||||
typename unordered_type::bucket_type buckets[BucketSize];
|
typename unordered_type::bucket_type buckets[BucketSize + ExtraBuckets];
|
||||||
unordered_type testset(values.begin(), values.end(), bucket_traits(
|
unordered_type testset(values.begin(), values.end(), bucket_traits(
|
||||||
pointer_traits<bucket_ptr>::pointer_to(buckets[0]), BucketSize));
|
pointer_traits<bucket_ptr>::pointer_to(buckets[0]), sizeof(buckets)/sizeof(*buckets)));
|
||||||
|
|
||||||
typedef typename unordered_type::iterator iterator;
|
typedef typename unordered_type::iterator iterator;
|
||||||
|
|
||||||
@@ -657,6 +682,8 @@ void test_unordered<ContainerDefiner>::test_clone(value_cont_type& values)
|
|||||||
{
|
{
|
||||||
typedef typename ContainerDefiner::template container
|
typedef typename ContainerDefiner::template container
|
||||||
<>::type unordered_type;
|
<>::type unordered_type;
|
||||||
|
const std::size_t ExtraBuckets = unordered_type::bucket_overhead;
|
||||||
|
|
||||||
typedef typename unordered_type::value_type value_type;
|
typedef typename unordered_type::value_type value_type;
|
||||||
typedef std::multiset<value_type> std_multiset_t;
|
typedef std::multiset<value_type> std_multiset_t;
|
||||||
|
|
||||||
@@ -665,12 +692,12 @@ void test_unordered<ContainerDefiner>::test_clone(value_cont_type& values)
|
|||||||
|
|
||||||
{
|
{
|
||||||
//Test with equal bucket arrays
|
//Test with equal bucket arrays
|
||||||
typename unordered_type::bucket_type buckets1 [BucketSize];
|
typename unordered_type::bucket_type buckets1[BucketSize + ExtraBuckets];
|
||||||
typename unordered_type::bucket_type buckets2 [BucketSize];
|
typename unordered_type::bucket_type buckets2[BucketSize + ExtraBuckets];
|
||||||
unordered_type testset1 (values.begin(), values.end(), bucket_traits(
|
unordered_type testset1 (values.begin(), values.end(), bucket_traits(
|
||||||
pointer_traits<bucket_ptr>::pointer_to(buckets1[0]), BucketSize));
|
pointer_traits<bucket_ptr>::pointer_to(buckets1[0]), sizeof(buckets1)/sizeof(*buckets1)));
|
||||||
unordered_type testset2 (bucket_traits(
|
unordered_type testset2 (bucket_traits(
|
||||||
pointer_traits<bucket_ptr>::pointer_to(buckets2[0]), BucketSize));
|
pointer_traits<bucket_ptr>::pointer_to(buckets2[0]), sizeof(buckets2)/sizeof(*buckets2)));
|
||||||
|
|
||||||
testset2.clone_from(testset1, test::new_cloner<value_type>(), test::delete_disposer<value_type>());
|
testset2.clone_from(testset1, test::new_cloner<value_type>(), test::delete_disposer<value_type>());
|
||||||
BOOST_TEST(testset1 == testset2);
|
BOOST_TEST(testset1 == testset2);
|
||||||
@@ -692,12 +719,12 @@ void test_unordered<ContainerDefiner>::test_clone(value_cont_type& values)
|
|||||||
}
|
}
|
||||||
{
|
{
|
||||||
//Test with bigger source bucket arrays
|
//Test with bigger source bucket arrays
|
||||||
typename unordered_type::bucket_type buckets1 [BucketSize*2];
|
typename unordered_type::bucket_type buckets1[BucketSize*2u + ExtraBuckets];
|
||||||
typename unordered_type::bucket_type buckets2 [BucketSize];
|
typename unordered_type::bucket_type buckets2[BucketSize + ExtraBuckets];
|
||||||
unordered_type testset1 (values.begin(), values.end(), bucket_traits(
|
unordered_type testset1 (values.begin(), values.end(), bucket_traits(
|
||||||
pointer_traits<bucket_ptr>::pointer_to(buckets1[0]), BucketSize*2));
|
pointer_traits<bucket_ptr>::pointer_to(buckets1[0]), sizeof(buckets1)/sizeof(*buckets1)));
|
||||||
unordered_type testset2 (bucket_traits(
|
unordered_type testset2 (bucket_traits(
|
||||||
pointer_traits<bucket_ptr>::pointer_to(buckets2[0]), BucketSize));
|
pointer_traits<bucket_ptr>::pointer_to(buckets2[0]), sizeof(buckets2)/sizeof(*buckets2)));
|
||||||
|
|
||||||
testset2.clone_from(testset1, test::new_cloner<value_type>(), test::delete_disposer<value_type>());
|
testset2.clone_from(testset1, test::new_cloner<value_type>(), test::delete_disposer<value_type>());
|
||||||
BOOST_TEST(testset1 == testset2);
|
BOOST_TEST(testset1 == testset2);
|
||||||
@@ -719,12 +746,12 @@ void test_unordered<ContainerDefiner>::test_clone(value_cont_type& values)
|
|||||||
}
|
}
|
||||||
{
|
{
|
||||||
//Test with smaller source bucket arrays
|
//Test with smaller source bucket arrays
|
||||||
typename unordered_type::bucket_type buckets1 [BucketSize];
|
typename unordered_type::bucket_type buckets1[BucketSize + ExtraBuckets];
|
||||||
typename unordered_type::bucket_type buckets2 [BucketSize*2];
|
typename unordered_type::bucket_type buckets2[BucketSize*2u + ExtraBuckets];
|
||||||
unordered_type testset1 (values.begin(), values.end(), bucket_traits(
|
unordered_type testset1 (values.begin(), values.end(), bucket_traits(
|
||||||
pointer_traits<bucket_ptr>::pointer_to(buckets1[0]), BucketSize));
|
pointer_traits<bucket_ptr>::pointer_to(buckets1[0]), sizeof(buckets1)/sizeof(*buckets1)));
|
||||||
unordered_type testset2 (bucket_traits(
|
unordered_type testset2 (bucket_traits(
|
||||||
pointer_traits<bucket_ptr>::pointer_to(buckets2[0]), BucketSize*2));
|
pointer_traits<bucket_ptr>::pointer_to(buckets2[0]), sizeof(buckets2)/sizeof(*buckets2)));
|
||||||
|
|
||||||
testset2.clone_from(testset1, test::new_cloner<value_type>(), test::delete_disposer<value_type>());
|
testset2.clone_from(testset1, test::new_cloner<value_type>(), test::delete_disposer<value_type>());
|
||||||
BOOST_TEST(testset1 == testset2);
|
BOOST_TEST(testset1 == testset2);
|
||||||
|
Reference in New Issue
Block a user