Changes and fixes for Boost 1.37

[SVN r49277]
This commit is contained in:
Ion Gaztañaga
2008-10-11 13:18:02 +00:00
parent d8641cd15c
commit be6ca1b7ec
15 changed files with 1012 additions and 180 deletions

View File

@@ -596,7 +596,7 @@ Apart from that, [*Boost.Intrusive] offers additional features:
be configured to use any type of pointer. This configuration information is also
transmitted to the containers, so all the internal pointers used by intrusive containers
configured with these hooks will be smart pointers. As an example,
[*Boost.Interprocess] defines an mart pointer compatible with shared memory,
[*Boost.Interprocess] defines a smart pointer compatible with shared memory,
called `offset_ptr`. [*Boost.Intrusive] can be configured to use this smart pointer
to allow shared memory intrusive containers.
@@ -656,6 +656,15 @@ want to redefine intrusive safe-mode assertions without modifying the global
used in hooks' destructors to check that the hook is in a default state.
If any of these macros is not redefined, the assertion will default to `BOOST_ASSERT`.
If `BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT` or `BOOST_INTRUSIVE_SAFE_HOOK_DESTRUCTOR_ASSERT`
is defined and the programmer needs to include a file to configure that assertion, it can define
`BOOST_INTRUSIVE_SAFE_HOOK_DESTRUCTOR_ASSERT_INCLUDE` or `BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT_INCLUDE`
with the name of the file to include:
[c++]
#define BOOST_INTRUSIVE_SAFE_HOOK_DESTRUCTOR_ASSERT MYASSERT
#define BOOST_INTRUSIVE_SAFE_HOOK_DESTRUCTOR_ASSERT_INCLUDE <myassert.h>
[endsect]
@@ -1032,8 +1041,9 @@ the same options explained in the section
* [*`optimize_size<bool Enable>`]: The hook will be optimized for size
instead of speed. The hook will embed the color bit of the red-black
tree node in the parent pointer if pointer alignment is even.
Optimizing the size will reduce speed performance a bit since masking
operations will be needed to access parent pointer and color attributes.
In some platforms, optimizing the size might reduce speed performance a bit
since masking operations will be needed to access parent pointer and color attributes,
in other platforms this option improves performance due to improved memory locality.
Default: `optimize_size<false>`.
[endsect]
@@ -1288,6 +1298,12 @@ And they also can receive additional options:
equal hashes, so comparing the hash values of two elements before using the
comparison functor can speed up some implementations.
* [*`incremental<bool Enabled>`]: Activates incremental hashing (also known as Linear Hashing).
This option implies `power_2_buckets<true>` and the container will require power of two buckets.
For more information on incremental hashing, see
[@http://en.wikipedia.org/wiki/Linear_hashing `Linear hash` on Wikipedia]
Default: `incremental<false>`
[endsect]
[section:unordered_set_unordered_multiset_example Example]
@@ -1558,8 +1574,9 @@ the size of the node:
* [*`optimize_size<bool Enable>`]: The hook will be optimized for size
instead of speed. The hook will embed the balance bits of the AVL
tree node in the parent pointer if pointer alignment is multiple of 4.
Optimizing the size will reduce speed performance a bit since masking
operations will be needed to access parent pointer and balance factor attributes.
In some platforms, optimizing the size might reduce speed performance a bit
since masking operations will be needed to access parent pointer and balance factor attributes,
in other platforms this option improves performance due to improved memory locality.
Default: `optimize_size<false>`.
[endsect]
@@ -1890,7 +1907,7 @@ and [classref boost::intrusive::unordered_set unordered_set] reference for more
With multiple ordered and unordered associative containers
([classref boost::intrusive::multiset multiset] and
[classref boost::intrusive::unordered_multiset unordered_multiset]) there's
[classref boost::intrusive::unordered_multiset unordered_multiset]) there is
no need for these advanced insertion functions, since insertions are always succesful.
[endsect]
@@ -1982,7 +1999,7 @@ The cloning function works as follows:
all the constructed elements are disposed using the disposer function object.
Here's an example of `clone_from`:
Here is an example of `clone_from`:
[import ../example/doc_clone_from.cpp]
[doc_clone_from]
@@ -2116,7 +2133,7 @@ These hooks support these options:
be inserted container. Additionally, these hooks don't support `unlink()` and
`swap_nodes()` operations for the same reason.
Here's an example that creates a class with two any hooks, and uses one to insert the
Here is an example that creates a class with two any hooks, and uses one to insert the
class in a [classref slist] and the other one in a [classref list].
[import ../example/doc_any_hook.cpp]
@@ -2699,7 +2716,7 @@ used in node algorithms, since these types can be different. Apart from this,
Instead of using [*Boost.Intrusive] predefined hooks
a user might want to develop customized containers, for example, using nodes that are
optimized for a specific
application or that are compatible with a a legacy ABI. A user might want
application or that are compatible with a legacy ABI. A user might want
to have only two additional pointers in his class and insert the class in a doubly
linked list sometimes and in a singly linked list in other situations. You can't
achieve this using [*Boost.Intrusive] predefined hooks. Now, instead of using
@@ -3471,6 +3488,17 @@ all the objects to be inserted in intrusive containers in containers like `std::
[section:release_notes Release Notes]
[section:release_notes_boost_1_37_00 Boost 1.37 Release]
* Intrusive now takes advantage of compilers with variadic templates.
* `clone_from` functions now copy predicates and hash functions of associative containers.
* Added incremental hashing to unordered containers via `incremental<>` option.
* Update some function parameters from `iterator` to `const_iterator` in containers
to keep up with the draft of the next standard.
* Added an option to specify include files for intrusive configurable assertion macros.
[endsect]
[section:release_notes_boost_1_36_00 Boost 1.36 Release]
* Added `linear<>` and `cache_last<>` options to singly linked lists.
@@ -3512,7 +3540,7 @@ all the objects to be inserted in intrusive containers in containers like `std::
[endsect]
[section:acknowledgments Acknowledgements]
[section:acknowledgements Acknowledegements]
[*Olaf Krzikalla] would like to thank:

View File

@@ -21,7 +21,7 @@ class Window : public list_base_hook<>
//This is a container those value is an abstract class: you can't do this with std::list.
typedef list<Window> win_list;
//An static intrusive list declaration
//A static intrusive list declaration
static win_list all_windows;
//Constructor. Includes this window in the list

View File

@@ -267,6 +267,9 @@
<File
RelativePath="..\..\..\..\..\boost\intrusive\detail\utilities.hpp">
</File>
<File
RelativePath="..\..\..\..\..\boost\intrusive\detail\workaround.hpp">
</File>
</Filter>
</Filter>
<Filter

3
proj/vc7ide/to-do.txt Normal file
View File

@@ -0,0 +1,3 @@
-> Implement C++0x features (variadic templates & rvalue references)
-> Offer bidirectional iterator for hashtables
-> Non-array buckets

View File

@@ -3,7 +3,7 @@
ProjectType="Visual C++"
Version="7.10"
Name="unordered_set"
ProjectGUID="{90E701E6-2C91-F4A7-BA6C-A9F3B0949279}"
ProjectGUID="{9101EE76-BB6C-2C91-F4B7-A27B94908F19}"
Keyword="Win32Proj">
<Platforms>
<Platform
@@ -21,6 +21,7 @@
Optimization="0"
AdditionalIncludeDirectories="../../../../../"
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
GeneratePreprocessedFile="0"
MinimalRebuild="TRUE"
BasicRuntimeChecks="3"
RuntimeLibrary="5"
@@ -116,7 +117,7 @@
<Filter
Name="Source Files"
Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
UniqueIdentifier="{4F3C77F1-B78A-C745-4726-2D752AA322FF}">
UniqueIdentifier="{4F3C77F1-B78A-C745-4726-252AD75C322E}">
<File
RelativePath="..\..\..\test\unordered_set_test.cpp">
</File>

View File

@@ -13,6 +13,9 @@
#include <boost/intrusive/slist.hpp>
#include <boost/intrusive/set.hpp>
#include <boost/intrusive/unordered_set.hpp>
#include <boost/intrusive/splay_set.hpp>
#include <boost/intrusive/avl_set.hpp>
#include <boost/intrusive/sg_set.hpp>
#include "smart_ptr.hpp"
#include <vector>
@@ -28,6 +31,12 @@ class MyClass
< void_pointer<smart_ptr<void> >, link_mode<normal_link> >
, public unordered_set_base_hook
< void_pointer<smart_ptr<void> >, link_mode<normal_link> >
, public avl_set_base_hook
< void_pointer<smart_ptr<void> >, link_mode<normal_link> >
, public splay_set_base_hook
< void_pointer<smart_ptr<void> >, link_mode<normal_link> >
, public bs_set_base_hook
< void_pointer<smart_ptr<void> >, link_mode<normal_link> >
{
int int_;
@@ -51,6 +60,9 @@ typedef list<MyClass> List;
typedef slist<MyClass> Slist;
typedef set<MyClass> Set;
typedef unordered_set<MyClass> USet;
typedef avl_set<MyClass> AvlSet;
typedef splay_set<MyClass> SplaySet;
typedef sg_set<MyClass> SgSet;
int main()
{
@@ -67,6 +79,9 @@ int main()
Slist my_slist;
Set my_set;
USet my_uset(USet::bucket_traits(buckets, 100));
AvlSet my_avlset;
SplaySet my_splayset;
SgSet my_sgset;
//Now insert them in the reverse order
//in the base hook intrusive list
@@ -75,6 +90,9 @@ int main()
my_slist.push_front(*it);
my_set.insert(*it);
my_uset.insert(*it);
my_avlset.insert(*it);
my_splayset.insert(*it);
my_sgset.insert(*it);
}
//Now test lists
@@ -82,13 +100,24 @@ int main()
List::const_iterator list_it(my_list.cbegin());
Slist::const_iterator slist_it(my_slist.cbegin());
Set::const_reverse_iterator set_rit(my_set.crbegin());
AvlSet::const_reverse_iterator avl_set_rit(my_avlset.crbegin());
SplaySet::const_reverse_iterator splay_set_rit(my_splayset.crbegin());
SgSet::const_reverse_iterator sg_set_rit(my_sgset.crbegin());
VectRit vect_it(values.rbegin()), vect_itend(values.rend());
//Test the objects inserted in the base hook list
for(; vect_it != vect_itend; ++vect_it, ++list_it, ++slist_it, ++set_rit){
for(; vect_it != vect_itend
; ++vect_it, ++list_it
, ++slist_it, ++set_rit
, ++avl_set_rit, ++splay_set_rit
, ++sg_set_rit){
if(&*list_it != &*vect_it) return 1;
if(&*slist_it != &*vect_it) return 1;
if(&*set_rit != &*vect_it) return 1;
if(&*avl_set_rit != &*vect_it) return 1;
if(&*splay_set_rit != &*vect_it)return 1;
if(&*sg_set_rit != &*vect_it) return 1;
if(my_uset.find(*set_rit) == my_uset.cend()) return 1;
}
}

View File

@@ -13,6 +13,7 @@
#include <boost/intrusive/detail/config_begin.hpp>
#include <boost/intrusive/list.hpp>
#include <boost/intrusive/detail/pointer_to_other.hpp>
#include "itestvalue.hpp"
#include "smart_ptr.hpp"
@@ -446,13 +447,12 @@ class test_main_template<VoidPointer, false>
>
>::type
>::test_all(data);
/*
test_list<stateful_value_traits
< value_type
, list_node_traits<VoidPointer>
, safe_link>
>::test_all(data);
*/
// test_list<stateful_value_traits
// < value_type
// , list_node_traits<VoidPointer>
// , safe_link>
// >::test_all(data);
test_list < typename detail::get_base_value_traits
< value_type
, typename value_type::list_auto_base_hook_t
@@ -467,13 +467,13 @@ class test_main_template<VoidPointer, false>
>
>::type
>::test_all(data);
/*
test_list<stateful_value_traits
< value_type
, list_node_traits<VoidPointer>
, auto_unlink>
>::test_all(data);
*/
// test_list<stateful_value_traits
// < value_type
// , list_node_traits<VoidPointer>
// , auto_unlink>
// >::test_all(data);
return 0;
}
};
@@ -488,3 +488,285 @@ int main( int, char* [] )
return boost::report_errors();
}
#include <boost/intrusive/detail/config_end.hpp>
/*
#include <cstddef>
////////////////////////////////////////////////////
// Builds an index_tuple<0, 1, 2, ..., Num-1>, that will
// be used to "unpack" into comma-separated values
// in a function call.
////////////////////////////////////////////////////
template<int... Indexes>
struct index_tuple{};
template<std::size_t Num, typename Tuple = index_tuple<> >
struct build_number_seq;
template<std::size_t Num, int... Indexes>
struct build_number_seq<Num, index_tuple<Indexes...> >
: build_number_seq<Num - 1, index_tuple<Indexes..., sizeof...(Indexes)> >
{};
template<int... Indexes>
struct build_number_seq<0, index_tuple<Indexes...> >
{ typedef index_tuple<Indexes...> type; };
template<class ...Types>
struct typelist
{};
template<class T>
struct invert_typelist;
template<int I, typename Tuple>
struct typelist_element;
template<int I, typename Head, typename... Tail>
struct typelist_element<I, typelist<Head, Tail...> >
{
typedef typename typelist_element<I-1, typelist<Tail...> >::type type;
};
template<typename Head, typename... Tail>
struct typelist_element<0, typelist<Head, Tail...> >
{
typedef Head type;
};
template<int ...Ints, class ...Types>
typelist<typename typelist_element<(sizeof...(Types) - 1) - Ints, typelist<Types...> >::type...>
inverted_typelist(index_tuple<Ints...>, typelist<Types...>)
{
return typelist<typename typelist_element<(sizeof...(Types) - 1) - Ints, typelist<Types...> >::type...>();
}
template<class Typelist>
struct sizeof_typelist;
template<class ...Types>
struct sizeof_typelist< typelist<Types...> >
{
static const std::size_t value = sizeof...(Types);
};
//invert_typelist_impl
template<class Typelist, class Indexes>
struct invert_typelist_impl;
template<class Typelist, int ...Ints>
struct invert_typelist_impl< Typelist, index_tuple<Ints...> >
{
static const std::size_t last_idx = sizeof_typelist<Typelist>::value - 1;
typedef typelist
<typename typelist_element<last_idx - Ints, Typelist>::type...> type;
};
template<class Typelist, int Int>
struct invert_typelist_impl< Typelist, index_tuple<Int> >
{
typedef Typelist type;
};
template<class Typelist>
struct invert_typelist_impl< Typelist, index_tuple<> >
{
typedef Typelist type;
};
//invert_typelist
template<class Typelist>
struct invert_typelist;
template<class ...Types>
struct invert_typelist< typelist<Types...> >
{
typedef typelist<Types...> typelist_t;
typedef typename build_number_seq<sizeof...(Types)>::type indexes_t;
typedef typename invert_typelist_impl<typelist_t, indexes_t>::type type;
};
struct none
{
template<class Base>
struct pack : Base
{ };
};
//!This option setter specifies the type of
//!a void pointer. This will instruct the hook
//!to use this type of pointer instead of the
//!default one
template<class VoidPointer>
struct void_pointer
{
/// @cond
template<class Base>
struct pack : Base
{
typedef VoidPointer void_pointer;
};
/// @endcond
};
//!This option setter specifies the type of
//!the tag of a base hook. A type cannot have two
//!base hooks of the same type, so a tag can be used
//!to differentiate two base hooks with otherwise same type
template<class Tag>
struct tag
{
/// @cond
template<class Base>
struct pack : Base
{
typedef Tag tag;
};
/// @endcond
};
//!This option setter specifies if the hook
//!should be optimized for size instead of for speed.
template<bool Enabled>
struct optimize_size
{
/// @cond
template<class Base>
struct pack : Base
{
static const bool optimize_size = Enabled;
};
/// @endcond
};
//!This option setter specifies if the list container should
//!use a linear implementation instead of a circular one.
template<bool Enabled>
struct linear
{
/// @cond
template<class Base>
struct pack : Base
{
static const bool linear = Enabled;
};
/// @endcond
};
//!This option setter specifies if the list container should
//!use a linear implementation instead of a circular one.
template<bool Enabled>
struct cache_last
{
/// @cond
template<class Base>
struct pack : Base
{
static const bool cache_last = Enabled;
};
/// @endcond
};
template<class Typelist>
struct do_pack;
template<>
struct do_pack<typelist<> >;
template<class Prev>
struct do_pack<typelist<Prev> >
{
typedef Prev type;
};
template<class Prev, class Last>
struct do_pack<typelist<Prev, Last> >
{
typedef typename Prev::template pack<Last> type;
};
template<class Prev, class ...Others>
struct do_pack<typelist<Prev, Others...> >
{
typedef typename Prev::template pack
<typename do_pack<typelist<Others...>>::type> type;
};
template<class ...Options>
struct pack_options
{
typedef typelist<Options...> typelist_t;
typedef typename invert_typelist<typelist_t>::type inverted_typelist;
typedef typename do_pack<inverted_typelist>::type type;
};
struct hook_defaults
: public pack_options
< none
, void_pointer<void*>
, tag<int>
, optimize_size<false>
, linear<false>
>::type
{};
#include <iostream>
#include <typeinfo>
struct S
{};
int main()
{
{
typedef typelist<int, float, double> typelist_t;
typedef invert_typelist<typelist_t>::type inverted_typelist;
std::cout << "original: " << typeid(typelist_t).name() << std::endl;
std::cout << "inverted: " << typeid(inverted_typelist).name() << std::endl;
}
{
typedef typelist<int> typelist_t;
typedef invert_typelist<typelist_t>::type inverted_typelist;
std::cout << "original: " << typeid(typelist_t).name() << std::endl;
std::cout << "inverted: " << typeid(inverted_typelist).name() << std::endl;
}
{
typedef typelist<> typelist_t;
typedef invert_typelist<typelist_t>::type inverted_typelist;
std::cout << "original: " << typeid(typelist_t).name() << std::endl;
std::cout << "inverted: " << typeid(inverted_typelist).name() << std::endl;
}
{
typedef pack_options<S, none>::type options_t;
std::cout << "options_t " << typeid(options_t).name() << std::endl;
}
{
typedef pack_options<S, none, none>::type options_t;
std::cout << "options_t " << typeid(options_t).name() << std::endl;
}
hook_defaults h;
return 1;
}
*/

View File

@@ -108,7 +108,6 @@ class test_main_template<VoidPointer, false>
int main( int, char* [] )
{
test_main_template<void*, false>()();
test_main_template<boost::intrusive::smart_ptr<void>, false>()();
test_main_template<void*, true>()();

View File

@@ -18,8 +18,18 @@
namespace boost { namespace intrusive { namespace test {
#if !defined (BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
template<class T, class O1, class O2, class O3, class O4>
struct has_rebalance<boost::intrusive::sg_multiset<T, O1, O2, O3, O4> >
#else
template<class T, class ...Options>
#endif
struct has_rebalance<boost::intrusive::sg_multiset<T,
#if !defined (BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
O1, O2, O3, O4
#else
Options...
#endif
> >
{
static const bool value = true;
};

View File

@@ -17,8 +17,18 @@
namespace boost { namespace intrusive { namespace test {
#if !defined (BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
template<class T, class O1, class O2, class O3, class O4>
struct has_rebalance<boost::intrusive::sg_set<T, O1, O2, O3, O4> >
#else
template<class T, class ...Options>
#endif
struct has_rebalance<boost::intrusive::sg_set<T,
#if !defined (BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
O1, O2, O3, O4
#else
Options...
#endif
> >
{
static const bool value = true;
};

View File

@@ -19,20 +19,51 @@
namespace boost { namespace intrusive { namespace test {
#if !defined (BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
template<class T, class O1, class O2, class O3, class O4>
struct has_const_overloads<boost::intrusive::splay_multiset<T, O1, O2, O3, O4> >
#else
template<class T, class ...Options>
#endif
struct has_const_overloads<boost::intrusive::splay_multiset<
#if !defined (BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
T, O1, O2, O3, O4
#else
T, Options...
#endif
>
>
{
static const bool value = false;
};
#if !defined (BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
template<class T, class O1, class O2, class O3, class O4>
struct has_splay<boost::intrusive::splay_multiset<T, O1, O2, O3, O4> >
#else
template<class T, class ...Options>
#endif
struct has_splay<boost::intrusive::splay_multiset<T,
#if !defined (BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
O1, O2, O3, O4
#else
Options...
#endif
> >
{
static const bool value = true;
};
#if !defined (BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
template<class T, class O1, class O2, class O3, class O4>
struct has_rebalance<boost::intrusive::splay_multiset<T, O1, O2, O3, O4> >
#else
template<class T, class ...Options>
#endif
struct has_rebalance<boost::intrusive::splay_multiset<T,
#if !defined (BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
O1, O2, O3, O4
#else
Options...
#endif
> >
{
static const bool value = true;
};

View File

@@ -17,20 +17,50 @@
namespace boost { namespace intrusive { namespace test {
#if !defined (BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
template<class T, class O1, class O2, class O3, class O4>
struct has_const_overloads<boost::intrusive::splay_set<T, O1, O2, O3, O4> >
#else
template<class T, class ...Options>
#endif
struct has_const_overloads<boost::intrusive::splay_set<T,
#if !defined (BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
O1, O2, O3, O4
#else
Options...
#endif
> >
{
static const bool value = false;
};
#if !defined (BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
template<class T, class O1, class O2, class O3, class O4>
struct has_splay<boost::intrusive::splay_set<T, O1, O2, O3, O4> >
#else
template<class T, class ...Options>
#endif
struct has_splay<boost::intrusive::splay_set<T,
#if !defined (BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
O1, O2, O3, O4
#else
Options...
#endif
> >
{
static const bool value = true;
};
#if !defined (BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
template<class T, class O1, class O2, class O3, class O4>
struct has_rebalance<boost::intrusive::splay_set<T, O1, O2, O3, O4> >
#else
template<class T, class ...Options>
#endif
struct has_rebalance<boost::intrusive::splay_set<T,
#if !defined (BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
O1, O2, O3, O4
#else
Options...
#endif
> >
{
static const bool value = true;
};

View File

@@ -15,10 +15,7 @@
#define TEST_INTRUSIVE_SEQUENCE( INTVALUES, ITERATOR )\
{ \
const int init_values_size = sizeof(INTVALUES)/sizeof(INTVALUES[0]); \
std::vector<int> expected; \
expected.assign(&INTVALUES[0], &INTVALUES[0] + init_values_size); \
BOOST_TEST (std::equal(expected.begin(), expected.end(), ITERATOR) ); \
BOOST_TEST (std::equal(&INTVALUES[0], &INTVALUES[0] + sizeof(INTVALUES)/sizeof(INTVALUES[0]), ITERATOR) ); \
}
#define TEST_INTRUSIVE_SEQUENCE_EXPECTED( EXPECTEDVECTOR, ITERATOR )\

View File

@@ -25,9 +25,9 @@
using namespace boost::intrusive;
static const std::size_t BucketSize = 11;
static const std::size_t BucketSize = 8;
template<class ValueTraits, bool CacheBegin, bool CompareHash>
template<class ValueTraits, bool CacheBegin, bool CompareHash, bool Incremental>
struct test_unordered_multiset
{
typedef typename ValueTraits::value_type value_type;
@@ -35,14 +35,16 @@ struct test_unordered_multiset
static void test_sort(std::vector<value_type>& values);
static void test_insert(std::vector<value_type>& values);
static void test_swap(std::vector<value_type>& values);
static void test_rehash(std::vector<value_type>& values);
static void test_rehash(std::vector<value_type>& values, detail::true_);
static void test_rehash(std::vector<value_type>& values, detail::false_);
static void test_find(std::vector<value_type>& values);
static void test_impl();
static void test_clone(std::vector<value_type>& values);
};
template<class ValueTraits, bool CacheBegin, bool CompareHash>
void test_unordered_multiset<ValueTraits, CacheBegin, CompareHash>::test_all (std::vector<typename ValueTraits::value_type>& values)
template<class ValueTraits, bool CacheBegin, bool CompareHash, bool Incremental>
void test_unordered_multiset<ValueTraits, CacheBegin, CompareHash, Incremental>::
test_all (std::vector<typename ValueTraits::value_type>& values)
{
typedef typename ValueTraits::value_type value_type;
typedef unordered_multiset
@@ -51,6 +53,7 @@ void test_unordered_multiset<ValueTraits, CacheBegin, CompareHash>::test_all (st
, constant_time_size<value_type::constant_time_size>
, cache_begin<CacheBegin>
, compare_hash<CompareHash>
, incremental<Incremental>
> unordered_multiset_type;
{
typedef typename unordered_multiset_type::bucket_traits bucket_traits;
@@ -71,15 +74,16 @@ void test_unordered_multiset<ValueTraits, CacheBegin, CompareHash>::test_all (st
test_sort(values);
test_insert(values);
test_swap(values);
test_rehash(values);
test_rehash(values, detail::bool_<Incremental>());
test_find(values);
test_impl();
test_clone(values);
}
//test case due to an error in tree implementation:
template<class ValueTraits, bool CacheBegin, bool CompareHash>
void test_unordered_multiset<ValueTraits, CacheBegin, CompareHash>::test_impl()
template<class ValueTraits, bool CacheBegin, bool CompareHash, bool Incremental>
void test_unordered_multiset<ValueTraits, CacheBegin, CompareHash, Incremental>
::test_impl()
{
typedef typename ValueTraits::value_type value_type;
typedef unordered_multiset
@@ -88,6 +92,7 @@ void test_unordered_multiset<ValueTraits, CacheBegin, CompareHash>::test_impl()
, constant_time_size<value_type::constant_time_size>
, cache_begin<CacheBegin>
, compare_hash<CompareHash>
, incremental<Incremental>
> unordered_multiset_type;
typedef typename unordered_multiset_type::bucket_traits bucket_traits;
@@ -110,8 +115,9 @@ void test_unordered_multiset<ValueTraits, CacheBegin, CompareHash>::test_impl()
}
//test: constructor, iterator, clear, reverse_iterator, front, back, size:
template<class ValueTraits, bool CacheBegin, bool CompareHash>
void test_unordered_multiset<ValueTraits, CacheBegin, CompareHash>::test_sort(std::vector<typename ValueTraits::value_type>& values)
template<class ValueTraits, bool CacheBegin, bool CompareHash, bool Incremental>
void test_unordered_multiset<ValueTraits, CacheBegin, CompareHash, Incremental>
::test_sort(std::vector<typename ValueTraits::value_type>& values)
{
typedef typename ValueTraits::value_type value_type;
typedef unordered_multiset
@@ -120,21 +126,29 @@ void test_unordered_multiset<ValueTraits, CacheBegin, CompareHash>::test_sort(st
, constant_time_size<value_type::constant_time_size>
, cache_begin<CacheBegin>
, compare_hash<CompareHash>
, incremental<Incremental>
> unordered_multiset_type;
typedef typename unordered_multiset_type::bucket_traits bucket_traits;
typename unordered_multiset_type::bucket_type buckets [BucketSize];
unordered_multiset_type testset1(values.begin(), values.end(), bucket_traits(buckets, BucketSize));
if(Incremental){
{ int init_values [] = { 4, 5, 1, 2, 2, 3 };
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
}
else{
{ int init_values [] = { 1, 2, 2, 3, 4, 5 };
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
}
testset1.clear();
BOOST_TEST (testset1.empty());
}
//test: insert, const_iterator, const_reverse_iterator, erase, iterator_to:
template<class ValueTraits, bool CacheBegin, bool CompareHash>
void test_unordered_multiset<ValueTraits, CacheBegin, CompareHash>::test_insert(std::vector<typename ValueTraits::value_type>& values)
template<class ValueTraits, bool CacheBegin, bool CompareHash, bool Incremental>
void test_unordered_multiset<ValueTraits, CacheBegin, CompareHash, Incremental>
::test_insert(std::vector<typename ValueTraits::value_type>& values)
{
typedef typename ValueTraits::value_type value_type;
typedef unordered_multiset
@@ -143,16 +157,61 @@ void test_unordered_multiset<ValueTraits, CacheBegin, CompareHash>::test_insert(
, constant_time_size<value_type::constant_time_size>
, cache_begin<CacheBegin>
, compare_hash<CompareHash>
, incremental<Incremental>
> unordered_multiset_type;
typedef typename unordered_multiset_type::bucket_traits bucket_traits;
typedef typename unordered_multiset_type::iterator iterator;
{
typename unordered_multiset_type::bucket_type buckets [BucketSize];
unordered_multiset_type testset(bucket_traits(buckets, BucketSize));
testset.insert(&values[0] + 2, &values[0] + 5);
const unordered_multiset_type& const_testset = testset;
if(Incremental){
{
{ int init_values [] = { 4, 5, 1 };
TEST_INTRUSIVE_SEQUENCE( init_values, const_testset.begin() ); }
typename unordered_multiset_type::iterator i = testset.begin();
BOOST_TEST (i->value_ == 4);
i = testset.insert (values[0]);
BOOST_TEST (&*i == &values[0]);
i = testset.iterator_to (values[2]);
BOOST_TEST (&*i == &values[2]);
testset.erase(i);
{ int init_values [] = { 5, 1, 3 };
TEST_INTRUSIVE_SEQUENCE( init_values, const_testset.begin() ); }
testset.clear();
testset.insert(&values[0], &values[0] + values.size());
{ int init_values [] = { 4, 5, 1, 2, 2, 3 };
TEST_INTRUSIVE_SEQUENCE( init_values, const_testset.begin() ); }
BOOST_TEST (testset.erase(1) == 1);
BOOST_TEST (testset.erase(2) == 2);
BOOST_TEST (testset.erase(3) == 1);
BOOST_TEST (testset.erase(4) == 1);
BOOST_TEST (testset.erase(5) == 1);
BOOST_TEST (testset.empty() == true);
//Now with a single bucket
typename unordered_multiset_type::bucket_type single_bucket[1];
unordered_multiset_type testset2(bucket_traits(single_bucket, 1));
testset2.insert(&values[0], &values[0] + values.size());
BOOST_TEST (testset2.erase(5) == 1);
BOOST_TEST (testset2.erase(2) == 2);
BOOST_TEST (testset2.erase(1) == 1);
BOOST_TEST (testset2.erase(4) == 1);
BOOST_TEST (testset2.erase(3) == 1);
BOOST_TEST (testset2.empty() == true);
}
}
else{
{
{ int init_values [] = { 1, 4, 5 };
TEST_INTRUSIVE_SEQUENCE( init_values, const_testset.begin() ); }
@@ -192,6 +251,7 @@ void test_unordered_multiset<ValueTraits, CacheBegin, CompareHash>::test_insert(
BOOST_TEST (testset2.erase(3) == 1);
BOOST_TEST (testset2.empty() == true);
}
}
{
//Now erase just one per loop
const int random_init[] = { 3, 2, 4, 1, 5, 2, 2 };
@@ -273,8 +333,9 @@ void test_unordered_multiset<ValueTraits, CacheBegin, CompareHash>::test_insert(
}
//test: insert (seq-version), swap, erase (seq-version), size:
template<class ValueTraits, bool CacheBegin, bool CompareHash>
void test_unordered_multiset<ValueTraits, CacheBegin, CompareHash>::test_swap(std::vector<typename ValueTraits::value_type>& values)
template<class ValueTraits, bool CacheBegin, bool CompareHash, bool Incremental>
void test_unordered_multiset<ValueTraits, CacheBegin, CompareHash, Incremental>::
test_swap(std::vector<typename ValueTraits::value_type>& values)
{
typedef typename ValueTraits::value_type value_type;
typedef unordered_multiset
@@ -283,10 +344,11 @@ void test_unordered_multiset<ValueTraits, CacheBegin, CompareHash>::test_swap(st
, constant_time_size<value_type::constant_time_size>
, cache_begin<CacheBegin>
, compare_hash<CompareHash>
, incremental<Incremental>
> unordered_multiset_type;
typedef typename unordered_multiset_type::bucket_traits bucket_traits;
typename unordered_multiset_type::bucket_type buckets [BucketSize];
{
typename unordered_multiset_type::bucket_type buckets2 [BucketSize];
unordered_multiset_type testset1(&values[0], &values[0] + 2, bucket_traits(buckets, BucketSize));
unordered_multiset_type testset2(bucket_traits(buckets2, BucketSize));
@@ -294,6 +356,18 @@ void test_unordered_multiset<ValueTraits, CacheBegin, CompareHash>::test_swap(st
testset2.insert (&values[0] + 2, &values[0] + 6);
testset1.swap (testset2);
if(Incremental){
{ int init_values [] = { 4, 5, 1, 2 };
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
{ int init_values [] = { 2, 3 };
TEST_INTRUSIVE_SEQUENCE( init_values, testset2.begin() ); }
testset1.erase (testset1.iterator_to(values[4]), testset1.end());
BOOST_TEST (testset1.size() == 1);
// BOOST_TEST (&testset1.front() == &values[3]);
BOOST_TEST (&*testset1.begin() == &values[2]);
}
else{
{ int init_values [] = { 1, 2, 4, 5 };
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
@@ -306,9 +380,13 @@ void test_unordered_multiset<ValueTraits, CacheBegin, CompareHash>::test_swap(st
}
}
//test: rehash:
template<class ValueTraits, bool CacheBegin, bool CompareHash>
void test_unordered_multiset<ValueTraits, CacheBegin, CompareHash>::test_rehash(std::vector<typename ValueTraits::value_type>& values)
template<class ValueTraits, bool CacheBegin, bool CompareHash, bool Incremental>
void test_unordered_multiset<ValueTraits, CacheBegin, CompareHash, Incremental>
::test_rehash(std::vector<typename ValueTraits::value_type>& values, detail::true_)
{
typedef typename ValueTraits::value_type value_type;
typedef unordered_multiset
@@ -317,6 +395,135 @@ void test_unordered_multiset<ValueTraits, CacheBegin, CompareHash>::test_rehash(
, constant_time_size<value_type::constant_time_size>
, cache_begin<CacheBegin>
, compare_hash<CompareHash>
, incremental<Incremental>
> unordered_multiset_type;
typedef typename unordered_multiset_type::bucket_traits bucket_traits;
//Build a uset
typename unordered_multiset_type::bucket_type buckets1 [BucketSize];
typename unordered_multiset_type::bucket_type buckets2 [BucketSize*2];
unordered_multiset_type testset1(&values[0], &values[0] + values.size(), bucket_traits(buckets1, BucketSize));
//Test current state
BOOST_TEST(testset1.split_count() == BucketSize/2);
{ int init_values [] = { 4, 5, 1, 2, 2, 3 };
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
//Incremental rehash step
BOOST_TEST (testset1.incremental_rehash() == true);
BOOST_TEST(testset1.split_count() == (BucketSize/2+1));
{ int init_values [] = { 5, 1, 2, 2, 3, 4 };
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
//Rest of incremental rehashes should lead to the same sequence
for(std::size_t split_bucket = testset1.split_count(); split_bucket != BucketSize; ++split_bucket){
BOOST_TEST (testset1.incremental_rehash() == true);
BOOST_TEST(testset1.split_count() == (split_bucket+1));
{ int init_values [] = { 1, 2, 2, 3, 4, 5 };
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
}
//This incremental rehash should fail because we've reached the end of the bucket array
BOOST_TEST (testset1.incremental_rehash() == false);
BOOST_TEST(testset1.split_count() == BucketSize);
{ int init_values [] = { 1, 2, 2, 3, 4, 5 };
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
//
//Try incremental hashing specifying a new bucket traits pointing to the same array
//
//This incremental rehash should fail because the new size is not twice the original
BOOST_TEST(testset1.incremental_rehash(bucket_traits(buckets1, BucketSize)) == false);
BOOST_TEST(testset1.split_count() == BucketSize);
{ int init_values [] = { 1, 2, 2, 3, 4, 5 };
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
//This incremental rehash should success because the new size is twice the original
//and split_count is the same as the old bucket count
BOOST_TEST(testset1.incremental_rehash(bucket_traits(buckets1, BucketSize*2)) == true);
BOOST_TEST(testset1.split_count() == BucketSize);
{ int init_values [] = { 1, 2, 2, 3, 4, 5 };
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
//This incremental rehash should also success because the new size is half the original
//and split_count is the same as the new bucket count
BOOST_TEST(testset1.incremental_rehash(bucket_traits(buckets1, BucketSize)) == true);
BOOST_TEST(testset1.split_count() == BucketSize);
{ int init_values [] = { 1, 2, 2, 3, 4, 5 };
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
//
//Try incremental hashing specifying a new bucket traits pointing to the same array
//
//This incremental rehash should fail because the new size is not twice the original
BOOST_TEST(testset1.incremental_rehash(bucket_traits(buckets2, BucketSize)) == false);
BOOST_TEST(testset1.split_count() == BucketSize);
{ int init_values [] = { 1, 2, 2, 3, 4, 5 };
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
//This incremental rehash should success because the new size is twice the original
//and split_count is the same as the old bucket count
BOOST_TEST(testset1.incremental_rehash(bucket_traits(buckets2, BucketSize*2)) == true);
BOOST_TEST(testset1.split_count() == BucketSize);
{ int init_values [] = { 1, 2, 2, 3, 4, 5 };
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
//This incremental rehash should also success because the new size is half the original
//and split_count is the same as the new bucket count
BOOST_TEST(testset1.incremental_rehash(bucket_traits(buckets1, BucketSize)) == true);
BOOST_TEST(testset1.split_count() == BucketSize);
{ int init_values [] = { 1, 2, 2, 3, 4, 5 };
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
//Full shrink rehash
testset1.rehash(bucket_traits(buckets1, 4));
BOOST_TEST (testset1.size() == values.size());
BOOST_TEST (testset1.incremental_rehash() == false);
{ int init_values [] = { 4, 5, 1, 2, 2, 3 };
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
//Full shrink rehash again
testset1.rehash(bucket_traits(buckets1, 2));
BOOST_TEST (testset1.size() == values.size());
BOOST_TEST (testset1.incremental_rehash() == false);
{ int init_values [] = { 2, 2, 4, 3, 5, 1 };
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
//Full growing rehash
testset1.rehash(bucket_traits(buckets1, BucketSize));
BOOST_TEST (testset1.size() == values.size());
BOOST_TEST (testset1.incremental_rehash() == false);
{ int init_values [] = { 1, 2, 2, 3, 4, 5 };
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
//Incremental rehash shrinking
//First incremental rehashes should lead to the same sequence
for(std::size_t split_bucket = testset1.split_count(); split_bucket > 6; --split_bucket){
BOOST_TEST (testset1.incremental_rehash(false) == true);
BOOST_TEST(testset1.split_count() == (split_bucket-1));
{ int init_values [] = { 1, 2, 2, 3, 4, 5 };
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
}
//Incremental rehash step
BOOST_TEST (testset1.incremental_rehash(false) == true);
BOOST_TEST(testset1.split_count() == (BucketSize/2+1));
{ int init_values [] = { 5, 1, 2, 2, 3, 4 };
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
//Incremental rehash step 2
BOOST_TEST (testset1.incremental_rehash(false) == true);
BOOST_TEST(testset1.split_count() == (BucketSize/2));
{ int init_values [] = { 4, 5, 1, 2, 2, 3 };
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
//This incremental rehash should fail because we've reached the half of the bucket array
BOOST_TEST(testset1.incremental_rehash(false) == false);
BOOST_TEST(testset1.split_count() == BucketSize/2);
{ int init_values [] = { 4, 5, 1, 2, 2, 3 };
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
}
template<class ValueTraits, bool CacheBegin, bool CompareHash, bool Incremental>
void test_unordered_multiset<ValueTraits, CacheBegin, CompareHash, Incremental>
::test_rehash(std::vector<typename ValueTraits::value_type>& values, detail::false_)
{
typedef typename ValueTraits::value_type value_type;
typedef unordered_multiset
<value_type
, value_traits<ValueTraits>
, constant_time_size<value_type::constant_time_size>
, cache_begin<CacheBegin>
, compare_hash<CompareHash>
, incremental<Incremental>
> unordered_multiset_type;
typedef typename unordered_multiset_type::bucket_traits bucket_traits;
@@ -325,36 +532,37 @@ void test_unordered_multiset<ValueTraits, CacheBegin, CompareHash>::test_rehash(
typename unordered_multiset_type::bucket_type buckets3 [BucketSize*2];
unordered_multiset_type testset1(&values[0], &values[0] + 6, bucket_traits(buckets1, BucketSize));
BOOST_TEST (testset1.size() == 6);
BOOST_TEST (testset1.size() == values.size());
{ int init_values [] = { 1, 2, 2, 3, 4, 5 };
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
testset1.rehash(bucket_traits(buckets2, 2));
BOOST_TEST (testset1.size() == 6);
BOOST_TEST (testset1.size() == values.size());
{ int init_values [] = { 4, 2, 2, 5, 3, 1 };
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
testset1.rehash(bucket_traits(buckets3, BucketSize*2));
BOOST_TEST (testset1.size() == 6);
BOOST_TEST (testset1.size() == values.size());
{ int init_values [] = { 1, 2, 2, 3, 4, 5 };
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
//Now rehash reducing the buckets
testset1.rehash(bucket_traits(buckets3, 2));
BOOST_TEST (testset1.size() == 6);
BOOST_TEST (testset1.size() == values.size());
{ int init_values [] = { 4, 2, 2, 5, 3, 1 };
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
//Now rehash increasing the buckets
testset1.rehash(bucket_traits(buckets3, BucketSize*2));
BOOST_TEST (testset1.size() == 6);
BOOST_TEST (testset1.size() == values.size());
{ int init_values [] = { 1, 2, 2, 3, 4, 5 };
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
}
//test: find, equal_range (lower_bound, upper_bound):
template<class ValueTraits, bool CacheBegin, bool CompareHash>
void test_unordered_multiset<ValueTraits, CacheBegin, CompareHash>::test_find(std::vector<typename ValueTraits::value_type>& values)
template<class ValueTraits, bool CacheBegin, bool CompareHash, bool Incremental>
void test_unordered_multiset<ValueTraits, CacheBegin, CompareHash, Incremental>::
test_find(std::vector<typename ValueTraits::value_type>& values)
{
typedef typename ValueTraits::value_type value_type;
typedef unordered_multiset
@@ -363,6 +571,7 @@ void test_unordered_multiset<ValueTraits, CacheBegin, CompareHash>::test_find(st
, constant_time_size<value_type::constant_time_size>
, cache_begin<CacheBegin>
, compare_hash<CompareHash>
, incremental<Incremental>
> unordered_multiset_type;
typedef typename unordered_multiset_type::bucket_traits bucket_traits;
@@ -387,8 +596,8 @@ void test_unordered_multiset<ValueTraits, CacheBegin, CompareHash>::test_find(st
}
template<class ValueTraits, bool CacheBegin, bool CompareHash>
void test_unordered_multiset<ValueTraits, CacheBegin, CompareHash>
template<class ValueTraits, bool CacheBegin, bool CompareHash, bool Incremental>
void test_unordered_multiset<ValueTraits, CacheBegin, CompareHash, Incremental>
::test_clone(std::vector<typename ValueTraits::value_type>& values)
{
typedef typename ValueTraits::value_type value_type;
@@ -398,6 +607,7 @@ void test_unordered_multiset<ValueTraits, CacheBegin, CompareHash>
, constant_time_size<value_type::constant_time_size>
, cache_begin<CacheBegin>
, compare_hash<CompareHash>
, incremental<Incremental>
> unordered_multiset_type;
typedef typename unordered_multiset_type::bucket_traits bucket_traits;
{
@@ -442,7 +652,7 @@ void test_unordered_multiset<ValueTraits, CacheBegin, CompareHash>
unordered_multiset_type testset2 (bucket_traits(buckets2, BucketSize*2));
testset2.clone_from(testset1, test::new_cloner<value_type>(), test::delete_disposer<value_type>());
//Ordering is not guarantee in the cloning so insert data in a set and test
//Ordering is not guaranteed in the cloning so insert data in a set and test
std::multiset<typename ValueTraits::value_type>
src(testset1.begin(), testset1.end());
std::multiset<typename ValueTraits::value_type>
@@ -453,7 +663,7 @@ void test_unordered_multiset<ValueTraits, CacheBegin, CompareHash>
}
}
template<class VoidPointer, bool constant_time_size>
template<class VoidPointer, bool constant_time_size, bool Incremental>
class test_main_template
{
public:
@@ -471,6 +681,7 @@ class test_main_template
>::type
, true
, false
, Incremental
>::test_all(data);
test_unordered_multiset < typename detail::get_member_value_traits
@@ -482,14 +693,15 @@ class test_main_template
>::type
, false
, false
, Incremental
>::test_all(data);
return 0;
}
};
template<class VoidPointer>
class test_main_template<VoidPointer, false>
template<class VoidPointer, bool Incremental>
class test_main_template<VoidPointer, false, Incremental>
{
public:
int operator()()
@@ -506,6 +718,7 @@ class test_main_template<VoidPointer, false>
>::type
, true
, false
, Incremental
>::test_all(data);
test_unordered_multiset < typename detail::get_member_value_traits
@@ -517,6 +730,7 @@ class test_main_template<VoidPointer, false>
>::type
, false
, false
, Incremental
>::test_all(data);
test_unordered_multiset < typename detail::get_base_value_traits
@@ -525,6 +739,7 @@ class test_main_template<VoidPointer, false>
>::type
, true
, true
, Incremental
>::test_all(data);
test_unordered_multiset < typename detail::get_member_value_traits
@@ -536,6 +751,7 @@ class test_main_template<VoidPointer, false>
>::type
, false
, true
, Incremental
>::test_all(data);
return 0;
}
@@ -543,10 +759,14 @@ class test_main_template<VoidPointer, false>
int main( int, char* [] )
{
test_main_template<void*, false>()();
test_main_template<smart_ptr<void>, false>()();
test_main_template<void*, true>()();
test_main_template<smart_ptr<void>, true>()();
test_main_template<void*, false, true>()();
test_main_template<smart_ptr<void>, false, true>()();
test_main_template<void*, true, true>()();
test_main_template<smart_ptr<void>, true, true>()();
test_main_template<void*, false, false>()();
test_main_template<smart_ptr<void>, false, false>()();
test_main_template<void*, true, true>()();
test_main_template<smart_ptr<void>, true, false>()();
return boost::report_errors();
}

View File

@@ -24,9 +24,9 @@
using namespace boost::intrusive;
static const std::size_t BucketSize = 11;
static const std::size_t BucketSize = 8;
template<class ValueTraits, bool CacheBegin, bool CompareHash>
template<class ValueTraits, bool CacheBegin, bool CompareHash, bool Incremental>
struct test_unordered_set
{
typedef typename ValueTraits::value_type value_type;
@@ -34,14 +34,16 @@ struct test_unordered_set
static void test_sort(std::vector<value_type>& values);
static void test_insert(std::vector<value_type>& values);
static void test_swap(std::vector<value_type>& values);
static void test_rehash(std::vector<value_type>& values);
static void test_rehash(std::vector<value_type>& values, detail::true_);
static void test_rehash(std::vector<value_type>& values, detail::false_);
static void test_find(std::vector<value_type>& values);
static void test_impl();
static void test_clone(std::vector<value_type>& values);
};
template<class ValueTraits, bool CacheBegin, bool CompareHash>
void test_unordered_set<ValueTraits, CacheBegin, CompareHash>::test_all(std::vector<typename ValueTraits::value_type>& values)
template<class ValueTraits, bool CacheBegin, bool CompareHash, bool Incremental>
void test_unordered_set<ValueTraits, CacheBegin, CompareHash, Incremental>::
test_all(std::vector<typename ValueTraits::value_type>& values)
{
typedef typename ValueTraits::value_type value_type;
typedef unordered_set
@@ -50,6 +52,7 @@ void test_unordered_set<ValueTraits, CacheBegin, CompareHash>::test_all(std::vec
, constant_time_size<value_type::constant_time_size>
, cache_begin<CacheBegin>
, compare_hash<CompareHash>
, incremental<Incremental>
> unordered_set_type;
typedef typename unordered_set_type::bucket_traits bucket_traits;
{
@@ -70,15 +73,15 @@ void test_unordered_set<ValueTraits, CacheBegin, CompareHash>::test_all(std::vec
test_sort(values);
test_insert(values);
test_swap(values);
test_rehash(values);
test_rehash(values, detail::bool_<Incremental>());
test_find(values);
test_impl();
test_clone(values);
}
//test case due to an error in tree implementation:
template<class ValueTraits, bool CacheBegin, bool CompareHash>
void test_unordered_set<ValueTraits, CacheBegin, CompareHash>::test_impl()
template<class ValueTraits, bool CacheBegin, bool CompareHash, bool Incremental>
void test_unordered_set<ValueTraits, CacheBegin, CompareHash, Incremental>::test_impl()
{
typedef typename ValueTraits::value_type value_type;
typedef unordered_set
@@ -87,6 +90,7 @@ void test_unordered_set<ValueTraits, CacheBegin, CompareHash>::test_impl()
, constant_time_size<value_type::constant_time_size>
, cache_begin<CacheBegin>
, compare_hash<CompareHash>
, incremental<Incremental>
> unordered_set_type;
typedef typename unordered_set_type::bucket_traits bucket_traits;
@@ -107,8 +111,9 @@ void test_unordered_set<ValueTraits, CacheBegin, CompareHash>::test_impl()
}
//test: constructor, iterator, clear, reverse_iterator, front, back, size:
template<class ValueTraits, bool CacheBegin, bool CompareHash>
void test_unordered_set<ValueTraits, CacheBegin, CompareHash>::test_sort(std::vector<typename ValueTraits::value_type>& values)
template<class ValueTraits, bool CacheBegin, bool CompareHash, bool Incremental>
void test_unordered_set<ValueTraits, CacheBegin, CompareHash, Incremental>::
test_sort(std::vector<typename ValueTraits::value_type>& values)
{
typedef typename ValueTraits::value_type value_type;
typedef unordered_set
@@ -117,23 +122,31 @@ void test_unordered_set<ValueTraits, CacheBegin, CompareHash>::test_sort(std::ve
, constant_time_size<value_type::constant_time_size>
, cache_begin<CacheBegin>
, compare_hash<CompareHash>
, incremental<Incremental>
> unordered_set_type;
typedef typename unordered_set_type::bucket_traits bucket_traits;
typename unordered_set_type::bucket_type buckets [BucketSize];
unordered_set_type testset1(values.begin(), values.end(), bucket_traits(buckets, BucketSize));
BOOST_TEST (5 == std::distance(testset1.begin(), testset1.end()));
if(Incremental){
{ int init_values [] = { 4, 5, 1, 2, 3 };
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
}
else{
{ int init_values [] = { 1, 2, 3, 4, 5 };
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
}
testset1.clear();
BOOST_TEST (testset1.empty());
}
//test: insert, const_iterator, const_reverse_iterator, erase, iterator_to:
template<class ValueTraits, bool CacheBegin, bool CompareHash>
void test_unordered_set<ValueTraits, CacheBegin, CompareHash>::test_insert(std::vector<typename ValueTraits::value_type>& values)
template<class ValueTraits, bool CacheBegin, bool CompareHash, bool Incremental>
void test_unordered_set<ValueTraits, CacheBegin, CompareHash, Incremental>::
test_insert(std::vector<typename ValueTraits::value_type>& values)
{
typedef typename ValueTraits::value_type value_type;
typedef unordered_set
@@ -142,6 +155,7 @@ void test_unordered_set<ValueTraits, CacheBegin, CompareHash>::test_insert(std::
, constant_time_size<value_type::constant_time_size>
, cache_begin<CacheBegin>
, compare_hash<CompareHash>
, incremental<Incremental>
> unordered_set_type;
typedef typename unordered_set_type::bucket_traits bucket_traits;
@@ -150,9 +164,27 @@ void test_unordered_set<ValueTraits, CacheBegin, CompareHash>::test_insert(std::
testset.insert(&values[0] + 2, &values[0] + 5);
const unordered_set_type& const_testset = testset;
if(Incremental)
{
{ int init_values [] = { 4, 5, 1 };
TEST_INTRUSIVE_SEQUENCE( init_values, const_testset.begin() ); }
typename unordered_set_type::iterator i = testset.begin();
BOOST_TEST (i->value_ == 4);
i = testset.insert(values[0]).first;
BOOST_TEST (&*i == &values[0]);
i = testset.iterator_to (values[2]);
BOOST_TEST (&*i == &values[2]);
testset.erase (i);
{ int init_values [] = { 5, 1, 3 };
TEST_INTRUSIVE_SEQUENCE( init_values, const_testset.begin() ); }
}
else{
{ int init_values [] = { 1, 4, 5 };
TEST_INTRUSIVE_SEQUENCE( init_values, const_testset.begin() ); }
typename unordered_set_type::iterator i = testset.begin();
BOOST_TEST (i->value_ == 1);
@@ -167,10 +199,12 @@ void test_unordered_set<ValueTraits, CacheBegin, CompareHash>::test_insert(std::
{ int init_values [] = { 1, 3, 5 };
TEST_INTRUSIVE_SEQUENCE( init_values, const_testset.begin() ); }
}
}
//test: insert (seq-version), swap, erase (seq-version), size:
template<class ValueTraits, bool CacheBegin, bool CompareHash>
void test_unordered_set<ValueTraits, CacheBegin, CompareHash>::test_swap(std::vector<typename ValueTraits::value_type>& values)
template<class ValueTraits, bool CacheBegin, bool CompareHash, bool Incremental>
void test_unordered_set<ValueTraits, CacheBegin, CompareHash, Incremental>::
test_swap(std::vector<typename ValueTraits::value_type>& values)
{
typedef typename ValueTraits::value_type value_type;
typedef unordered_set
@@ -179,6 +213,7 @@ void test_unordered_set<ValueTraits, CacheBegin, CompareHash>::test_swap(std::ve
, constant_time_size<value_type::constant_time_size>
, cache_begin<CacheBegin>
, compare_hash<CompareHash>
, incremental<Incremental>
> unordered_set_type;
typedef typename unordered_set_type::bucket_traits bucket_traits;
@@ -190,20 +225,30 @@ void test_unordered_set<ValueTraits, CacheBegin, CompareHash>::test_swap(std::ve
testset2.insert (&values[0] + 2, &values[0] + 6);
testset1.swap (testset2);
if(Incremental){
{ int init_values [] = { 4, 5, 1, 2 };
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
{ int init_values [] = { 2, 3 };
TEST_INTRUSIVE_SEQUENCE( init_values, testset2.begin() ); }
testset1.erase (testset1.iterator_to(values[4]), testset1.end());
BOOST_TEST (testset1.size() == 1);
BOOST_TEST (&*testset1.begin() == &values[2]);
}
else{
{ int init_values [] = { 1, 2, 4, 5 };
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
{ int init_values [] = { 2, 3 };
TEST_INTRUSIVE_SEQUENCE( init_values, testset2.begin() ); }
testset1.erase (testset1.iterator_to(values[5]), testset1.end());
BOOST_TEST (testset1.size() == 1);
// BOOST_TEST (&testset1.front() == &values[3]);
BOOST_TEST (&*testset1.begin() == &values[3]);
}
}
//test: rehash:
template<class ValueTraits, bool CacheBegin, bool CompareHash>
void test_unordered_set<ValueTraits, CacheBegin, CompareHash>::test_rehash(std::vector<typename ValueTraits::value_type>& values)
template<class ValueTraits, bool CacheBegin, bool CompareHash, bool Incremental>
void test_unordered_set<ValueTraits, CacheBegin, CompareHash, Incremental>::
test_rehash(std::vector<typename ValueTraits::value_type>& values, detail::true_)
{
typedef typename ValueTraits::value_type value_type;
typedef unordered_set
@@ -212,6 +257,137 @@ void test_unordered_set<ValueTraits, CacheBegin, CompareHash>::test_rehash(std::
, constant_time_size<value_type::constant_time_size>
, cache_begin<CacheBegin>
, compare_hash<CompareHash>
, incremental<Incremental>
> unordered_set_type;
typedef typename unordered_set_type::bucket_traits bucket_traits;
//Build a uset
typename unordered_set_type::bucket_type buckets1 [BucketSize];
typename unordered_set_type::bucket_type buckets2 [BucketSize*2];
unordered_set_type testset1(&values[0], &values[0] + 6, bucket_traits(buckets1, BucketSize));
//Test current state
BOOST_TEST(testset1.split_count() == BucketSize/2);
{ int init_values [] = { 4, 5, 1, 2, 3 };
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
//Incremental rehash step
BOOST_TEST (testset1.incremental_rehash() == true);
BOOST_TEST(testset1.split_count() == (BucketSize/2+1));
{ int init_values [] = { 5, 1, 2, 3, 4 };
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
//Rest of incremental rehashes should lead to the same sequence
for(std::size_t split_bucket = testset1.split_count(); split_bucket != BucketSize; ++split_bucket){
BOOST_TEST (testset1.incremental_rehash() == true);
BOOST_TEST(testset1.split_count() == (split_bucket+1));
{ int init_values [] = { 1, 2, 3, 4, 5 };
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
}
//This incremental rehash should fail because we've reached the end of the bucket array
BOOST_TEST(testset1.incremental_rehash() == false);
BOOST_TEST(testset1.split_count() == BucketSize);
{ int init_values [] = { 1, 2, 3, 4, 5 };
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
//
//Try incremental hashing specifying a new bucket traits pointing to the same array
//
//This incremental rehash should fail because the new size is not twice the original
BOOST_TEST(testset1.incremental_rehash(bucket_traits(buckets1, BucketSize)) == false);
BOOST_TEST(testset1.split_count() == BucketSize);
{ int init_values [] = { 1, 2, 3, 4, 5 };
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
//This incremental rehash should success because the new size is twice the original
//and split_count is the same as the old bucket count
BOOST_TEST(testset1.incremental_rehash(bucket_traits(buckets1, BucketSize*2)) == true);
BOOST_TEST(testset1.split_count() == BucketSize);
{ int init_values [] = { 1, 2, 3, 4, 5 };
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
//This incremental rehash should also success because the new size is half the original
//and split_count is the same as the new bucket count
BOOST_TEST(testset1.incremental_rehash(bucket_traits(buckets1, BucketSize)) == true);
BOOST_TEST(testset1.split_count() == BucketSize);
{ int init_values [] = { 1, 2, 3, 4, 5 };
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
//
//Try incremental hashing specifying a new bucket traits pointing to the same array
//
//This incremental rehash should fail because the new size is not twice the original
BOOST_TEST(testset1.incremental_rehash(bucket_traits(buckets2, BucketSize)) == false);
BOOST_TEST(testset1.split_count() == BucketSize);
{ int init_values [] = { 1, 2, 3, 4, 5 };
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
//This incremental rehash should success because the new size is twice the original
//and split_count is the same as the old bucket count
BOOST_TEST(testset1.incremental_rehash(bucket_traits(buckets2, BucketSize*2)) == true);
BOOST_TEST(testset1.split_count() == BucketSize);
{ int init_values [] = { 1, 2, 3, 4, 5 };
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
//This incremental rehash should also success because the new size is half the original
//and split_count is the same as the new bucket count
BOOST_TEST(testset1.incremental_rehash(bucket_traits(buckets1, BucketSize)) == true);
BOOST_TEST(testset1.split_count() == BucketSize);
{ int init_values [] = { 1, 2, 3, 4, 5 };
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
//Full shrink rehash
testset1.rehash(bucket_traits(buckets1, 4));
BOOST_TEST (testset1.size() == values.size()-1);
BOOST_TEST (testset1.incremental_rehash() == false);
{ int init_values [] = { 4, 5, 1, 2, 3 };
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
//Full shrink rehash again
testset1.rehash(bucket_traits(buckets1, 2));
BOOST_TEST (testset1.size() == values.size()-1);
BOOST_TEST (testset1.incremental_rehash() == false);
{ int init_values [] = { 2, 4, 3, 5, 1 };
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
//Full growing rehash
testset1.rehash(bucket_traits(buckets1, BucketSize));
BOOST_TEST (testset1.size() == values.size()-1);
BOOST_TEST (testset1.incremental_rehash() == false);
{ int init_values [] = { 1, 2, 3, 4, 5 };
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
//Incremental rehash shrinking
//First incremental rehashes should lead to the same sequence
for(std::size_t split_bucket = testset1.split_count(); split_bucket > 6; --split_bucket){
BOOST_TEST (testset1.incremental_rehash(false) == true);
BOOST_TEST(testset1.split_count() == (split_bucket-1));
{ int init_values [] = { 1, 2, 3, 4, 5 };
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
}
//Incremental rehash step
BOOST_TEST (testset1.incremental_rehash(false) == true);
BOOST_TEST(testset1.split_count() == (BucketSize/2+1));
{ int init_values [] = { 5, 1, 2, 3, 4 };
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
//Incremental rehash step 2
BOOST_TEST (testset1.incremental_rehash(false) == true);
BOOST_TEST(testset1.split_count() == (BucketSize/2));
{ int init_values [] = { 4, 5, 1, 2, 3 };
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
//This incremental rehash should fail because we've reached the half of the bucket array
BOOST_TEST(testset1.incremental_rehash(false) == false);
BOOST_TEST(testset1.split_count() == BucketSize/2);
{ int init_values [] = { 4, 5, 1, 2, 3 };
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
}
//test: rehash:
template<class ValueTraits, bool CacheBegin, bool CompareHash, bool Incremental>
void test_unordered_set<ValueTraits, CacheBegin, CompareHash, Incremental>::
test_rehash(std::vector<typename ValueTraits::value_type>& values, detail::false_)
{
typedef typename ValueTraits::value_type value_type;
typedef unordered_set
<value_type
, value_traits<ValueTraits>
, constant_time_size<value_type::constant_time_size>
, cache_begin<CacheBegin>
, compare_hash<CompareHash>
, incremental<Incremental>
> unordered_set_type;
typedef typename unordered_set_type::bucket_traits bucket_traits;
@@ -220,37 +396,38 @@ void test_unordered_set<ValueTraits, CacheBegin, CompareHash>::test_rehash(std::
typename unordered_set_type::bucket_type buckets3 [BucketSize*2];
unordered_set_type testset1(&values[0], &values[0] + 6, bucket_traits(buckets1, BucketSize));
BOOST_TEST (testset1.size() == 5);
BOOST_TEST (testset1.size() == values.size()-1);
{ int init_values [] = { 1, 2, 3, 4, 5 };
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
testset1.rehash(bucket_traits(buckets2, 2));
BOOST_TEST (testset1.size() == 5);
BOOST_TEST (testset1.size() == values.size()-1);
{ int init_values [] = { 4, 2, 5, 3, 1 };
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
testset1.rehash(bucket_traits(buckets3, BucketSize*2));
BOOST_TEST (testset1.size() == 5);
BOOST_TEST (testset1.size() == values.size()-1);
{ int init_values [] = { 1, 2, 3, 4, 5 };
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
//Now rehash reducing the buckets
testset1.rehash(bucket_traits(buckets3, 2));
BOOST_TEST (testset1.size() == 5);
BOOST_TEST (testset1.size() == values.size()-1);
{ int init_values [] = { 4, 2, 5, 3, 1 };
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
//Now rehash increasing the buckets
testset1.rehash(bucket_traits(buckets3, BucketSize*2));
BOOST_TEST (testset1.size() == 5);
BOOST_TEST (testset1.size() == values.size()-1);
{ int init_values [] = { 1, 2, 3, 4, 5 };
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
}
//test: find, equal_range (lower_bound, upper_bound):
template<class ValueTraits, bool CacheBegin, bool CompareHash>
void test_unordered_set<ValueTraits, CacheBegin, CompareHash>::test_find(std::vector<typename ValueTraits::value_type>& values)
template<class ValueTraits, bool CacheBegin, bool CompareHash, bool Incremental>
void test_unordered_set<ValueTraits, CacheBegin, CompareHash, Incremental>::
test_find(std::vector<typename ValueTraits::value_type>& values)
{
typedef typename ValueTraits::value_type value_type;
typedef unordered_set
@@ -259,6 +436,7 @@ void test_unordered_set<ValueTraits, CacheBegin, CompareHash>::test_find(std::ve
, constant_time_size<value_type::constant_time_size>
, cache_begin<CacheBegin>
, compare_hash<CompareHash>
, incremental<Incremental>
> unordered_set_type;
typedef typename unordered_set_type::bucket_traits bucket_traits;
@@ -281,8 +459,8 @@ void test_unordered_set<ValueTraits, CacheBegin, CompareHash>::test_find(std::ve
BOOST_TEST (testset.find (cmp_val) == testset.end());
}
template<class ValueTraits, bool CacheBegin, bool CompareHash>
void test_unordered_set<ValueTraits, CacheBegin, CompareHash>
template<class ValueTraits, bool CacheBegin, bool CompareHash, bool Incremental>
void test_unordered_set<ValueTraits, CacheBegin, CompareHash, Incremental>
::test_clone(std::vector<typename ValueTraits::value_type>& values)
{
typedef typename ValueTraits::value_type value_type;
@@ -292,6 +470,7 @@ void test_unordered_set<ValueTraits, CacheBegin, CompareHash>
, constant_time_size<value_type::constant_time_size>
, cache_begin<CacheBegin>
, compare_hash<CompareHash>
, incremental<Incremental>
> unordered_set_type;
typedef typename unordered_set_type::bucket_traits bucket_traits;
{
@@ -319,7 +498,7 @@ void test_unordered_set<ValueTraits, CacheBegin, CompareHash>
unordered_set_type testset2 (bucket_traits(buckets2, BucketSize));
testset2.clone_from(testset1, test::new_cloner<value_type>(), test::delete_disposer<value_type>());
//Ordering is not guarantee in the cloning so insert data in a set and test
//Ordering is not guaranteed in the cloning so insert data in a set and test
std::set<typename ValueTraits::value_type>
src(testset1.begin(), testset1.end());
std::set<typename ValueTraits::value_type>
@@ -347,7 +526,7 @@ void test_unordered_set<ValueTraits, CacheBegin, CompareHash>
}
}
template<class VoidPointer, bool constant_time_size>
template<class VoidPointer, bool constant_time_size, bool incremental>
class test_main_template
{
public:
@@ -365,6 +544,7 @@ class test_main_template
>::type
, true
, false
, incremental
>::test_all(data);
test_unordered_set < typename detail::get_member_value_traits
< value_type
@@ -375,14 +555,15 @@ class test_main_template
>::type
, false
, false
, incremental
>::test_all(data);
return 0;
}
};
template<class VoidPointer>
class test_main_template<VoidPointer, false>
template<class VoidPointer, bool incremental>
class test_main_template<VoidPointer, false, incremental>
{
public:
int operator()()
@@ -399,6 +580,7 @@ class test_main_template<VoidPointer, false>
>::type
, true
, false
, incremental
>::test_all(data);
test_unordered_set < typename detail::get_member_value_traits
@@ -410,6 +592,7 @@ class test_main_template<VoidPointer, false>
>::type
, false
, false
, incremental
>::test_all(data);
test_unordered_set < typename detail::get_base_value_traits
@@ -418,6 +601,7 @@ class test_main_template<VoidPointer, false>
>::type
, true
, true
, incremental
>::test_all(data);
test_unordered_set < typename detail::get_member_value_traits
@@ -429,6 +613,7 @@ class test_main_template<VoidPointer, false>
>::type
, false
, true
, incremental
>::test_all(data);
return 0;
}
@@ -436,10 +621,14 @@ class test_main_template<VoidPointer, false>
int main( int, char* [] )
{
test_main_template<void*, false>()();
test_main_template<smart_ptr<void>, false>()();
test_main_template<void*, true>()();
test_main_template<smart_ptr<void>, true>()();
test_main_template<void*, false, true>()();
test_main_template<smart_ptr<void>, false, true>()();
test_main_template<void*, true, true>()();
test_main_template<smart_ptr<void>, true, true>()();
test_main_template<void*, false, false>()();
test_main_template<smart_ptr<void>, false, false>()();
test_main_template<void*, true, true>()();
test_main_template<smart_ptr<void>, true, false>()();
return boost::report_errors();
}
#include <boost/intrusive/detail/config_end.hpp>