mirror of
https://github.com/boostorg/intrusive.git
synced 2025-07-31 21:14:48 +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_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]
|
||||
|
||||
* 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 intrusive{
|
||||
} //namespace boost{
|
||||
|
@@ -26,7 +26,10 @@
|
||||
#include <boost/intrusive/pointer_traits.hpp>
|
||||
#include <boost/intrusive/detail/mpl.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 <climits>
|
||||
#include <boost/move/core.hpp>
|
||||
@@ -35,10 +38,20 @@
|
||||
namespace boost {
|
||||
namespace intrusive {
|
||||
|
||||
template <class Slist>
|
||||
struct bucket_impl : public Slist
|
||||
template <class NodeTraits>
|
||||
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()
|
||||
{}
|
||||
|
||||
@@ -46,68 +59,22 @@ struct bucket_impl : public Slist
|
||||
{}
|
||||
|
||||
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&)
|
||||
{
|
||||
//This bucket is still in use!
|
||||
BOOST_INTRUSIVE_INVARIANT_ASSERT(Slist::empty());
|
||||
return *this;
|
||||
}
|
||||
{ return *this; }
|
||||
|
||||
BOOST_INTRUSIVE_FORCEINLINE node_ptr get_node_ptr()
|
||||
{ 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>
|
||||
struct hash_reduced_slist_node_traits
|
||||
@@ -133,22 +100,7 @@ struct reduced_slist_node_traits
|
||||
>::type type;
|
||||
};
|
||||
|
||||
template<class NodeTraits>
|
||||
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>
|
||||
template<class BucketValueTraits, bool LinearBuckets, bool IsConst>
|
||||
class hashtable_iterator
|
||||
{
|
||||
typedef typename BucketValueTraits::value_traits value_traits;
|
||||
@@ -166,24 +118,25 @@ class hashtable_iterator
|
||||
private:
|
||||
typedef typename value_traits::node_traits node_traits;
|
||||
typedef typename node_traits::node_ptr node_ptr;
|
||||
typedef typename get_slist_impl
|
||||
< typename reduced_slist_node_traits
|
||||
<node_traits>::type >::type slist_impl;
|
||||
typedef typename slist_impl::iterator siterator;
|
||||
typedef typename slist_impl::const_iterator const_siterator;
|
||||
typedef bucket_impl<slist_impl> bucket_type;
|
||||
typedef typename BucketValueTraits::bucket_type bucket_type;
|
||||
typedef typename bucket_type::node_traits slist_node_traits;
|
||||
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;
|
||||
typedef circular_slist_algorithms<slist_node_traits> slist_node_algorithms;
|
||||
|
||||
typedef typename pointer_traits
|
||||
<pointer>::template rebind_pointer
|
||||
< const BucketValueTraits >::type const_bucketvaltraits_ptr;
|
||||
typedef typename slist_impl::size_type size_type;
|
||||
class nat;
|
||||
typedef typename
|
||||
detail::if_c< IsConst
|
||||
, hashtable_iterator<BucketValueTraits, false>
|
||||
, hashtable_iterator<BucketValueTraits, LinearBuckets, false>
|
||||
, 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>::
|
||||
pointer_to(static_cast<typename node_traits::node&>(*p));
|
||||
@@ -211,8 +164,8 @@ class hashtable_iterator
|
||||
BOOST_INTRUSIVE_FORCEINLINE const siterator &slist_it() const
|
||||
{ return slist_it_; }
|
||||
|
||||
BOOST_INTRUSIVE_FORCEINLINE hashtable_iterator<BucketValueTraits, false> unconst() const
|
||||
{ return hashtable_iterator<BucketValueTraits, false>(this->slist_it(), this->get_bucket_value_traits()); }
|
||||
BOOST_INTRUSIVE_FORCEINLINE hashtable_iterator<BucketValueTraits, LinearBuckets, false> unconst() const
|
||||
{ return hashtable_iterator<BucketValueTraits, LinearBuckets, false>(this->slist_it(), this->get_bucket_value_traits()); }
|
||||
|
||||
BOOST_INTRUSIVE_FORCEINLINE hashtable_iterator& operator++()
|
||||
{ this->increment(); return *this; }
|
||||
@@ -252,33 +205,36 @@ class hashtable_iterator
|
||||
{ return traitsptr_->priv_bucket_traits(); }
|
||||
|
||||
private:
|
||||
|
||||
void increment()
|
||||
{
|
||||
const bucket_traits &rbuck_traits = this->priv_bucket_traits();
|
||||
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_;
|
||||
const typename slist_impl::node_ptr n = slist_it_.pointed_node();
|
||||
const siterator first_bucket_bbegin = buckets->end();
|
||||
if(first_bucket_bbegin.pointed_node() <= n && n <= buckets[buckets_len-1].cend().pointed_node()){
|
||||
const slist_node_ptr n = slist_it_.pointed_node();
|
||||
const siterator first_bucket_bbegin(buckets->get_node_ptr());
|
||||
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
|
||||
//1. get the bucket_impl from the iterator
|
||||
const bucket_type &b = static_cast<const bucket_type&>
|
||||
(bucket_type::slist_type::container_from_end_iterator(slist_it_));
|
||||
const bucket_type &b = static_cast<const bucket_type&>(*n);
|
||||
|
||||
//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
|
||||
slist_node_ptr bucket_nodeptr = buckets->get_node_ptr();
|
||||
do{
|
||||
if (++n_bucket >= buckets_len){ //bucket overflow, return end() iterator
|
||||
slist_it_ = buckets->before_begin();
|
||||
slist_it_ = first_bucket_bbegin;
|
||||
return;
|
||||
}
|
||||
bucket_nodeptr = buckets[n_bucket].get_node_ptr();
|
||||
}
|
||||
while (buckets[n_bucket].empty());
|
||||
slist_it_ = buckets[n_bucket].begin();
|
||||
while (slist_node_algorithms::is_empty(bucket_nodeptr));
|
||||
slist_it_ = siterator(bucket_nodeptr);
|
||||
++slist_it_;
|
||||
}
|
||||
else{
|
||||
//++slist_it_ yield to a valid object
|
||||
@@ -289,6 +245,134 @@ class hashtable_iterator
|
||||
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 boost {
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -570,6 +570,7 @@ template
|
||||
, class O8 = void
|
||||
, class O9 = void
|
||||
, class O10 = void
|
||||
, class O11 = void
|
||||
>
|
||||
#else
|
||||
template<class T, class ...Options>
|
||||
@@ -589,6 +590,7 @@ template
|
||||
, class O8 = void
|
||||
, class O9 = void
|
||||
, class O10 = void
|
||||
, class O11 = void
|
||||
>
|
||||
#else
|
||||
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.
|
||||
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
|
||||
|
||||
struct hook_defaults
|
||||
|
@@ -28,8 +28,13 @@ namespace intrusive {
|
||||
|
||||
/// @cond
|
||||
|
||||
template<class U>
|
||||
void priority_order();
|
||||
namespace adldft {
|
||||
|
||||
template<class T, class U>
|
||||
BOOST_INTRUSIVE_FORCEINLINE bool priority_order(const T &t, const U &u)
|
||||
{ return t < u; }
|
||||
|
||||
} //namespace adldft {
|
||||
|
||||
/// @endcond
|
||||
|
||||
@@ -43,6 +48,7 @@ struct priority_compare
|
||||
|
||||
BOOST_INTRUSIVE_FORCEINLINE bool operator()(const T &val, const T &val2) const
|
||||
{
|
||||
using adldft::priority_order;
|
||||
return priority_order(val, val2);
|
||||
}
|
||||
};
|
||||
@@ -53,6 +59,7 @@ struct priority_compare<void>
|
||||
template<class T, class U>
|
||||
BOOST_INTRUSIVE_FORCEINLINE bool operator()(const T &t, const U &u) const
|
||||
{
|
||||
using adldft::priority_order;
|
||||
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>
|
||||
#endif
|
||||
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>
|
||||
#endif
|
||||
{
|
||||
/// @cond
|
||||
private:
|
||||
@@ -115,7 +117,6 @@ class unordered_set_impl
|
||||
typedef typename implementation_defined::node node;
|
||||
typedef typename implementation_defined::node_ptr node_ptr;
|
||||
typedef typename implementation_defined::const_node_ptr const_node_ptr;
|
||||
typedef typename implementation_defined::node_algorithms node_algorithms;
|
||||
|
||||
public:
|
||||
|
||||
@@ -420,6 +421,7 @@ template<class T, class O1 = void, class O2 = void
|
||||
, class O5 = void, class O6 = void
|
||||
, class O7 = void, class O8 = void
|
||||
, class O9 = void, class O10= void
|
||||
, class O11 = void
|
||||
>
|
||||
#endif
|
||||
struct make_unordered_set
|
||||
@@ -428,7 +430,7 @@ struct make_unordered_set
|
||||
typedef typename pack_options
|
||||
< hashtable_defaults,
|
||||
#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
|
||||
Options...
|
||||
#endif
|
||||
@@ -438,7 +440,7 @@ struct make_unordered_set
|
||||
<T, typename packed_options::proto_value_traits>::type value_traits;
|
||||
|
||||
typedef typename make_bucket_traits
|
||||
<T, true, packed_options>::type bucket_traits;
|
||||
<T, packed_options>::type bucket_traits;
|
||||
|
||||
typedef unordered_set_impl
|
||||
< 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::compare_hash)*hash_bool_flags::compare_hash_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;
|
||||
|
||||
/// @endcond
|
||||
@@ -462,27 +465,26 @@ struct make_unordered_set
|
||||
#ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED
|
||||
|
||||
#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
|
||||
template<class T, class ...Options>
|
||||
#endif
|
||||
class unordered_set
|
||||
: public make_unordered_set<T,
|
||||
#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
|
||||
Options...
|
||||
#endif
|
||||
>::type
|
||||
{
|
||||
typedef typename make_unordered_set
|
||||
<T,
|
||||
typedef typename make_unordered_set<T,
|
||||
#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
|
||||
Options...
|
||||
#endif
|
||||
>::type Base;
|
||||
>::type Base;
|
||||
|
||||
//Assert if passed value traits are compatible with the type
|
||||
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>
|
||||
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>
|
||||
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
|
||||
@@ -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>
|
||||
#endif
|
||||
class unordered_multiset_impl
|
||||
#ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED
|
||||
: public hashtable_impl<ValueTraits, VoidOrKeyOfValue, VoidOrKeyHash, VoidOrKeyEqual, BucketTraits, SizeType, BoolFlags>
|
||||
#endif
|
||||
{
|
||||
/// @cond
|
||||
private:
|
||||
@@ -613,7 +617,6 @@ class unordered_multiset_impl
|
||||
typedef typename implementation_defined::node node;
|
||||
typedef typename implementation_defined::node_ptr node_ptr;
|
||||
typedef typename implementation_defined::const_node_ptr const_node_ptr;
|
||||
typedef typename implementation_defined::node_algorithms node_algorithms;
|
||||
|
||||
public:
|
||||
|
||||
@@ -872,6 +875,7 @@ template<class T, class O1 = void, class O2 = void
|
||||
, class O5 = void, class O6 = void
|
||||
, class O7 = void, class O8 = void
|
||||
, class O9 = void, class O10= void
|
||||
, class O11 = void
|
||||
>
|
||||
#endif
|
||||
struct make_unordered_multiset
|
||||
@@ -880,7 +884,7 @@ struct make_unordered_multiset
|
||||
typedef typename pack_options
|
||||
< hashtable_defaults,
|
||||
#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
|
||||
Options...
|
||||
#endif
|
||||
@@ -890,7 +894,7 @@ struct make_unordered_multiset
|
||||
<T, typename packed_options::proto_value_traits>::type value_traits;
|
||||
|
||||
typedef typename make_bucket_traits
|
||||
<T, true, packed_options>::type bucket_traits;
|
||||
<T, packed_options>::type bucket_traits;
|
||||
|
||||
typedef unordered_multiset_impl
|
||||
< 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::compare_hash)*hash_bool_flags::compare_hash_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;
|
||||
|
||||
/// @endcond
|
||||
@@ -914,14 +919,14 @@ struct make_unordered_multiset
|
||||
#ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED
|
||||
|
||||
#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
|
||||
template<class T, class ...Options>
|
||||
#endif
|
||||
class unordered_multiset
|
||||
: public make_unordered_multiset<T,
|
||||
#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
|
||||
Options...
|
||||
#endif
|
||||
@@ -977,11 +982,11 @@ class unordered_multiset
|
||||
|
||||
template <class Cloner, class 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>
|
||||
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
|
||||
|
@@ -108,10 +108,10 @@ struct unordered_group_adapter
|
||||
typedef typename NodeTraits::node_ptr 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); }
|
||||
|
||||
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); }
|
||||
};
|
||||
|
||||
|
@@ -22,8 +22,6 @@
|
||||
#include <boost/intrusive/link_mode.hpp>
|
||||
|
||||
|
||||
namespace boost {
|
||||
namespace intrusive {
|
||||
|
||||
struct BPtr_Value
|
||||
{
|
||||
@@ -210,6 +208,8 @@ struct ValueContainer< BPtr_Value >
|
||||
typedef bounded_reference_cont< BPtr_Value > type;
|
||||
};
|
||||
|
||||
namespace boost {
|
||||
namespace intrusive {
|
||||
namespace test{
|
||||
|
||||
template <>
|
||||
|
@@ -14,9 +14,6 @@
|
||||
|
||||
#include <boost/functional/hash/hash.hpp>
|
||||
|
||||
namespace boost{
|
||||
namespace intrusive{
|
||||
|
||||
struct int_holder
|
||||
{
|
||||
explicit int_holder(int value = 0)
|
||||
@@ -111,7 +108,4 @@ struct int_priority_of_value
|
||||
{ return tv.int_value(); }
|
||||
};
|
||||
|
||||
} //namespace boost{
|
||||
} //namespace intrusive{
|
||||
|
||||
#endif //BOOST_INTRUSIVE_DETAIL_INT_HOLDER_HPP
|
||||
|
@@ -22,9 +22,6 @@
|
||||
#include <boost/intrusive/detail/get_value_traits.hpp>
|
||||
#include <boost/container/vector.hpp>
|
||||
|
||||
namespace boost{
|
||||
namespace intrusive{
|
||||
|
||||
struct testvalue_filler
|
||||
{
|
||||
void *dummy_[3];
|
||||
@@ -134,35 +131,48 @@ struct testvalue
|
||||
boost::hash<int> hasher;
|
||||
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)
|
||||
{ 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)
|
||||
/*
|
||||
bool priority_order(int t1, int 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);
|
||||
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;
|
||||
}
|
||||
|
||||
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
|
||||
{
|
||||
@@ -206,13 +216,14 @@ struct ValueContainer< testvalue<Hooks> >
|
||||
template < typename Pointer >
|
||||
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 typename pointer_rebind<pointer, const element_type>::type const_pointer;
|
||||
typedef typename boost::intrusive::pointer_rebind<pointer, const element_type>::type const_pointer;
|
||||
|
||||
public:
|
||||
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()
|
||||
@@ -235,50 +246,38 @@ struct testvalue_traits
|
||||
typedef testvalue< Hooks > value_type;
|
||||
|
||||
//base
|
||||
typedef typename detail::get_base_value_traits
|
||||
typedef typename boost::intrusive::detail::get_base_value_traits
|
||||
< value_type
|
||||
, typename Hooks::base_hook_type
|
||||
>::type base_value_traits;
|
||||
//auto-base
|
||||
typedef typename detail::get_base_value_traits
|
||||
typedef typename boost::intrusive::detail::get_base_value_traits
|
||||
< value_type
|
||||
, typename Hooks::auto_base_hook_type
|
||||
>::type auto_base_value_traits;
|
||||
//member
|
||||
typedef typename detail::get_member_value_traits
|
||||
< member_hook
|
||||
typedef typename boost::intrusive::detail::get_member_value_traits
|
||||
< boost::intrusive::member_hook
|
||||
< value_type
|
||||
, typename Hooks::member_hook_type
|
||||
, &value_type::node_
|
||||
>
|
||||
>::type member_value_traits;
|
||||
//auto-member
|
||||
typedef typename detail::get_member_value_traits
|
||||
< member_hook
|
||||
typedef typename boost::intrusive::detail::get_member_value_traits
|
||||
< boost::intrusive::member_hook
|
||||
< value_type
|
||||
, typename Hooks::auto_member_hook_type
|
||||
, &value_type::auto_node_
|
||||
>
|
||||
>::type auto_member_value_traits;
|
||||
//nonmember
|
||||
typedef nonhook_node_member_value_traits
|
||||
typedef boost::intrusive::nonhook_node_member_value_traits
|
||||
< value_type
|
||||
, typename Hooks::nonhook_node_member_type
|
||||
, &value_type::nhn_member_
|
||||
, safe_link
|
||||
, boost::intrusive::safe_link
|
||||
> 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
|
||||
|
@@ -113,8 +113,8 @@ int main()
|
||||
Slist my_slist(slist_traits(values, slist_hook_array));
|
||||
Set my_set (std::less<MyClass>(), rbtree_traits(values, rbtree_hook_array));
|
||||
Uset my_uset ( Uset::bucket_traits(buckets, NumElements)
|
||||
, boost::hash<MyClass>()
|
||||
, std::equal_to<MyClass>()
|
||||
, Uset::hasher()
|
||||
, Uset::key_equal()
|
||||
, 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
|
||||
typename Container::size_type sz = Container::suggested_upper_bucket_count(size_type(-1));
|
||||
BOOST_TEST( sz > size_type(-1)/2 );
|
||||
//In the rest of cases the upper bound is returned
|
||||
sz = Container::suggested_upper_bucket_count(size_type(-1)/2);
|
||||
BOOST_TEST( sz >= size_type(-1)/2 );
|
||||
//If size_type is big enough 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);
|
||||
BOOST_TEST( sz >= size_type(-1)/2 );
|
||||
}
|
||||
sz = Container::suggested_upper_bucket_count(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);
|
||||
BOOST_TEST( sz > 0 );
|
||||
//
|
||||
|
@@ -27,7 +27,8 @@
|
||||
|
||||
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
|
||||
{
|
||||
typedef unordered_rebinder_common<ValueTraits, DefaultHolder, Map> common_t;
|
||||
@@ -45,6 +46,7 @@ struct rebinder
|
||||
, cache_begin<CacheBegin>
|
||||
, compare_hash<CompareHash>
|
||||
, incremental<Incremental>
|
||||
, linear_buckets<LinearBuckets>
|
||||
, typename common_t::holder_opt
|
||||
, typename common_t::key_of_value_opt
|
||||
, Option1
|
||||
@@ -62,11 +64,11 @@ enum HookType
|
||||
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;
|
||||
|
||||
template<class VoidPointer, bool ConstantTimeSize, bool DefaultHolder, bool Map>
|
||||
class test_main_template<VoidPointer, ConstantTimeSize, DefaultHolder, Map, Base>
|
||||
template<class VoidPointer, bool ConstantTimeSize, bool DefaultHolder, bool Map, bool LinearBuckets>
|
||||
class test_main_template<VoidPointer, ConstantTimeSize, DefaultHolder, Map, Base, LinearBuckets>
|
||||
{
|
||||
public:
|
||||
static void execute()
|
||||
@@ -87,13 +89,14 @@ class test_main_template<VoidPointer, ConstantTimeSize, DefaultHolder, Map, Base
|
||||
>::type base_hook_t;
|
||||
test::test_unordered
|
||||
< //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);
|
||||
}
|
||||
};
|
||||
|
||||
template<class VoidPointer, bool ConstantTimeSize, bool DefaultHolder, bool Map>
|
||||
class test_main_template<VoidPointer, ConstantTimeSize, DefaultHolder, Map, Member>
|
||||
template<class VoidPointer, bool ConstantTimeSize, bool DefaultHolder, bool Map, bool LinearBuckets>
|
||||
class test_main_template<VoidPointer, ConstantTimeSize, DefaultHolder, Map, Member, LinearBuckets>
|
||||
{
|
||||
public:
|
||||
static void execute()
|
||||
@@ -114,13 +117,14 @@ class test_main_template<VoidPointer, ConstantTimeSize, DefaultHolder, Map, Memb
|
||||
>::type member_hook_t;
|
||||
test::test_unordered
|
||||
< //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);
|
||||
}
|
||||
};
|
||||
|
||||
template<class VoidPointer, bool ConstantTimeSize, bool DefaultHolder, bool Map>
|
||||
class test_main_template<VoidPointer, ConstantTimeSize, DefaultHolder, Map, NonMember>
|
||||
template<class VoidPointer, bool ConstantTimeSize, bool DefaultHolder, bool Map, bool LinearBuckets>
|
||||
class test_main_template<VoidPointer, ConstantTimeSize, DefaultHolder, Map, NonMember, LinearBuckets>
|
||||
|
||||
{
|
||||
public:
|
||||
@@ -137,7 +141,8 @@ class test_main_template<VoidPointer, ConstantTimeSize, DefaultHolder, Map, NonM
|
||||
//nonmember
|
||||
test::test_unordered
|
||||
< //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);
|
||||
}
|
||||
};
|
||||
@@ -147,21 +152,31 @@ int main()
|
||||
//VoidPointer x ConstantTimeSize x Map x DefaultHolder
|
||||
|
||||
//void pointer
|
||||
test_main_template<void*, false, false, false, Base>::execute();
|
||||
test_main_template<void*, false, true, false, Member>::execute();
|
||||
test_main_template<void*, true, false, false, NonMember>::execute();
|
||||
test_main_template<void*, true, true, false, Base>::execute();
|
||||
test_main_template<void*, false, false, false, Base, false>::execute();
|
||||
test_main_template<void*, false, true, false, Member, false>::execute();
|
||||
test_main_template<void*, true, false, false, NonMember, false>::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
|
||||
test_main_template<smart_ptr<void>, false, false, false, Member>::execute();
|
||||
test_main_template<smart_ptr<void>, false, true, false, NonMember>::execute();
|
||||
test_main_template<smart_ptr<void>, true, false, false, Base>::execute();
|
||||
test_main_template<smart_ptr<void>, true, true, 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, false>::execute();
|
||||
test_main_template<smart_ptr<void>, true, false, false, Base, false>::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)
|
||||
//test_main_template_bptr< false, false >::execute();
|
||||
//test_main_template_bptr< false, true >::execute();
|
||||
//test_main_template_bptr< true, false >::execute();
|
||||
//test_main_template_bptr< true, true >::execute();
|
||||
|
||||
return boost::report_errors();
|
||||
}
|
||||
|
@@ -25,7 +25,8 @@
|
||||
|
||||
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
|
||||
{
|
||||
typedef unordered_rebinder_common<ValueTraits, DefaultHolder, Map> common_t;
|
||||
@@ -43,6 +44,7 @@ struct rebinder
|
||||
, cache_begin<CacheBegin>
|
||||
, compare_hash<CompareHash>
|
||||
, incremental<Incremental>
|
||||
, linear_buckets<LinearBuckets>
|
||||
, typename common_t::holder_opt
|
||||
, typename common_t::key_of_value_opt
|
||||
, size_type<unsigned short>
|
||||
@@ -61,11 +63,11 @@ enum HookType
|
||||
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;
|
||||
|
||||
template<class VoidPointer, bool ConstantTimeSize, bool DefaultHolder, bool Map>
|
||||
class test_main_template<VoidPointer, ConstantTimeSize, DefaultHolder, Map, Base>
|
||||
template<class VoidPointer, bool ConstantTimeSize, bool DefaultHolder, bool Map, bool LinearBuckets>
|
||||
class test_main_template<VoidPointer, ConstantTimeSize, DefaultHolder, Map, Base, LinearBuckets>
|
||||
{
|
||||
public:
|
||||
static void execute()
|
||||
@@ -86,13 +88,14 @@ class test_main_template<VoidPointer, ConstantTimeSize, DefaultHolder, Map, Base
|
||||
>::type base_hook_t;
|
||||
test::test_unordered
|
||||
< //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);
|
||||
}
|
||||
};
|
||||
|
||||
template<class VoidPointer, bool ConstantTimeSize, bool DefaultHolder, bool Map>
|
||||
class test_main_template<VoidPointer, ConstantTimeSize, DefaultHolder, Map, Member>
|
||||
template<class VoidPointer, bool ConstantTimeSize, bool DefaultHolder, bool Map, bool LinearBuckets>
|
||||
class test_main_template<VoidPointer, ConstantTimeSize, DefaultHolder, Map, Member, LinearBuckets>
|
||||
{
|
||||
public:
|
||||
static void execute()
|
||||
@@ -113,13 +116,13 @@ class test_main_template<VoidPointer, ConstantTimeSize, DefaultHolder, Map, Memb
|
||||
>::type member_hook_t;
|
||||
test::test_unordered
|
||||
< //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);
|
||||
}
|
||||
};
|
||||
|
||||
template<class VoidPointer, bool ConstantTimeSize, bool DefaultHolder, bool Map>
|
||||
class test_main_template<VoidPointer, ConstantTimeSize, DefaultHolder, Map, NonMember>
|
||||
template<class VoidPointer, bool ConstantTimeSize, bool DefaultHolder, bool Map, bool LinearBuckets>
|
||||
class test_main_template<VoidPointer, ConstantTimeSize, DefaultHolder, Map, NonMember, LinearBuckets>
|
||||
|
||||
{
|
||||
public:
|
||||
@@ -136,7 +139,7 @@ class test_main_template<VoidPointer, ConstantTimeSize, DefaultHolder, Map, NonM
|
||||
//nonmember
|
||||
test::test_unordered
|
||||
< //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);
|
||||
}
|
||||
};
|
||||
@@ -146,16 +149,25 @@ int main()
|
||||
//VoidPointer x ConstantTimeSize x Map x DefaultHolder
|
||||
|
||||
//void pointer
|
||||
test_main_template<void*, false, false, false, Base>::execute();
|
||||
test_main_template<void*, false, true, false, Member>::execute();
|
||||
test_main_template<void*, true, false, false, NonMember>::execute();
|
||||
test_main_template<void*, true, true, false, Base>::execute();
|
||||
test_main_template<void*, false, false, false, Base, false>::execute();
|
||||
test_main_template<void*, false, true, false, Member, false>::execute();
|
||||
test_main_template<void*, true, false, false, NonMember, false>::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
|
||||
test_main_template<smart_ptr<void>, false, false, false, Member>::execute();
|
||||
test_main_template<smart_ptr<void>, false, true, false, NonMember>::execute();
|
||||
test_main_template<smart_ptr<void>, true, false, false, Base>::execute();
|
||||
test_main_template<smart_ptr<void>, true, true, 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, false>::execute();
|
||||
test_main_template<smart_ptr<void>, true, false, false, Base, false>::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)
|
||||
//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
|
||||
<>::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_ptr bucket_ptr;
|
||||
|
||||
{
|
||||
typename unordered_type::bucket_type buckets [BucketSize];
|
||||
typename unordered_type::bucket_type buckets [BucketSize + ExtraBuckets];
|
||||
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());
|
||||
test::test_container(testset);
|
||||
testset.clear();
|
||||
@@ -74,9 +77,9 @@ void test_unordered<ContainerDefiner>::test_all (value_cont_type& values)
|
||||
value_cont_type vals(BucketSize);
|
||||
for (std::size_t i = 0; i < BucketSize; ++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(
|
||||
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());
|
||||
test::test_iterator_forward(testset);
|
||||
}
|
||||
@@ -95,6 +98,8 @@ void test_unordered<ContainerDefiner>::test_impl()
|
||||
{
|
||||
typedef typename ContainerDefiner::template container
|
||||
<>::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_ptr bucket_ptr;
|
||||
|
||||
@@ -102,9 +107,9 @@ void test_unordered<ContainerDefiner>::test_impl()
|
||||
for (std::size_t i = 0u; i < 5u; ++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(
|
||||
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)
|
||||
testset.insert (values[i]);
|
||||
@@ -123,13 +128,15 @@ void test_unordered<ContainerDefiner>::test_sort(value_cont_type& values)
|
||||
{
|
||||
typedef typename ContainerDefiner::template container
|
||||
<>::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_ptr bucket_ptr;
|
||||
|
||||
typename unordered_type::bucket_type buckets [BucketSize];
|
||||
typename unordered_type::bucket_type buckets[BucketSize + ExtraBuckets];
|
||||
unordered_type testset1
|
||||
(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){
|
||||
{ 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>
|
||||
void test_unordered<ContainerDefiner>::test_insert(value_cont_type& values, detail::false_) //not multikey
|
||||
{
|
||||
|
||||
typedef typename ContainerDefiner::template container
|
||||
<>::type unordered_set_type;
|
||||
typedef typename unordered_set_type::bucket_traits bucket_traits;
|
||||
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(
|
||||
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);
|
||||
|
||||
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
|
||||
<>::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_ptr bucket_ptr;
|
||||
typedef typename unordered_type::iterator iterator;
|
||||
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(
|
||||
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);
|
||||
|
||||
@@ -251,9 +259,9 @@ void test_unordered<ContainerDefiner>::test_insert(value_cont_type& values, deta
|
||||
BOOST_TEST (testset.empty() == true);
|
||||
|
||||
//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(
|
||||
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());
|
||||
BOOST_TEST (testset2.erase(key_type(5)) == 1);
|
||||
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);
|
||||
|
||||
//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(
|
||||
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());
|
||||
BOOST_TEST (testset2.erase(key_type(5)) == 1);
|
||||
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
|
||||
const int random_init[] = { 3, 2, 4, 1, 5, 2, 2 };
|
||||
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){
|
||||
value_cont_type data (random_size);
|
||||
for (std::size_t j = 0; j < random_size; ++j)
|
||||
data[j].value_ = random_init[j];
|
||||
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.erase(testset_new.iterator_to(data[i]));
|
||||
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 NumIterations = BucketSize*LoadFactor;
|
||||
value_cont_type random_init(NumIterations);//Preserve memory
|
||||
value_cont_type set_tester;
|
||||
set_tester.reserve(NumIterations);
|
||||
|
||||
//Initialize values
|
||||
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];
|
||||
bucket_traits btraits(pointer_traits<bucket_ptr>::pointer_to(buckets[0]), BucketSize);
|
||||
typename unordered_type::bucket_type buckets[BucketSize + ExtraBuckets];
|
||||
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 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...
|
||||
BOOST_TEST ((random_init.size() - erased_cnt) == testset.size());
|
||||
|
||||
//Create an ordered copy of the intrusive container
|
||||
set_tester.insert(set_tester.end(), testset.begin(), testset.end());
|
||||
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())
|
||||
//for non-linear buckets is_linked is a reliable marker for a node
|
||||
//inserted in a hash map, but not for linear buckets, which are null-ended
|
||||
BOOST_IF_CONSTEXPR(!unordered_type::linear_buckets){
|
||||
value_cont_type set_tester;
|
||||
set_tester.reserve(NumIterations);
|
||||
//Create an ordered copy of the intrusive container
|
||||
set_tester.insert(set_tester.end(), testset.begin(), testset.end());
|
||||
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;
|
||||
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
|
||||
<>::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_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,
|
||||
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(
|
||||
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);
|
||||
testset1.swap (testset2);
|
||||
@@ -443,14 +455,16 @@ void test_unordered<ContainerDefiner>::test_rehash(value_cont_type& values, deta
|
||||
typedef typename ContainerDefiner::template container
|
||||
<>::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_ptr bucket_ptr;
|
||||
//Build a uset
|
||||
typename unordered_type::bucket_type buckets1 [BucketSize];
|
||||
typename unordered_type::bucket_type buckets2 [BucketSize*2];
|
||||
typename unordered_type::bucket_type buckets1[BucketSize + ExtraBuckets];
|
||||
typename unordered_type::bucket_type buckets2[BucketSize*2u + ExtraBuckets];
|
||||
unordered_type testset1(&values[0], &values[0] + values.size(),
|
||||
bucket_traits(pointer_traits<bucket_ptr>::
|
||||
pointer_to(buckets1[0]), BucketSize));
|
||||
pointer_to(buckets1[0]), sizeof(buckets1)/sizeof(*buckets1)));
|
||||
//Test current state
|
||||
BOOST_TEST(testset1.split_count() == BucketSize/2);
|
||||
{ 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
|
||||
BOOST_TEST(testset1.incremental_rehash(bucket_traits(
|
||||
pointer_traits<bucket_ptr>::
|
||||
pointer_to(buckets1[0]), BucketSize)) == false);
|
||||
pointer_traits<bucket_ptr>::pointer_to(buckets1[0])
|
||||
, sizeof(buckets1)/sizeof(*buckets1))) == false);
|
||||
BOOST_TEST(testset1.split_count() == BucketSize);
|
||||
{ int init_values [] = { 1, 2, 2, 3, 4, 5 };
|
||||
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
|
||||
BOOST_TEST(testset1.incremental_rehash(bucket_traits(
|
||||
pointer_traits<bucket_ptr>::
|
||||
pointer_to(buckets2[0]), BucketSize)) == false);
|
||||
pointer_to(buckets2[0])
|
||||
, BucketSize + ExtraBuckets)) == false);
|
||||
BOOST_TEST(testset1.split_count() == BucketSize);
|
||||
{ int init_values [] = { 1, 2, 2, 3, 4, 5 };
|
||||
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
|
||||
BOOST_TEST(testset1.incremental_rehash(bucket_traits(
|
||||
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);
|
||||
{ int init_values [] = { 1, 2, 2, 3, 4, 5 };
|
||||
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
|
||||
BOOST_TEST(testset1.incremental_rehash(bucket_traits(
|
||||
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);
|
||||
{ int init_values [] = { 1, 2, 2, 3, 4, 5 };
|
||||
TEST_INTRUSIVE_SEQUENCE_MAYBEUNIQUE( init_values, testset1 ); }
|
||||
@@ -516,7 +533,8 @@ void test_unordered<ContainerDefiner>::test_rehash(value_cont_type& values, deta
|
||||
//Shrink rehash
|
||||
testset1.rehash(bucket_traits(
|
||||
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);
|
||||
{ int init_values [] = { 4, 5, 1, 2, 2, 3 };
|
||||
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
|
||||
testset1.rehash(bucket_traits(
|
||||
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);
|
||||
{ int init_values [] = { 2, 2, 4, 3, 5, 1 };
|
||||
TEST_INTRUSIVE_SEQUENCE_MAYBEUNIQUE( init_values, testset1 ); }
|
||||
@@ -532,7 +551,11 @@ void test_unordered<ContainerDefiner>::test_rehash(value_cont_type& values, deta
|
||||
//Growing rehash
|
||||
testset1.rehash(bucket_traits(
|
||||
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)
|
||||
testset1.full_rehash();
|
||||
@@ -571,39 +594,40 @@ void test_unordered<ContainerDefiner>::test_rehash(value_cont_type& values, deta
|
||||
{
|
||||
typedef typename ContainerDefiner::template container
|
||||
<>::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_ptr bucket_ptr;
|
||||
|
||||
typename unordered_type::bucket_type buckets1 [BucketSize];
|
||||
typename unordered_type::bucket_type buckets2 [2];
|
||||
typename unordered_type::bucket_type buckets3 [BucketSize*2];
|
||||
typename unordered_type::bucket_type buckets1[BucketSize + ExtraBuckets];
|
||||
typename unordered_type::bucket_type buckets2 [2 + ExtraBuckets];
|
||||
typename unordered_type::bucket_type buckets3[BucketSize*2 + ExtraBuckets];
|
||||
|
||||
unordered_type testset1(&values[0], &values[0] + 6, bucket_traits(
|
||||
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 ); }
|
||||
|
||||
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 };
|
||||
TEST_INTRUSIVE_SEQUENCE_MAYBEUNIQUE( init_values, testset1 ); }
|
||||
|
||||
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 };
|
||||
TEST_INTRUSIVE_SEQUENCE_MAYBEUNIQUE( init_values, testset1 ); }
|
||||
|
||||
//Now rehash reducing the buckets
|
||||
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 };
|
||||
TEST_INTRUSIVE_SEQUENCE_MAYBEUNIQUE( init_values, testset1 ); }
|
||||
|
||||
//Now rehash increasing the buckets
|
||||
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 };
|
||||
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::key_of_value key_of_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(
|
||||
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;
|
||||
|
||||
@@ -657,6 +682,8 @@ void test_unordered<ContainerDefiner>::test_clone(value_cont_type& values)
|
||||
{
|
||||
typedef typename ContainerDefiner::template container
|
||||
<>::type unordered_type;
|
||||
const std::size_t ExtraBuckets = unordered_type::bucket_overhead;
|
||||
|
||||
typedef typename unordered_type::value_type value_type;
|
||||
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
|
||||
typename unordered_type::bucket_type buckets1 [BucketSize];
|
||||
typename unordered_type::bucket_type buckets2 [BucketSize];
|
||||
typename unordered_type::bucket_type buckets1[BucketSize + ExtraBuckets];
|
||||
typename unordered_type::bucket_type buckets2[BucketSize + ExtraBuckets];
|
||||
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(
|
||||
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>());
|
||||
BOOST_TEST(testset1 == testset2);
|
||||
@@ -692,12 +719,12 @@ void test_unordered<ContainerDefiner>::test_clone(value_cont_type& values)
|
||||
}
|
||||
{
|
||||
//Test with bigger source bucket arrays
|
||||
typename unordered_type::bucket_type buckets1 [BucketSize*2];
|
||||
typename unordered_type::bucket_type buckets2 [BucketSize];
|
||||
typename unordered_type::bucket_type buckets1[BucketSize*2u + ExtraBuckets];
|
||||
typename unordered_type::bucket_type buckets2[BucketSize + ExtraBuckets];
|
||||
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(
|
||||
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>());
|
||||
BOOST_TEST(testset1 == testset2);
|
||||
@@ -719,12 +746,12 @@ void test_unordered<ContainerDefiner>::test_clone(value_cont_type& values)
|
||||
}
|
||||
{
|
||||
//Test with smaller source bucket arrays
|
||||
typename unordered_type::bucket_type buckets1 [BucketSize];
|
||||
typename unordered_type::bucket_type buckets2 [BucketSize*2];
|
||||
typename unordered_type::bucket_type buckets1[BucketSize + ExtraBuckets];
|
||||
typename unordered_type::bucket_type buckets2[BucketSize*2u + ExtraBuckets];
|
||||
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(
|
||||
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>());
|
||||
BOOST_TEST(testset1 == testset2);
|
||||
|
Reference in New Issue
Block a user