Changes introduced by the new intrusive version.

[SVN r39550]
This commit is contained in:
Ion Gaztañaga
2007-09-26 17:38:32 +00:00
parent cbb4812c00
commit c4aa57001c
32 changed files with 2259 additions and 1025 deletions

View File

@ -10,7 +10,7 @@
// //
///////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////
//[doc_advanced_value_traits_code //[doc_advanced_value_traits_code
#include <boost/intrusive/linking_policy.hpp> #include <boost/intrusive/link_mode.hpp>
#include <boost/intrusive/list.hpp> #include <boost/intrusive/list.hpp>
#include <vector> #include <vector>
@ -46,7 +46,7 @@ struct simple_node_traits
//A templatized value traits for value_1 and value_2 //A templatized value traits for value_1 and value_2
template<class ValueType> template<class ValueType>
struct value_traits struct simple_value_traits
{ {
typedef simple_node_traits node_traits; typedef simple_node_traits node_traits;
typedef node_traits::node_ptr node_ptr; typedef node_traits::node_ptr node_ptr;
@ -54,7 +54,7 @@ struct value_traits
typedef ValueType value_type; typedef ValueType value_type;
typedef ValueType * pointer; typedef ValueType * pointer;
typedef const ValueType * const_pointer; typedef const ValueType * const_pointer;
enum { linking_policy = boost::intrusive::normal_link }; static const boost::intrusive::link_mode_type link_mode = boost::intrusive::normal_link;
static node_ptr to_node_ptr (value_type &value) { return node_ptr(&value); } static node_ptr to_node_ptr (value_type &value) { return node_ptr(&value); }
static const_node_ptr to_node_ptr (const value_type &value) { return const_node_ptr(&value); } static const_node_ptr to_node_ptr (const value_type &value) { return const_node_ptr(&value); }
static pointer to_value_ptr(node_ptr n) { return static_cast<value_type*>(n); } static pointer to_value_ptr(node_ptr n) { return static_cast<value_type*>(n); }
@ -65,8 +65,10 @@ struct value_traits
//[doc_advanced_value_traits_containers //[doc_advanced_value_traits_containers
//Now define two intrusive lists. Both lists will use the same algorithms: //Now define two intrusive lists. Both lists will use the same algorithms:
// circular_list_algorithms<simple_node_traits> // circular_list_algorithms<simple_node_traits>
typedef boost::intrusive::list <value_traits<value_1> > Value1List;
typedef boost::intrusive::list <value_traits<value_2> > Value2List; using namespace boost::intrusive;
typedef list <value_1, value_traits<simple_value_traits<value_1> > > Value1List;
typedef list <value_2, value_traits<simple_value_traits<value_2> > > Value2List;
//] //]
//[doc_advanced_value_traits_test //[doc_advanced_value_traits_test

View File

@ -9,7 +9,7 @@
// See http://www.boost.org/libs/intrusive for documentation. // See http://www.boost.org/libs/intrusive for documentation.
// //
///////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////
#include <boost/intrusive/linking_policy.hpp> #include <boost/intrusive/link_mode.hpp>
#include <boost/intrusive/list.hpp> #include <boost/intrusive/list.hpp>
#include <boost/intrusive/member_value_traits.hpp> #include <boost/intrusive/member_value_traits.hpp>
#include <vector> #include <vector>
@ -57,8 +57,8 @@ typedef member_value_traits
//Now define two intrusive lists. Both lists will use the same algorithms: //Now define two intrusive lists. Both lists will use the same algorithms:
// circular_list_algorithms<simple_node_traits> // circular_list_algorithms<simple_node_traits>
typedef boost::intrusive::list <ValueTraits1> Value1List; typedef list <value_1, value_traits<ValueTraits1> > Value1List;
typedef boost::intrusive::list <ValueTraits2> Value2List; typedef list <value_2, value_traits<ValueTraits2> > Value2List;
//] //]
//[doc_advanced_value_traits2_test //[doc_advanced_value_traits2_test

View File

@ -51,24 +51,21 @@ class Expensive : public set_base_hook<>, public unordered_set_base_hook<>
}; };
// A set and unordered_set that store Expensive objects // A set and unordered_set that store Expensive objects
typedef set<set_base_hook<>::value_traits<Expensive> > Set; typedef set<Expensive> Set;
typedef unordered_set<unordered_set_base_hook<>:: typedef unordered_set<Expensive> UnorderedSet;
value_traits<Expensive> > UnorderedSet;
// Search functions // Search functions
Expensive *get_from_set(const char* key, Set &set) Expensive *get_from_set(const char* key, Set &set_object)
{ {
Set::iterator it = set.find(Expensive(key)); Set::iterator it = set_object.find(Expensive(key));
if( it == set.end() ) return 0; if( it == set_object.end() ) return 0;
return &*it; return &*it;
} }
Expensive *get_from_unordered_set Expensive *get_from_uset(const char* key, UnorderedSet &uset_object)
(const char* key, UnorderedSet &unordered_set)
{ {
UnorderedSet::iterator it = UnorderedSet::iterator it = uset_object.find(Expensive (key));
unordered_set.find(Expensive (key)); if( it == uset_object.end() ) return 0;
if( it == unordered_set.end() ) return 0;
return &*it; return &*it;
} }
//] //]
@ -94,38 +91,35 @@ struct StrExpEqual
}; };
// Optimized search functions // Optimized search functions
Expensive *get_from_set_optimized(const char* key, Set &set) Expensive *get_from_set_optimized(const char* key, Set &set_object)
{ {
Set::iterator it = set.find(key, StrExpComp()); Set::iterator it = set_object.find(key, StrExpComp());
if( it == set.end() ) return 0; if( it == set_object.end() ) return 0;
return &*it; return &*it;
} }
Expensive *get_from_unordered_set_optimized Expensive *get_from_uset_optimized(const char* key, UnorderedSet &uset_object)
(const char* key, UnorderedSet &unordered_set)
{ {
UnorderedSet::iterator it = UnorderedSet::iterator it = uset_object.find(key, StrHasher(), StrExpEqual());
unordered_set.find(key, StrHasher(), StrExpEqual()); if( it == uset_object.end() ) return 0;
if( it == unordered_set.end() ) return 0;
return &*it; return &*it;
} }
//] //]
//[doc_assoc_optimized_code_normal_insert //[doc_assoc_optimized_code_normal_insert
// Insertion functions // Insertion functions
bool insert_to_set(const char* key, Set &set) bool insert_to_set(const char* key, Set &set_object)
{ {
Expensive *pobject = new Expensive(key); Expensive *pobject = new Expensive(key);
bool success = set.insert(*pobject).second; bool success = set_object.insert(*pobject).second;
if(!success) delete pobject; if(!success) delete pobject;
return success; return success;
} }
bool insert_to_unordered_set bool insert_to_uset(const char* key, UnorderedSet &uset_object)
(const char* key, UnorderedSet &unordered_set)
{ {
Expensive *pobject = new Expensive(key); Expensive *pobject = new Expensive(key);
bool success = unordered_set.insert(*pobject).second; bool success = uset_object.insert(*pobject).second;
if(!success) delete pobject; if(!success) delete pobject;
return success; return success;
} }
@ -133,24 +127,20 @@ bool insert_to_unordered_set
//[doc_assoc_optimized_code_optimized_insert //[doc_assoc_optimized_code_optimized_insert
// Optimized insertion functions // Optimized insertion functions
bool insert_to_set_optimized(const char* key, Set &set) bool insert_to_set_optimized(const char* key, Set &set_object)
{ {
Set::insert_commit_data insert_data; Set::insert_commit_data insert_data;
bool success = set.insert_check bool success = set_object.insert_check(key, StrExpComp(), insert_data).second;
(key, StrExpComp(), insert_data).second; if(success) set_object.insert_commit(*new Expensive(key), insert_data);
if(success)
set.insert_commit(*new Expensive(key), insert_data);
return success; return success;
} }
bool insert_to_unordered_set_optimized bool insert_to_uset_optimized(const char* key, UnorderedSet &uset_object)
(const char* key, UnorderedSet &unordered_set)
{ {
UnorderedSet::insert_commit_data insert_data; UnorderedSet::insert_commit_data insert_data;
bool success = unordered_set.insert_check bool success = uset_object.insert_check
(key, StrHasher(), StrExpEqual(), insert_data).second; (key, StrHasher(), StrExpEqual(), insert_data).second;
if(success) if(success) uset_object.insert_commit(*new Expensive(key), insert_data);
unordered_set.insert_commit(*new Expensive(key), insert_data);
return success; return success;
} }
//] //]
@ -159,7 +149,7 @@ int main()
{ {
Set set; Set set;
UnorderedSet::bucket_type buckets[10]; UnorderedSet::bucket_type buckets[10];
UnorderedSet unordered_set(buckets, 10); UnorderedSet unordered_set(UnorderedSet::bucket_traits(buckets, 10));
const char * const expensive_key const char * const expensive_key
= "A long string that avoids small string optimization"; = "A long string that avoids small string optimization";
@ -170,7 +160,7 @@ int main()
return 1; return 1;
} }
if(get_from_unordered_set(expensive_key, unordered_set)){ if(get_from_uset(expensive_key, unordered_set)){
return 1; return 1;
} }
@ -178,7 +168,7 @@ int main()
return 1; return 1;
} }
if(get_from_unordered_set_optimized(expensive_key, unordered_set)){ if(get_from_uset_optimized(expensive_key, unordered_set)){
return 1; return 1;
} }
@ -189,7 +179,7 @@ int main()
return 1; return 1;
} }
if(!get_from_unordered_set(expensive_key, unordered_set)){ if(!get_from_uset(expensive_key, unordered_set)){
return 1; return 1;
} }
@ -197,7 +187,7 @@ int main()
return 1; return 1;
} }
if(!get_from_unordered_set_optimized(expensive_key, unordered_set)){ if(!get_from_uset_optimized(expensive_key, unordered_set)){
return 1; return 1;
} }
@ -208,7 +198,7 @@ int main()
return 1; return 1;
} }
if(!insert_to_unordered_set(expensive_key, unordered_set)){ if(!insert_to_uset(expensive_key, unordered_set)){
return 1; return 1;
} }
@ -228,7 +218,7 @@ int main()
return 1; return 1;
} }
if(!insert_to_unordered_set_optimized(expensive_key, unordered_set)){ if(!insert_to_uset_optimized(expensive_key, unordered_set)){
return 1; return 1;
} }
@ -251,7 +241,7 @@ int main()
return 1; return 1;
} }
if(insert_to_unordered_set(expensive_key, unordered_set)){ if(insert_to_uset(expensive_key, unordered_set)){
return 1; return 1;
} }
@ -259,7 +249,7 @@ int main()
return 1; return 1;
} }
if(insert_to_unordered_set_optimized(expensive_key, unordered_set)){ if(insert_to_uset_optimized(expensive_key, unordered_set)){
return 1; return 1;
} }

View File

@ -15,39 +15,38 @@
using namespace boost::intrusive; using namespace boost::intrusive;
class MyClass : public list_base_hook<tag, auto_unlink> typedef list_base_hook<link_mode<auto_unlink> > auto_unlink_hook;
class MyClass : public auto_unlink_hook
//This hook removes the node in the destructor //This hook removes the node in the destructor
{ {
int int_; int int_;
public: public:
MyClass(int i = 0) : int_(i) {} MyClass(int i = 0) : int_(i) {}
void unlink() { list_base_hook<tag, auto_unlink>::unlink(); } void unlink() { auto_unlink_hook::unlink(); }
bool is_linked() { return list_base_hook<tag, auto_unlink>::is_linked(); } bool is_linked() { return auto_unlink_hook::is_linked(); }
int get() const { return int_; }
}; };
//Define a list that will store MyClass //Define a list that will store values using the base hook
//using the public base hook
//The list can't have constant-time size! //The list can't have constant-time size!
typedef list< list_base_hook<tag, auto_unlink>:: typedef list< MyClass, constant_time_size<false> > List;
value_traits<MyClass>, false > List;
int main() int main()
{ {
//Create the list //Create the list
List list; List l;
{ {
//Create myclass and check it's linked //Create myclass and check it's linked
MyClass myclass; MyClass myclass;
assert(myclass.is_linked() == false); assert(myclass.is_linked() == false);
//Insert the object //Insert the object
list.push_back(myclass); l.push_back(myclass);
//Check that we have inserted the object //Check that we have inserted the object
assert(list.empty() == false); assert(l.empty() == false);
assert(&list.front() == &myclass); assert(&l.front() == &myclass);
assert(myclass.is_linked() == true); assert(myclass.is_linked() == true);
//Now myclass' destructor will unlink it //Now myclass' destructor will unlink it
@ -55,7 +54,7 @@ int main()
} }
//Check auto-unlink has been executed //Check auto-unlink has been executed
assert(list.empty() == true); assert(l.empty() == true);
{ {
//Now test the unlink() function //Now test the unlink() function
@ -65,18 +64,18 @@ int main()
assert(myclass.is_linked() == false); assert(myclass.is_linked() == false);
//Insert the object //Insert the object
list.push_back(myclass); l.push_back(myclass);
//Check that we have inserted the object //Check that we have inserted the object
assert(list.empty() == false); assert(l.empty() == false);
assert(&list.front() == &myclass); assert(&l.front() == &myclass);
assert(myclass.is_linked() == true); assert(myclass.is_linked() == true);
//Now unlink the node //Now unlink the node
myclass.unlink(); myclass.unlink();
//Check auto-unlink has been executed //Check auto-unlink has been executed
assert(list.empty() == true); assert(l.empty() == true);
} }
return 0; return 0;
} }

View File

@ -0,0 +1,83 @@
/////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2007
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/intrusive for documentation.
//
/////////////////////////////////////////////////////////////////////////////
//[doc_bucket_traits
#include <boost/intrusive/unordered_set.hpp>
#include <boost/functional/hash.hpp>
#include <vector>
using namespace boost::intrusive;
//A class to be inserted in an unordered_set
class MyClass : public unordered_set_base_hook<>
{
int int_;
public:
MyClass(int i = 0) : int_(i)
{}
friend bool operator==(const MyClass &l, const MyClass &r)
{ return l.int_ == r.int_; }
friend std::size_t hash_value(const MyClass &v)
{ return boost::hash_value(v.int_); }
};
//Define the base hook option
typedef base_hook< unordered_set_base_hook<> > BaseHookOption;
//Obtain the types of the bucket and the bucket pointer
typedef unordered_bucket<BaseHookOption>::type BucketType;
typedef unordered_bucket_ptr<BaseHookOption>::type BucketPtr;
//The custom bucket traits.
class custom_bucket_traits
{
public:
static const int NumBuckets = 100;
custom_bucket_traits(BucketPtr buckets)
: buckets_(buckets)
{}
//Functions to be implemented by custom bucket traits
BucketPtr bucket_begin() const { return buckets_; }
std::size_t bucket_count() const { return NumBuckets;}
private:
BucketPtr buckets_;
};
//Define the container using the custom bucket traits
typedef unordered_set<MyClass, bucket_traits<custom_bucket_traits> > BucketTraitsUset;
int main()
{
typedef std::vector<MyClass>::iterator VectIt;
std::vector<MyClass> values;
//Fill values
for(int i = 0; i < 100; ++i) values.push_back(MyClass(i));
//Now create the bucket array and the custom bucket traits object
BucketType buckets[custom_bucket_traits::NumBuckets];
custom_bucket_traits btraits(buckets);
//Now create the unordered set
BucketTraitsUset uset(btraits);
//Insert the values in the unordered set
for(VectIt it(values.begin()), itend(values.end()); it != itend; ++it)
uset.insert(*it);
return 0;
}
//]

View File

@ -14,9 +14,10 @@
#include <iostream> #include <iostream>
#include <vector> #include <vector>
using namespace boost::intrusive;
//A class that can be inserted in an intrusive list //A class that can be inserted in an intrusive list
class my_class class my_class : public list_base_hook<>
: public boost::intrusive::list_base_hook<>
{ {
public: public:
friend bool operator==(const my_class &a, const my_class &b) friend bool operator==(const my_class &a, const my_class &b)
@ -28,20 +29,18 @@ class my_class
}; };
//Definition of the intrusive list //Definition of the intrusive list
typedef boost::intrusive::list< my_class::value_traits<my_class> > my_class_list; typedef list<my_class> my_class_list;
//Cloner object function //Cloner object function
class new_cloner struct new_cloner
{ {
public:
my_class *operator()(const my_class &clone_this) my_class *operator()(const my_class &clone_this)
{ return new my_class(clone_this); } { return new my_class(clone_this); }
}; };
//The disposer object function //The disposer object function
class delete_disposer struct delete_disposer
{ {
public:
void operator()(my_class *delete_this) void operator()(my_class *delete_this)
{ delete delete_this; } { delete delete_this; }
}; };
@ -54,9 +53,8 @@ int main()
//Fill all the nodes and insert them in the list //Fill all the nodes and insert them in the list
my_class_list list; my_class_list list;
for(int i = 0; i < MaxElem; ++i){ for(int i = 0; i < MaxElem; ++i) nodes[i].int_ = i;
nodes[i].int_ = i;
}
list.insert(list.end(), nodes.begin(), nodes.end()); list.insert(list.end(), nodes.begin(), nodes.end());
//Now clone "list" using "new" and "delete" object functions //Now clone "list" using "new" and "delete" object functions
@ -64,12 +62,10 @@ int main()
cloned_list.clone_from(list, new_cloner(), delete_disposer()); cloned_list.clone_from(list, new_cloner(), delete_disposer());
//Test that both are equal //Test that both are equal
if(cloned_list != list){ if(cloned_list != list)
std::cout << "Both lists are different" << std::endl; std::cout << "Both lists are different" << std::endl;
} else
else{
std::cout << "Both lists are equal" << std::endl; std::cout << "Both lists are equal" << std::endl;
}
//Don't forget to free the memory from the second list //Don't forget to free the memory from the second list
cloned_list.clear_and_dispose(delete_disposer()); cloned_list.clear_and_dispose(delete_disposer());

View File

@ -12,9 +12,10 @@
//[doc_entity_code //[doc_entity_code
#include <boost/intrusive/list.hpp> #include <boost/intrusive/list.hpp>
using namespace boost::intrusive;
//A class that can be inserted in an intrusive list //A class that can be inserted in an intrusive list
class entity class entity : public list_base_hook<>
: public boost::intrusive::list_base_hook<>
{ {
public: public:
virtual ~entity(); virtual ~entity();
@ -26,25 +27,25 @@ class some_entity : public entity
{/**/}; {/**/};
//Definition of the intrusive list //Definition of the intrusive list
typedef boost::intrusive::list< entity::value_traits<entity> > entity_list; typedef list<entity> entity_list;
//A global list //A global list
entity_list list; entity_list global_list;
//The destructor removes itself from the list //The destructor removes itself from the global list
entity::~entity() entity::~entity()
{ list.erase(entity_list::iterator_to(*this)); } { global_list.erase(entity_list::s_iterator_to(*this)); }
//Function to insert a new "some_entity" in the list //Function to insert a new "some_entity" in the global list
void insert_some_entity() void insert_some_entity()
{ list.push_back (*new some_entity(/*...*/)); } { global_list.push_back (*new some_entity(/*...*/)); }
//Function to clear an entity from the intrusive list //Function to clear an entity from the intrusive global list
void clear_list () void clear_list ()
{ {
// entity's destructor removes itself from the list implicitly // entity's destructor removes itself from the global list implicitly
while (!list.empty()) while (!global_list.empty())
delete &list.front(); delete &global_list.front();
} }
int main() int main()
@ -52,7 +53,7 @@ int main()
//Insert some new entities //Insert some new entities
insert_some_entity(); insert_some_entity();
insert_some_entity(); insert_some_entity();
//list's destructor will free objects //global_list's destructor will free objects
return 0; return 0;
} }

View File

@ -12,9 +12,10 @@
//[doc_erasing_and_disposing //[doc_erasing_and_disposing
#include <boost/intrusive/list.hpp> #include <boost/intrusive/list.hpp>
using namespace boost::intrusive;
//A class that can be inserted in an intrusive list //A class that can be inserted in an intrusive list
class my_class class my_class : public list_base_hook<>
: public boost::intrusive::list_base_hook<>
{ {
public: public:
my_class(int i) my_class(int i)
@ -26,20 +27,18 @@ class my_class
}; };
//Definition of the intrusive list //Definition of the intrusive list
typedef boost::intrusive::list< my_class::value_traits<my_class> > my_class_list; typedef list<my_class> my_class_list;
//The predicate function //The predicate function
class is_even struct is_even
{ {
public:
bool operator()(const my_class &c) const bool operator()(const my_class &c) const
{ return 0 == (c.int_ % 2); } { return 0 == (c.int_ % 2); }
}; };
//The disposer object function //The disposer object function
class delete_disposer struct delete_disposer
{ {
public:
void operator()(my_class *delete_this) void operator()(my_class *delete_this)
{ delete delete_this; } { delete delete_this; }
}; };
@ -53,9 +52,7 @@ int main()
try{ try{
//Insert new objects in the container //Insert new objects in the container
for(int i = 0; i < MaxElem; ++i){ for(int i = 0; i < MaxElem; ++i) list.push_back(*new my_class(i));
list.push_back(*new my_class(i));
}
//Now use remove_and_dispose_if to erase and delete the objects //Now use remove_and_dispose_if to erase and delete the objects
list.remove_and_dispose_if(is_even(), delete_disposer()); list.remove_and_dispose_if(is_even(), delete_disposer());

View File

@ -0,0 +1,129 @@
/////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2007
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/intrusive for documentation.
//
/////////////////////////////////////////////////////////////////////////////
//[doc_external_value_traits
#include <boost/intrusive/list.hpp>
#include <vector>
using namespace boost::intrusive;
//This type is not modifiable so we can't store hooks or custom nodes
typedef int identifier_t;
//This value traits will associate elements from an array of identifiers with
//elements of an array of nodes. The element i of the value array will use the
//node i of the node array:
class external_traits
{
//Non-copyable
external_traits(const external_traits &);
external_traits& operator=(const external_traits &);
public:
typedef list_node_traits<void*> node_traits;
typedef node_traits::node node;
typedef node * node_ptr;
typedef const node * const_node_ptr;
typedef identifier_t value_type;
typedef identifier_t * pointer;
typedef const identifier_t * const_pointer;
static const link_mode_type link_mode = normal_link;
external_traits(pointer ids, std::size_t NumElements)
: ids_(ids), nodes_(NumElements)
{}
///Note: non static functions!
node_ptr to_node_ptr (value_type &value)
{ return &this->nodes_[0] + (&value - this->ids_); }
const_node_ptr to_node_ptr (const value_type &value) const
{ return &this->nodes_[0] + (&value - this->ids_); }
pointer to_value_ptr(node_ptr n)
{ return this->ids_ + (n - &this->nodes_[0]); }
const_pointer to_value_ptr(const_node_ptr n) const
{ return this->ids_ + (n - &this->nodes_[0]); }
private:
pointer ids_;
//This is an array of nodes that is necessary to form the linked list
std::vector<list_node_traits<void*>::node> nodes_;
};
//This is the value traits class that will be stored in the container
//and that will lead to the external traits using the address
//of the container.
struct internal_traits
{
static const bool external_value_traits = true;
typedef external_traits value_traits;
template<class Container>
value_traits &get_value_traits(Container &cont);
template<class Container>
const value_traits &get_value_traits(const Container &cont) const;
};
//The intrusive list that will use external value traits
typedef list<identifier_t, value_traits<internal_traits> > List;
class data_holder
: public List
{
public:
data_holder(identifier_t *ids, std::size_t NumElements)
: List()
, external_traits_(ids, NumElements)
{}
external_traits external_traits_;
};
template<class Container>
internal_traits::value_traits &internal_traits::get_value_traits(Container &cont)
{ return static_cast<data_holder&>(cont).external_traits_; }
template<class Container>
const internal_traits::value_traits &internal_traits::get_value_traits(const Container &cont) const
{ return static_cast<const data_holder&>(cont).external_traits_; }
int main()
{
const int NumElements = 100;
//This is an array of ids that we want to "store"
identifier_t ids [NumElements];
//Initialize id objects, each one with a different number
for(int i = 0; i != NumElements; ++i) ids[i] = i;
//The data holding the list and the external traits
data_holder data(ids, NumElements);
//This list will store ids without modifying identifier_t instances
//Stateful value traits must be explicitly passed in the constructor.
List &my_list = data;
//Insert ids in reverse order in the list
for(identifier_t * it(&ids[0]), *itend(&ids[NumElements]); it != itend; ++it)
my_list.push_front(*it);
//Now test lists
List::const_iterator list_it (my_list.cbegin());
identifier_t *it_val(&ids[NumElements]-1), *it_rbeg_val(&ids[0] -1);
//Test the objects inserted in the base hook list
for(; it_val != it_rbeg_val; --it_val, ++list_it){
if(&*list_it != &*it_val) return 1;
}
return 0;
}
//]

View File

@ -15,7 +15,7 @@
using namespace boost::intrusive; using namespace boost::intrusive;
class MyClass : public list_base_hook<> class MyClass : public list_base_hook<>
{ {
int int_; int int_;
@ -23,62 +23,51 @@ class MyClass : public list_base_hook<>
list_member_hook<> member_hook_; list_member_hook<> member_hook_;
MyClass(int i) : int_(i) {} MyClass(int i) : int_(i) {}
int get() const { return int_; }
}; };
//Define a list that will store MyClass using the base hook //Define a list that will store MyClass using the base hook
typedef list< list_base_hook<>::value_traits<MyClass> > typedef list<MyClass> BaseList;
BaseList;
//Define a list that will store MyClass using the member hook //Define a list that will store MyClass using the member hook
typedef list< list_member_hook<>:: typedef member_hook
value_traits<MyClass, &MyClass::member_hook_> < MyClass, list_member_hook<>, &MyClass::member_hook_> MemberOption;
> MemberList; typedef list<MyClass, MemberOption> MemberList;
int main() int main()
{ {
typedef std::vector<MyClass> Vect; typedef std::vector<MyClass>::iterator VectIt;
typedef Vect::iterator VectIt; typedef std::vector<MyClass>::reverse_iterator VectRit;
typedef Vect::reverse_iterator VectRit;
//Create several MyClass objects, each one //Create several MyClass objects, each one with a different value
//with a different internal number std::vector<MyClass> values;
Vect myclassvector; for(int i = 0; i < 100; ++i) values.push_back(MyClass(i));
for(int i = 0; i < 100; ++i)
myclassvector.push_back(MyClass(i));
BaseList baselist; BaseList baselist;
MemberList memberlist; MemberList memberlist;
//Now insert them in the reverse order //Now insert them in the reverse order in the base hook list
//in the base hook intrusive list for(VectIt it(values.begin()), itend(values.end())
for(VectIt it(myclassvector.begin()), itend(myclassvector.end())
; it != itend ; ++it){ ; it != itend ; ++it){
baselist.push_front(*it); baselist.push_front(*it);
} }
//Now insert them in the same order as in vector in the //Now insert them in the same order as in vector in the member hook list
//member hook intrusive list for(VectIt it(values.begin()), itend(values.end()); it != itend; ++it)
for(VectIt it(myclassvector.begin()), itend(myclassvector.end())
; it != itend; ++it){
memberlist.push_back(*it); memberlist.push_back(*it);
}
//Now test lists //Now test lists
{ {
BaseList::reverse_iterator rbit(baselist.rbegin()), rbitend(baselist.rend()); BaseList::reverse_iterator rbit(baselist.rbegin()), rbitend(baselist.rend());
MemberList::iterator mit(memberlist.begin()), mitend(memberlist.end()); MemberList::iterator mit(memberlist.begin()), mitend(memberlist.end());
VectIt it(myclassvector.begin()), itend(myclassvector.end()); VectIt it(values.begin()), itend(values.end());
//Test the objects inserted in the base hook list //Test the objects inserted in the base hook list
for(; it != itend; ++it, ++rbit){ for(; it != itend; ++it, ++rbit)
if(&*rbit != &*it) return 1; if(&*rbit != &*it) return 1;
}
//Test the objects inserted in the member hook list //Test the objects inserted in the member hook list
for(it = myclassvector.begin(); it != itend; ++it, ++mit){ for(it = values.begin(); it != itend; ++it, ++mit)
if(&*mit != &*it) return 1; if(&*mit != &*it) return 1;
}
} }
return 0; return 0;

View File

@ -15,43 +15,44 @@
#include <boost/functional/hash.hpp> #include <boost/functional/hash.hpp>
#include <vector> #include <vector>
using namespace boost::intrusive;
class intrusive_data class intrusive_data
{ {
int data_id_; int data_id_;
public: public:
int get() const { return data_id_; }
void set(int id) { data_id_ = id; } void set(int id) { data_id_ = id; }
//This class can be inserted in an intrusive list //This class can be inserted in an intrusive list
typedef boost::intrusive:: list_member_hook<> list_hook_;
list_member_hook<> list_member_hook_t;
list_member_hook_t list_hook_;
//This class can be inserted in an intrusive unordered_set //This class can be inserted in an intrusive unordered_set
typedef boost::intrusive:: unordered_set_member_hook<> unordered_set_hook_;
unordered_set_member_hook<> unordered_set_member_hook_t;
unordered_set_member_hook_t unordered_set_hook_;
//Comparison operators //Comparison operators
friend bool operator==(const intrusive_data &a, const intrusive_data &b) friend bool operator==(const intrusive_data &a, const intrusive_data &b)
{ return a.get() == b.get(); } { return a.data_id_ == b.data_id_; }
friend bool operator!=(const intrusive_data &a, const intrusive_data &b) friend bool operator!=(const intrusive_data &a, const intrusive_data &b)
{ return a.get() != b.get(); } { return a.data_id_ != b.data_id_; }
//The hash function
friend std::size_t hash_value(const intrusive_data &i)
{ return boost::hash<int>()(i.data_id_); }
}; };
//The hash function
std::size_t hash_value(const intrusive_data &i)
{ return boost::hash<int>()(i.get()); }
//Definition of the intrusive list that will hold intrusive_data //Definition of the intrusive list that will hold intrusive_data
typedef boost::intrusive::list< intrusive_data::list_member_hook_t:: typedef member_hook<intrusive_data, list_member_hook<>
value_traits<intrusive_data, &intrusive_data::list_hook_> > list_t; , &intrusive_data::list_hook_> MemberListOption;
typedef list<intrusive_data, MemberListOption> list_t;
//Definition of the intrusive unordered_set that will hold intrusive_data //Definition of the intrusive unordered_set that will hold intrusive_data
typedef boost::intrusive::unordered_set< intrusive_data::unordered_set_member_hook_t:: typedef member_hook
value_traits<intrusive_data, &intrusive_data::unordered_set_hook_> > unordered_set_t; < intrusive_data, unordered_set_member_hook<>
, &intrusive_data::unordered_set_hook_> MemberUsetOption;
typedef boost::intrusive::unordered_set
< intrusive_data, MemberUsetOption> unordered_set_t;
int main() int main()
{ {
@ -62,30 +63,32 @@ int main()
//Declare the intrusive containers //Declare the intrusive containers
list_t list; list_t list;
unordered_set_t::bucket_type buckets[MaxElem]; unordered_set_t::bucket_type buckets[MaxElem];
unordered_set_t unordered_set(buckets, MaxElem); unordered_set_t unordered_set
(unordered_set_t::bucket_traits(buckets, MaxElem));
//Initialize all the nodes //Initialize all the nodes
for(int i = 0; i < MaxElem; ++i) for(int i = 0; i < MaxElem; ++i) nodes[i].set(i);
nodes[i].set(i);
//Now insert them in both intrusive containers //Now insert them in both intrusive containers
list.insert(list.end(), nodes.begin(), nodes.end()); list.insert(list.end(), nodes.begin(), nodes.end());
unordered_set.insert(nodes.begin(), nodes.end()); unordered_set.insert(nodes.begin(), nodes.end());
//Now check list::iterator_to //Now check the iterator_to function
//which is an static member function
list_t::iterator list_it(list.begin()); list_t::iterator list_it(list.begin());
for(int i = 0; i < MaxElem; ++i, ++list_it) for(int i = 0; i < MaxElem; ++i, ++list_it)
if(list_t::iterator_to(nodes[i]) != list_it) if(list.iterator_to(nodes[i]) != list_it ||
list_t::s_iterator_to(nodes[i]) != list_it)
return 1; return 1;
//Now check unordered_set::iterator_to (which is a member function) //Now check unordered_set::s_iterator_to (which is a member function)
//and unordered_set::local_current (which is an static member function) //and unordered_set::s_local_iterator_to (which is an static member function)
unordered_set_t::iterator unordered_set_it(unordered_set.begin()); unordered_set_t::iterator unordered_set_it(unordered_set.begin());
for(int i = 0; i < MaxElem; ++i, ++unordered_set_it){ for(int i = 0; i < MaxElem; ++i){
if(unordered_set.iterator_to(nodes[i]) != unordered_set.find(nodes[i])) unordered_set_it = unordered_set.find(nodes[i]);
if(unordered_set.iterator_to(nodes[i]) != unordered_set_it)
return 1; return 1;
if(*unordered_set_t::local_iterator_to(nodes[i]) != *unordered_set.find(nodes[i])) if(*unordered_set.local_iterator_to(nodes[i]) != *unordered_set_it ||
*unordered_set_t::s_local_iterator_to(nodes[i]) != *unordered_set_it )
return 1; return 1;
} }

View File

@ -15,7 +15,7 @@
using namespace boost::intrusive; using namespace boost::intrusive;
class MyClass : public list_base_hook<> //This is a derivation hook class MyClass : public list_base_hook<> //This is a derivation hook
{ {
int int_; int int_;
@ -26,63 +26,49 @@ class MyClass : public list_base_hook<> //This is a derivation hook
MyClass(int i) MyClass(int i)
: int_(i) : int_(i)
{} {}
int get() const
{ return int_; }
}; };
//Define a list that will store MyClass using the public base hook //Define a list that will store MyClass using the public base hook
typedef list< list_base_hook<>::value_traits<MyClass> > BaseList; typedef list<MyClass> BaseList;
//Define a list that will store MyClass using the public member hook //Define a list that will store MyClass using the public member hook
typedef list< list_member_hook<>::value_traits<MyClass, &MyClass::member_hook_> > MemberList; typedef list< MyClass
, member_hook< MyClass, list_member_hook<>, &MyClass::member_hook_>
> MemberList;
int main() int main()
{ {
typedef std::vector<MyClass> Vect; typedef std::vector<MyClass>::iterator VectIt;
typedef Vect::iterator VectIt; typedef std::vector<MyClass>::reverse_iterator VectRit;
typedef Vect::reverse_iterator VectRit;
//Create several MyClass objects, each one //Create several MyClass objects, each one with a different value
//with a different internal number std::vector<MyClass> values;
Vect myclassvector; for(int i = 0; i < 100; ++i) values.push_back(MyClass(i));
for(int i = 0; i < 100; ++i)
myclassvector.push_back(MyClass(i));
BaseList baselist; BaseList baselist;
MemberList memberlist; MemberList memberlist;
//Now insert them in the reverse order //Now insert them in the reverse order in the base hook list
//in the base hook intrusive list for(VectIt it(values.begin()), itend(values.end()); it != itend; ++it)
for(VectIt it(myclassvector.begin()), itend(myclassvector.end())
; it != itend
; ++it){
baselist.push_front(*it); baselist.push_front(*it);
}
//Now insert them in the same order as in vector in the //Now insert them in the same order as in vector in the member hook list
//member hook intrusive list for(VectIt it(values.begin()), itend(values.end()); it != itend; ++it)
for(VectIt it(myclassvector.begin()), itend(myclassvector.end())
; it != itend
; ++it){
memberlist.push_back(*it); memberlist.push_back(*it);
}
//Now test lists //Now test lists
{ {
BaseList::reverse_iterator rbit(baselist.rbegin()), rbitend(baselist.rend()); BaseList::reverse_iterator rbit(baselist.rbegin()), rbitend(baselist.rend());
MemberList::iterator mit(memberlist.begin()), mitend(memberlist.end()); MemberList::iterator mit(memberlist.begin()), mitend(memberlist.end());
VectIt it(myclassvector.begin()), itend(myclassvector.end()); VectIt it(values.begin()), itend(values.end());
//Test the objects inserted in the base hook list //Test the objects inserted in the base hook list
for(; it != itend; ++it, ++rbit){ for(; it != itend; ++it, ++rbit)
if(&*rbit != &*it) return 1; if(&*rbit != &*it) return 1;
}
//Test the objects inserted in the member hook list //Test the objects inserted in the member hook list
for(it = myclassvector.begin(); it != itend; ++it, ++mit){ for(it = values.begin(); it != itend; ++it, ++mit)
if(&*mit != &*it) return 1; if(&*mit != &*it) return 1;
}
} }
return 0; return 0;

View File

@ -9,35 +9,49 @@
// See http://www.boost.org/libs/intrusive for documentation. // See http://www.boost.org/libs/intrusive for documentation.
// //
///////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////
//This is needed to allow concurrent test execution in
//several platforms. The shared memory must be unique
//for each process...
#include <boost/interprocess/detail/os_thread_functions.hpp>
#include <sstream>
const char *get_shared_memory_name()
{
std::stringstream s;
s << "process_" << boost::interprocess::detail::get_current_process_id();
static std::string str = s.str();
return str.c_str();
}
//[doc_offset_ptr_0 //[doc_offset_ptr_0
#include <boost/intrusive/list.hpp> #include <boost/intrusive/list.hpp>
#include <boost/interprocess/offset_ptr.hpp> #include <boost/interprocess/offset_ptr.hpp>
using namespace boost::intrusive;
namespace ip = boost::interprocess;
class shared_memory_data class shared_memory_data
//Declare the hook with an offset_ptr from Boost.Interprocess
//to make this class compatible with shared memory
: public list_base_hook< void_pointer< ip::offset_ptr<void> > >
{ {
int data_id_; int data_id_;
public: public:
int get() const { return data_id_; } int get() const { return data_id_; }
void set(int id) { data_id_ = id; } void set(int id) { data_id_ = id; }
//Declare the hook with an offset_ptr from Boost.Interprocess
//to make this class compatible with shared memory
typedef boost::intrusive::list_member_hook
< boost::intrusive::safe_link
, boost::interprocess::offset_ptr<void> > member_hook_t;
member_hook_t list_hook_;
}; };
//] //]
//[doc_offset_ptr_1 //[doc_offset_ptr_1
#include <boost/interprocess/managed_shared_memory.hpp> #include <boost/interprocess/managed_shared_memory.hpp>
#include <boost/interprocess/containers/vector.hpp> #include <boost/interprocess/containers/vector.hpp>
#include <boost/interprocess/containers/list.hpp>
#include <boost/interprocess/allocators/allocator.hpp> #include <boost/interprocess/allocators/allocator.hpp>
//Definition of the shared memory friendly intrusive list //Definition of the shared memory friendly intrusive list
typedef boost::intrusive::list< shared_memory_data::member_hook_t:: typedef ip::list<shared_memory_data> shm_list_t;
value_traits<shared_memory_data, &shared_memory_data::list_hook_> > shm_list_t;
int main() int main()
{ {
@ -45,45 +59,42 @@ int main()
//nodes and the container itself must be created in shared memory //nodes and the container itself must be created in shared memory
const int MaxElem = 100; const int MaxElem = 100;
const int ShmSize = 50000; const int ShmSize = 50000;
const char *ShmName = "SharedMemoryName"; const char *ShmName = get_shared_memory_name();
{
//Erase all old shared memory
ip::shared_memory_object::remove(ShmName);
ip::managed_shared_memory shm(ip::create_only, ShmName, ShmSize);
using namespace boost::interprocess; //Create all nodes in shared memory using a shared memory vector
//See Boost.Interprocess documentation for more information on this
typedef ip::allocator
< shared_memory_data, ip::managed_shared_memory::segment_manager>
shm_allocator_t;
typedef ip::vector<shared_memory_data, shm_allocator_t> shm_vector_t;
shm_allocator_t shm_alloc(shm.get_segment_manager());
shm_vector_t *pshm_vect =
shm.construct<shm_vector_t>(ip::anonymous_instance)(shm_alloc);
pshm_vect->resize(MaxElem);
//Erase all old shared memory //Initialize all the nodes
shared_memory_object::remove(ShmName); for(int i = 0; i < MaxElem; ++i) (*pshm_vect)[i].set(i);
managed_shared_memory shm(create_only, ShmName, ShmSize);
//Create all nodes in shared memory using a shared memory vector //Now create the shared memory intrusive list
//See Boost.Interprocess documentation for more information on this shm_list_t *plist = shm.construct<shm_list_t>(ip::anonymous_instance)();
typedef allocator< shared_memory_data plist->insert(plist->end(), pshm_vect->begin(), pshm_vect->end());
, managed_shared_memory::segment_manager> shm_allocator_t;
typedef vector<shared_memory_data, shm_allocator_t> shm_vector_t;
shm_allocator_t shm_alloc(shm.get_segment_manager());
shm_vector_t *pshm_vect = shm.construct<shm_vector_t>(anonymous_instance)(shm_alloc);
pshm_vect->resize(MaxElem);
//Initialize all the nodes //Check all the inserted nodes
for(int i = 0; i < MaxElem; ++i){ int checker = 0;
(*pshm_vect)[i].set(i); for( shm_list_t::const_iterator it = plist->begin(), itend(plist->end())
} ; it != itend; ++it, ++checker){
if(it->get() != checker) return false;
//Now create the shared memory intrusive list
shm_list_t *plist = shm.construct<shm_list_t>(anonymous_instance)();
plist->insert(plist->end(), pshm_vect->begin(), pshm_vect->end());
//Check all the inserted nodes
int checker = 0;
for( shm_list_t::const_iterator it = plist->begin(), itend(plist->end())
; it != itend
; ++it, ++checker){
if(it->get() != checker){
return false;
} }
}
//Now delete the list and after that, the nodes //Now delete the list and after that, the nodes
shm.destroy_ptr(plist); shm.destroy_ptr(plist);
shm.destroy_ptr(pshm_vect); shm.destroy_ptr(pshm_vect);
}
ip::shared_memory_object::remove(ShmName);
return 0; return 0;
} }
//] //]

View File

@ -17,7 +17,7 @@
using namespace boost::intrusive; using namespace boost::intrusive;
//This is a base hook //This is a base hook
class MyClass : public set_base_hook<> class MyClass : public set_base_hook<>
{ {
int int_; int int_;
@ -28,69 +28,54 @@ class MyClass : public set_base_hook<>
MyClass(int i) MyClass(int i)
: int_(i) : int_(i)
{} {}
int get() const
{ return int_; }
friend bool operator< (const MyClass &a, const MyClass &b) friend bool operator< (const MyClass &a, const MyClass &b)
{ return a.get() < b.get(); } { return a.int_ < b.int_; }
friend bool operator> (const MyClass &a, const MyClass &b) friend bool operator> (const MyClass &a, const MyClass &b)
{ return a.get() > b.get(); } { return a.int_ > b.int_; }
friend bool operator== (const MyClass &a, const MyClass &b) friend bool operator== (const MyClass &a, const MyClass &b)
{ return a.get() < b.get(); } { return a.int_ < b.int_; }
}; };
//Define an set that will store MyClass //Define an set using the base hook that will store values in reverse order
//in reverse order using the public base hook typedef set< MyClass, compare<std::greater<MyClass> > > BaseSet;
typedef set< set_base_hook<>::value_traits<MyClass>
, std::greater<MyClass> > BaseSet;
//Define an multiset that will store MyClass //Define an multiset using the member hook
//using the public member hook typedef member_hook<MyClass, set_member_hook<>, &MyClass::member_hook_> MemberOption;
typedef multiset< set_member_hook<>:: typedef multiset< MyClass, MemberOption> MemberIMultiset;
value_traits<MyClass, &MyClass::member_hook_>
, std::less<MyClass> > MemberIMultiset;
int main() int main()
{ {
typedef std::vector<MyClass> Vect; typedef std::vector<MyClass>::iterator VectIt;
typedef Vect::iterator VectIt; typedef std::vector<MyClass>::reverse_iterator VectRit;
typedef Vect::reverse_iterator VectRit;
//Create several MyClass objects, each one //Create several MyClass objects, each one with a different value
//with a different internal number std::vector<MyClass> values;
Vect myclassvector; for(int i = 0; i < 100; ++i) values.push_back(MyClass(i));
for(int i = 0; i < 100; ++i)
myclassvector.push_back(MyClass(i));
BaseSet baseset; BaseSet baseset;
MemberIMultiset membermultiset; MemberIMultiset membermultiset;
//Now insert them in the reverse order //Now insert them in the reverse order in the base hook set
//in the base hook intrusive set for(VectIt it(values.begin()), itend(values.end()); it != itend; ++it)
for(VectIt it(myclassvector.begin()), itend(myclassvector.end())
; it != itend; ++it)
baseset.insert(*it); baseset.insert(*it);
//Now insert them in the same order as in vector in the //Now insert them in the same order as in vector in the member hook set
//member hook intrusive set for(VectIt it(values.begin()), itend(values.end()); it != itend; ++it)
for(VectIt it(myclassvector.begin()), itend(myclassvector.end())
; it != itend; ++it)
membermultiset.insert(*it); membermultiset.insert(*it);
//Now test sets //Now test sets
{ {
BaseSet::reverse_iterator rbit(baseset.rbegin()), rbitend(baseset.rend()); BaseSet::reverse_iterator rbit(baseset.rbegin()), rbitend(baseset.rend());
MemberIMultiset::iterator mit(membermultiset.begin()), mitend(membermultiset.end()); MemberIMultiset::iterator mit(membermultiset.begin()), mitend(membermultiset.end());
VectIt it(myclassvector.begin()), itend(myclassvector.end()); VectIt it(values.begin()), itend(values.end());
//Test the objects inserted in the base hook set //Test the objects inserted in the base hook set
for(; it != itend; ++it, ++rbit){ for(; it != itend; ++it, ++rbit)
if(&*rbit != &*it) return 1; if(&*rbit != &*it) return 1;
}
//Test the objects inserted in the member hook set //Test the objects inserted in the member hook set
for(it = myclassvector.begin(); it != itend; ++it, ++mit){ for(it = values.begin(); it != itend; ++it, ++mit)
if(&*mit != &*it) return 1; if(&*mit != &*it) return 1;
}
} }
return 0; return 0;
} }

View File

@ -16,7 +16,7 @@
using namespace boost::intrusive; using namespace boost::intrusive;
//This is a base hook //This is a base hook
class MyClass : public slist_base_hook<> class MyClass : public slist_base_hook<>
{ {
int int_; int int_;
@ -27,45 +27,34 @@ class MyClass : public slist_base_hook<>
MyClass(int i) MyClass(int i)
: int_(i) : int_(i)
{} {}
int get() const
{ return int_; }
}; };
//Define an slist that will store MyClass using the public base hook //Define an slist that will store MyClass using the public base hook
typedef slist< slist_base_hook<>::value_traits<MyClass> > BaseList; typedef slist<MyClass> BaseList;
//Define an slist that will store MyClass using the public member hook //Define an slist that will store MyClass using the public member hook
typedef slist< slist_member_hook<>::value_traits<MyClass, &MyClass::member_hook_> > MemberList; typedef member_hook<MyClass, slist_member_hook<>, &MyClass::member_hook_> MemberOption;
typedef slist<MyClass, MemberOption> MemberList;
int main() int main()
{ {
typedef std::vector<MyClass> Vect; typedef std::vector<MyClass>::iterator VectIt;
typedef Vect::iterator VectIt; typedef std::vector<MyClass>::reverse_iterator VectRit;
typedef Vect::reverse_iterator VectRit;
//Create several MyClass objects, each one //Create several MyClass objects, each one with a different value
//with a different internal number std::vector<MyClass> values;
Vect myclassvector; for(int i = 0; i < 100; ++i) values.push_back(MyClass(i));
for(int i = 0; i < 100; ++i)
myclassvector.push_back(MyClass(i));
BaseList baselist; BaseList baselist;
MemberList memberlist; MemberList memberlist;
//Now insert them in the reverse order //Now insert them in the reverse order in the base hook list
//in the base hook intrusive list for(VectIt it(values.begin()), itend(values.end()); it != itend; ++it)
for(VectIt it(myclassvector.begin()), itend(myclassvector.end())
; it != itend
; ++it){
baselist.push_front(*it); baselist.push_front(*it);
}
//Now insert them in the same order as in vector in the //Now insert them in the same order as in vector in the member hook list
//member hook intrusive list
for(BaseList::iterator it(baselist.begin()), itend(baselist.end()) for(BaseList::iterator it(baselist.begin()), itend(baselist.end())
; it != itend ; it != itend; ++it){
; ++it){
memberlist.push_front(*it); memberlist.push_front(*it);
} }
@ -73,18 +62,16 @@ int main()
{ {
BaseList::iterator bit(baselist.begin()), bitend(baselist.end()); BaseList::iterator bit(baselist.begin()), bitend(baselist.end());
MemberList::iterator mit(memberlist.begin()), mitend(memberlist.end()); MemberList::iterator mit(memberlist.begin()), mitend(memberlist.end());
VectRit rit(myclassvector.rbegin()), ritend(myclassvector.rend()); VectRit rit(values.rbegin()), ritend(values.rend());
VectIt it(myclassvector.begin()), itend(myclassvector.end()); VectIt it(values.begin()), itend(values.end());
//Test the objects inserted in the base hook list //Test the objects inserted in the base hook list
for(; rit != ritend; ++rit, ++bit){ for(; rit != ritend; ++rit, ++bit)
if(&*bit != &*rit) return 1; if(&*bit != &*rit) return 1;
}
//Test the objects inserted in the member hook list //Test the objects inserted in the member hook list
for(; it != itend; ++it, ++mit){ for(; it != itend; ++it, ++mit)
if(&*mit != &*it) return 1; if(&*mit != &*it) return 1;
}
} }
return 0; return 0;

View File

@ -0,0 +1,87 @@
/////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2007
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/intrusive for documentation.
//
/////////////////////////////////////////////////////////////////////////////
//[doc_stateful_value_traits
#include <boost/intrusive/list.hpp>
using namespace boost::intrusive;
//This type is not modifiable so we can't store hooks or custom nodes
typedef int identifier_t;
//This value traits will associate elements from an array of identifiers with
//elements of an array of nodes. The element i of the value array will use the
//node i of the node array:
struct stateful_value_traits
{
typedef list_node_traits<void*> node_traits;
typedef node_traits::node node;
typedef node * node_ptr;
typedef const node * const_node_ptr;
typedef identifier_t value_type;
typedef identifier_t * pointer;
typedef const identifier_t * const_pointer;
static const link_mode_type link_mode = normal_link;
stateful_value_traits(pointer ids, node_ptr node_array)
: ids_(ids), nodes_(node_array)
{}
///Note: non static functions!
node_ptr to_node_ptr (value_type &value)
{ return this->nodes_ + (&value - this->ids_); }
const_node_ptr to_node_ptr (const value_type &value) const
{ return this->nodes_ + (&value - this->ids_); }
pointer to_value_ptr(node_ptr n)
{ return this->ids_ + (n - this->nodes_); }
const_pointer to_value_ptr(const_node_ptr n) const
{ return this->ids_ + (n - this->nodes_); }
private:
pointer ids_;
node_ptr nodes_;
};
int main()
{
const int NumElements = 100;
//This is an array of ids that we want to "store"
identifier_t ids [NumElements];
//This is an array of nodes that is necessary to form the linked list
list_node_traits<void*>::node nodes [NumElements];
//Initialize id objects, each one with a different number
for(int i = 0; i != NumElements; ++i) ids[i] = i;
//Define a list that will "link" identifiers using external nodes
typedef list<identifier_t, value_traits<stateful_value_traits> > List;
//This list will store ids without modifying identifier_t instances
//Stateful value traits must be explicitly passed in the constructor.
List my_list (stateful_value_traits (ids, nodes));
//Insert ids in reverse order in the list
for(identifier_t * it(&ids[0]), *itend(&ids[NumElements]); it != itend; ++it)
my_list.push_front(*it);
//Now test lists
List::const_iterator list_it (my_list.cbegin());
identifier_t *it_val(&ids[NumElements-1]), *it_rbeg_val(&ids[0]-1);
//Test the objects inserted in the base hook list
for(; it_val != it_rbeg_val; --it_val, ++list_it)
if(&*list_it != &*it_val) return 1;
return 0;
}
//]

View File

@ -17,56 +17,43 @@
using namespace boost::intrusive; using namespace boost::intrusive;
//This is a derivation hook class MyClass : public unordered_set_base_hook<>
class MyClass : public unordered_set_base_hook<> { //This is a derivation hook
{
int int_; int int_;
public: public:
//This is a member hook unordered_set_member_hook<> member_hook_; //This is a member hook
unordered_set_member_hook<> member_hook_;
MyClass(int i) MyClass(int i)
: int_(i) : int_(i)
{} {}
int get() const
{ return int_; }
friend bool operator== (const MyClass &a, const MyClass &b) friend bool operator== (const MyClass &a, const MyClass &b)
{ return a.get() == b.get(); } { return a.int_ == b.int_; }
friend bool operator> (const MyClass &a, const MyClass &b) friend std::size_t hash_value(const MyClass &value)
{ return a.get() > b.get(); } { return std::size_t(value.int_); }
}; };
std::size_t hash_value(const MyClass &value) //Define an unordered_set that will store MyClass objects using the base hook
{ return std::size_t(value.get()); } typedef unordered_set<MyClass> BaseSet;
//Define an unordered_set that will store MyClass //Define an unordered_multiset that will store MyClass using the member hook
//in reverse order using the public base hook typedef member_hook<MyClass, unordered_set_member_hook<>, &MyClass::member_hook_>
typedef unordered_set< unordered_set_base_hook<>:: MemberOption;
value_traits<MyClass> > BaseSet; typedef unordered_multiset< MyClass, MemberOption> MemberMultiSet;
//Define an unordered_multiset that will store MyClass
//using the public member hook
typedef unordered_multiset< unordered_set_member_hook<>::
value_traits<MyClass, &MyClass::member_hook_> > MemberMultiSet;
int main() int main()
{ {
typedef std::vector<MyClass> Vect; typedef std::vector<MyClass>::iterator VectIt;
typedef Vect::iterator VectIt; typedef std::vector<MyClass>::reverse_iterator VectRit;
typedef Vect::reverse_iterator VectRit;
//Create a vector with 100 different MyClass objects, //Create a vector with 100 different MyClass objects
//each one with a different internal number std::vector<MyClass> values;
Vect myclassvector; for(int i = 0; i < 100; ++i) values.push_back(MyClass(i));
for(int i = 0; i < 100; ++i)
myclassvector.push_back(MyClass(i));
//Create a copy of the vector //Create a copy of the vector
Vect myclassvector2(myclassvector); std::vector<MyClass> values2(values);
//Create a bucket array for base_set //Create a bucket array for base_set
BaseSet::bucket_type base_buckets[100]; BaseSet::bucket_type base_buckets[100];
@ -74,20 +61,18 @@ int main()
//Create a bucket array for member_multi_set //Create a bucket array for member_multi_set
MemberMultiSet::bucket_type member_buckets[200]; MemberMultiSet::bucket_type member_buckets[200];
//Create a the unordered_set and unordered_multiset, //Create unordered containers taking buckets as arguments
//taking buckets as arguments BaseSet base_set(BaseSet::bucket_traits(base_buckets, 100));
BaseSet base_set(base_buckets, 100); MemberMultiSet member_multi_set
MemberMultiSet member_multi_set(member_buckets, 200); (MemberMultiSet::bucket_traits(member_buckets, 200));
//Now insert myclassvector's elements in the unordered_set //Now insert values's elements in the unordered_set
for(VectIt it(myclassvector.begin()), itend(myclassvector.end()) for(VectIt it(values.begin()), itend(values.end()); it != itend; ++it)
; it != itend; ++it){
base_set.insert(*it); base_set.insert(*it);
}
//Now insert myclassvector's and myclassvector2's elements in the unordered_multiset //Now insert values's and values2's elements in the unordered_multiset
for(VectIt it(myclassvector.begin()), itend(myclassvector.end()), for(VectIt it(values.begin()), itend(values.end()),
it2(myclassvector2.begin()),itend2(myclassvector2.end()) it2(values2.begin()),itend2(values2.end())
; it != itend; ++it, ++it2){ ; it != itend; ++it, ++it2){
member_multi_set.insert(*it); member_multi_set.insert(*it);
member_multi_set.insert(*it2); member_multi_set.insert(*it2);
@ -95,7 +80,7 @@ int main()
//Now find every element //Now find every element
{ {
VectIt it(myclassvector.begin()), itend(myclassvector.end()); VectIt it(values.begin()), itend(values.end());
for(; it != itend; ++it){ for(; it != itend; ++it){
//base_set should contain one element for each key //base_set should contain one element for each key

View File

@ -10,7 +10,7 @@
// //
///////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////
//[doc_value_traits_code_legacy //[doc_value_traits_code_legacy
#include <boost/intrusive/linking_policy.hpp> #include <boost/intrusive/link_mode.hpp>
#include <boost/intrusive/list.hpp> #include <boost/intrusive/list.hpp>
#include <boost/intrusive/slist.hpp> #include <boost/intrusive/slist.hpp>
#include <vector> #include <vector>
@ -30,6 +30,9 @@ struct legacy_value
//Define our own NodeTraits that will configure singly and doubly linked //Define our own NodeTraits that will configure singly and doubly linked
//list algorithms. Note that this node traits is compatible with //list algorithms. Note that this node traits is compatible with
//circular_slist_algorithms and circular_list_algorithms. //circular_slist_algorithms and circular_list_algorithms.
namespace bi = boost::intrusive;
struct legacy_node_traits struct legacy_node_traits
{ {
typedef legacy_value node; typedef legacy_value node;
@ -54,7 +57,7 @@ struct legacy_value_traits
typedef legacy_value value_type; typedef legacy_value value_type;
typedef legacy_value * pointer; typedef legacy_value * pointer;
typedef const legacy_value * const_pointer; typedef const legacy_value * const_pointer;
enum { linking_policy = boost::intrusive::normal_link }; static const bi::link_mode_type link_mode = bi::normal_link;
static node_ptr to_node_ptr (value_type &value) { return node_ptr(&value); } static node_ptr to_node_ptr (value_type &value) { return node_ptr(&value); }
static const_node_ptr to_node_ptr (const value_type &value) { return const_node_ptr(&value); } static const_node_ptr to_node_ptr (const value_type &value) { return const_node_ptr(&value); }
static pointer to_value_ptr(node_ptr n) { return pointer(n); } static pointer to_value_ptr(node_ptr n) { return pointer(n); }
@ -65,8 +68,9 @@ struct legacy_value_traits
//[doc_value_traits_test //[doc_value_traits_test
//Now define an intrusive list and slist that will store legacy_value objects //Now define an intrusive list and slist that will store legacy_value objects
typedef boost::intrusive::list <legacy_value_traits> LegacyAbiList; typedef bi::value_traits<legacy_value_traits> ValueTraitsOption;
typedef boost::intrusive::slist<legacy_value_traits> LegacyAbiSlist; typedef bi::list<legacy_value, ValueTraitsOption> LegacyAbiList;
typedef bi::slist<legacy_value, ValueTraitsOption> LegacyAbiSlist;
template<class List> template<class List>
bool test_list() bool test_list()
@ -87,9 +91,8 @@ bool test_list()
typename Vect::const_iterator it(legacy_vector.begin()), itend(legacy_vector.end()); typename Vect::const_iterator it(legacy_vector.begin()), itend(legacy_vector.end());
//Test the objects inserted in our list //Test the objects inserted in our list
for(; it != itend; ++it, ++bit){ for(; it != itend; ++it, ++bit)
if(&*bit != &*it) return false; if(&*bit != &*it) return false;
}
return true; return true;
} }

View File

@ -15,11 +15,11 @@
using namespace boost::intrusive; using namespace boost::intrusive;
//An abstract class that can be inserted in an intrusive list //An abstract class that can be inserted in an intrusive list
class Window : public list_base_hook<> class Window : public list_base_hook<>
{ {
public: public:
//This is a container those value is an abstract class: you can't do this with std::list. //This is a container those value is an abstract class: you can't do this with std::list.
typedef list< list_base_hook<>::value_traits<Window> > win_list; typedef list<Window> win_list;
//An static intrusive list declaration //An static intrusive list declaration
static win_list all_windows; static win_list all_windows;
@ -27,7 +27,7 @@ class Window : public list_base_hook<>
//Constructor. Includes this window in the list //Constructor. Includes this window in the list
Window() { all_windows.push_back(*this); } Window() { all_windows.push_back(*this); }
//Destructor. Removes this node from the list //Destructor. Removes this node from the list
virtual ~Window() { all_windows.erase(win_list::iterator_to(*this)); } virtual ~Window() { all_windows.erase(win_list::s_iterator_to(*this)); }
//Pure virtual function to be implemented by derived classes //Pure virtual function to be implemented by derived classes
virtual void Paint() = 0; virtual void Paint() = 0;
}; };
@ -71,15 +71,13 @@ class MainWindow : public Window
//Main function //Main function
int main() int main()
{ {
//When each Window class is created, is //When a Window class is created, is automatically registered in the global list
//automatically registered in the global list
MainWindow window; MainWindow window;
//Paint all the windows, sub-windows and so on //Paint all the windows, sub-windows and so on
paint_all_windows(); paint_all_windows();
//All the windows are automatically unregistered //All the windows are automatically unregistered in their destructors.
//in their destructors.
return 0; return 0;
} }
//] //]

View File

@ -11,6 +11,7 @@
///////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////
//Includes for tests //Includes for tests
#include <boost/config.hpp>
#include <list> #include <list>
#include <functional> #include <functional>
#include <iostream> #include <iostream>
@ -26,11 +27,8 @@ const int NumElements = 100000;
using namespace boost::intrusive; using namespace boost::intrusive;
template<bool BigSize> template<bool BigSize> struct filler { int dummy[10]; };
struct filler { int dummy[10]; }; template <> struct filler<false> {};
template <>
struct filler<false> {};
template<bool BigSize> //The object for non-intrusive containers template<bool BigSize> //The object for non-intrusive containers
struct test_class : private filler<BigSize> struct test_class : private filler<BigSize>
@ -42,8 +40,9 @@ struct test_class : private filler<BigSize>
friend bool operator >(const test_class &l, const test_class &r) { return l.i_ > r.i_; } friend bool operator >(const test_class &l, const test_class &r) { return l.i_ > r.i_; }
}; };
template <bool BigSize, linking_policy Policy> //The object for intrusive containers template <bool BigSize, link_mode_type LinkMode>
struct itest_class : public list_base_hook<tag, Policy>, public test_class<BigSize> struct itest_class //The object for intrusive containers
: public list_base_hook<link_mode<LinkMode> >, public test_class<BigSize>
{ {
itest_class() {} itest_class() {}
itest_class(int i) : test_class<BigSize>(i) {} itest_class(int i) : test_class<BigSize>(i) {}
@ -60,11 +59,10 @@ struct func_ptr_adaptor : public FuncObj
}; };
//] //]
template <bool BigSize, linking_policy Policy> template <bool BigSize, link_mode_type LinkMode>
struct get_ilist //Helps to define an intrusive list from a policy struct get_ilist //Helps to define an intrusive list from a policy
{ {
typedef list_base_hook<tag, Policy> hook; typedef list<itest_class<BigSize, LinkMode>, constant_time_size<false> > type;
typedef list<typename hook::template value_traits<itest_class<BigSize, Policy> >, false> type;
}; };
template <bool BigSize> //Helps to define an std list template <bool BigSize> //Helps to define an std list
@ -73,17 +71,16 @@ struct get_list { typedef std::list<test_class<BigSize> > type; };
template <bool BigSize> //Helps to define an std pointer list template <bool BigSize> //Helps to define an std pointer list
struct get_ptrlist { typedef std::list<test_class<BigSize>*> type; }; struct get_ptrlist { typedef std::list<test_class<BigSize>*> type; };
//////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////
// //
// PUSH_BACK // PUSH_BACK
// //
//////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////
template <bool BigSize, linking_policy Policy> template <bool BigSize, link_mode_type LinkMode>
void test_intrusive_list_push_back() void test_intrusive_list_push_back()
{ {
typedef typename get_ilist<BigSize, Policy>::type ilist; typedef typename get_ilist<BigSize, LinkMode>::type ilist;
ptime tini = microsec_clock::universal_time(); ptime tini = microsec_clock::universal_time();
for(int i = 0; i < NumIter; ++i){ for(int i = 0; i < NumIter; ++i){
//First create the elements and insert them in the intrusive list //First create the elements and insert them in the intrusive list
@ -93,11 +90,12 @@ void test_intrusive_list_push_back()
for(int i = 0; i < NumElements; ++i) for(int i = 0; i < NumElements; ++i)
l.push_back(objects[i]); l.push_back(objects[i]);
//Elements are unlinked in ilist's destructor //Elements are unlinked in ilist's destructor
//Elements are disposed in vector's destructor //Elements are destroyed in vector's destructor
//] //]
} }
ptime tend = microsec_clock::universal_time(); ptime tend = microsec_clock::universal_time();
std::cout << "usecs/iteration: " << (tend-tini).total_microseconds()/NumIter << std::endl; std::cout << "link_mode: " << LinkMode << ", usecs/iteration: "
<< (tend-tini).total_microseconds()/NumIter << std::endl;
} }
template <bool BigSize> template <bool BigSize>
@ -111,11 +109,12 @@ void test_std_list_push_back()
stdlist l; stdlist l;
for(int i = 0; i < NumElements; ++i) for(int i = 0; i < NumElements; ++i)
l.push_back(typename stdlist::value_type(i)); l.push_back(typename stdlist::value_type(i));
//Elements unlinked and disposed in stdlist's destructor //Elements unlinked and destroyed in stdlist's destructor
//] //]
} }
ptime tend = microsec_clock::universal_time(); ptime tend = microsec_clock::universal_time();
std::cout << "usecs/iteration: " << (tend-tini).total_microseconds()/NumIter << std::endl; std::cout << "std::list usecs/iteration: "
<< (tend-tini).total_microseconds()/NumIter << std::endl;
} }
template <bool BigSize> template <bool BigSize>
@ -132,12 +131,13 @@ void test_compact_std_ptrlist_push_back()
stdptrlist l; stdptrlist l;
for(int i = 0; i < NumElements; ++i) for(int i = 0; i < NumElements; ++i)
l.push_back(&objects[i]); l.push_back(&objects[i]);
//Pointers to elements unlinked and disposed in stdptrlist's destructor //Pointers to elements unlinked and destroyed in stdptrlist's destructor
//Elements disposed in vector's destructor //Elements destroyed in vector's destructor
//] //]
} }
ptime tend = microsec_clock::universal_time(); ptime tend = microsec_clock::universal_time();
std::cout << "usecs/iteration: " << (tend-tini).total_microseconds()/NumIter << std::endl; std::cout << "compact std::list usecs/iteration: "
<< (tend-tini).total_microseconds()/NumIter << std::endl;
} }
template <bool BigSize> template <bool BigSize>
@ -155,12 +155,13 @@ void test_disperse_std_ptrlist_push_back()
objects.push_back(typename stdlist::value_type(i)); objects.push_back(typename stdlist::value_type(i));
l.push_back(&objects.back()); l.push_back(&objects.back());
} }
//Pointers to elements unlinked and disposed in stdptrlist's destructor //Pointers to elements unlinked and destroyed in stdptrlist's destructor
//Elements unlinked and disposed in stdlist's destructor //Elements unlinked and destroyed in stdlist's destructor
//] //]
} }
ptime tend = microsec_clock::universal_time(); ptime tend = microsec_clock::universal_time();
std::cout << "usecs/iteration: " << (tend-tini).total_microseconds()/NumIter << std::endl; std::cout << "disperse std::list usecs/iteration: "
<< (tend-tini).total_microseconds()/NumIter << std::endl;
} }
//////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////
@ -170,10 +171,10 @@ void test_disperse_std_ptrlist_push_back()
//////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////
//[perf_list_reverse //[perf_list_reverse
template <bool BigSize, linking_policy Policy> template <bool BigSize, link_mode_type LinkMode>
void test_intrusive_list_reverse() void test_intrusive_list_reverse()
{ {
typedef typename get_ilist<BigSize, Policy>::type ilist; typedef typename get_ilist<BigSize, LinkMode>::type ilist;
//First create the elements //First create the elements
std::vector<typename ilist::value_type> objects(NumElements); std::vector<typename ilist::value_type> objects(NumElements);
@ -186,7 +187,8 @@ void test_intrusive_list_reverse()
l.reverse(); l.reverse();
} }
ptime tend = microsec_clock::universal_time(); ptime tend = microsec_clock::universal_time();
std::cout << "usecs/iteration: " << (tend-tini).total_microseconds()/NumIter << std::endl; std::cout << "link_mode: " << LinkMode << ", usecs/iteration: "
<< (tend-tini).total_microseconds()/NumIter << std::endl;
} }
template <bool BigSize> template <bool BigSize>
@ -205,7 +207,8 @@ void test_std_list_reverse()
l.reverse(); l.reverse();
} }
ptime tend = microsec_clock::universal_time(); ptime tend = microsec_clock::universal_time();
std::cout << "usecs/iteration: " << (tend-tini).total_microseconds()/NumIter << std::endl; std::cout << "std::list usecs/iteration: "
<< (tend-tini).total_microseconds()/NumIter << std::endl;
} }
template <bool BigSize> template <bool BigSize>
@ -228,7 +231,8 @@ void test_compact_std_ptrlist_reverse()
l.reverse(); l.reverse();
} }
ptime tend = microsec_clock::universal_time(); ptime tend = microsec_clock::universal_time();
std::cout << "usecs/iteration: " << (tend-tini).total_microseconds()/NumIter << std::endl; std::cout << "compact std::list usecs/iteration: "
<< (tend-tini).total_microseconds()/NumIter << std::endl;
} }
template <bool BigSize> template <bool BigSize>
@ -252,7 +256,8 @@ void test_disperse_std_ptrlist_reverse()
l.reverse(); l.reverse();
} }
ptime tend = microsec_clock::universal_time(); ptime tend = microsec_clock::universal_time();
std::cout << "usecs/iteration: " << (tend-tini).total_microseconds()/NumIter << std::endl; std::cout << "disperse std::list usecs/iteration: "
<< (tend-tini).total_microseconds()/NumIter << std::endl;
} }
//] //]
@ -263,10 +268,10 @@ void test_disperse_std_ptrlist_reverse()
//////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////
//[perf_list_sort //[perf_list_sort
template <bool BigSize, linking_policy Policy> template <bool BigSize, link_mode_type LinkMode>
void test_intrusive_list_sort() void test_intrusive_list_sort()
{ {
typedef typename get_ilist<BigSize, Policy>::type ilist; typedef typename get_ilist<BigSize, LinkMode>::type ilist;
//First create the elements //First create the elements
std::vector<typename ilist::value_type> objects(NumElements); std::vector<typename ilist::value_type> objects(NumElements);
@ -287,7 +292,8 @@ void test_intrusive_list_sort()
} }
} }
ptime tend = microsec_clock::universal_time(); ptime tend = microsec_clock::universal_time();
std::cout << "usecs/iteration: " << (tend-tini).total_microseconds()/NumIter << std::endl; std::cout << "link_mode: " << LinkMode << ", usecs/iteration: "
<< (tend-tini).total_microseconds()/NumIter << std::endl;
} }
template <bool BigSize> template <bool BigSize>
@ -311,7 +317,8 @@ void test_std_list_sort()
} }
} }
ptime tend = microsec_clock::universal_time(); ptime tend = microsec_clock::universal_time();
std::cout << "usecs/iteration: " << (tend-tini).total_microseconds()/NumIter << std::endl; std::cout << "std::list usecs/iteration: "
<< (tend-tini).total_microseconds()/NumIter << std::endl;
} }
template <bool BigSize> template <bool BigSize>
@ -340,7 +347,8 @@ void test_compact_std_ptrlist_sort()
} }
} }
ptime tend = microsec_clock::universal_time(); ptime tend = microsec_clock::universal_time();
std::cout << "usecs/iteration: " << (tend-tini).total_microseconds()/NumIter << std::endl; std::cout << "compact std::list usecs/iteration: "
<< (tend-tini).total_microseconds()/NumIter << std::endl;
} }
template <bool BigSize> template <bool BigSize>
@ -368,7 +376,8 @@ void test_disperse_std_ptrlist_sort()
} }
} }
ptime tend = microsec_clock::universal_time(); ptime tend = microsec_clock::universal_time();
std::cout << "usecs/iteration: " << (tend-tini).total_microseconds()/NumIter << std::endl; std::cout << "disperse std::list usecs/iteration: "
<< (tend-tini).total_microseconds()/NumIter << std::endl;
} }
//] //]
@ -378,10 +387,10 @@ void test_disperse_std_ptrlist_sort()
// //
//////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////
//[perf_list_write_access //[perf_list_write_access
template <bool BigSize, linking_policy Policy> template <bool BigSize, link_mode_type LinkMode>
void test_intrusive_list_write_access() void test_intrusive_list_write_access()
{ {
typedef typename get_ilist<BigSize, Policy>::type ilist; typedef typename get_ilist<BigSize, LinkMode>::type ilist;
//First create the elements //First create the elements
std::vector<typename ilist::value_type> objects(NumElements); std::vector<typename ilist::value_type> objects(NumElements);
@ -401,7 +410,8 @@ void test_intrusive_list_write_access()
} }
} }
ptime tend = microsec_clock::universal_time(); ptime tend = microsec_clock::universal_time();
std::cout << "usecs/iteration: " << (tend-tini).total_microseconds()/NumIter << std::endl; std::cout << "link_mode: " << LinkMode << ", usecs/iteration: "
<< (tend-tini).total_microseconds()/NumIter << std::endl;
} }
template <bool BigSize> template <bool BigSize>
@ -423,7 +433,8 @@ void test_std_list_write_access()
} }
} }
ptime tend = microsec_clock::universal_time(); ptime tend = microsec_clock::universal_time();
std::cout << "usecs/iteration: " << (tend-tini).total_microseconds()/NumIter << std::endl; std::cout << "std::list usecs/iteration: "
<< (tend-tini).total_microseconds()/NumIter << std::endl;
} }
template <bool BigSize> template <bool BigSize>
@ -452,7 +463,8 @@ void test_compact_std_ptrlist_write_access()
} }
} }
ptime tend = microsec_clock::universal_time(); ptime tend = microsec_clock::universal_time();
std::cout << "usecs/iteration: " << (tend-tini).total_microseconds()/NumIter << std::endl; std::cout << "compact std::list usecs/iteration: "
<< (tend-tini).total_microseconds()/NumIter << std::endl;
} }
template <bool BigSize> template <bool BigSize>
@ -479,7 +491,8 @@ void test_disperse_std_ptrlist_write_access()
} }
} }
ptime tend = microsec_clock::universal_time(); ptime tend = microsec_clock::universal_time();
std::cout << "usecs/iteration: " << (tend-tini).total_microseconds()/NumIter << std::endl; std::cout << "disperse std::list usecs/iteration: "
<< (tend-tini).total_microseconds()/NumIter << std::endl;
} }
//] //]
@ -491,7 +504,7 @@ void test_disperse_std_ptrlist_write_access()
template<bool BigSize> template<bool BigSize>
void do_all_tests() void do_all_tests()
{ {
std::cout << "Testing push back() with BigSize:" << BigSize << std::endl; std::cout << "\n\nTesting push back() with BigSize:" << BigSize << std::endl;
test_intrusive_list_push_back<BigSize, normal_link>(); test_intrusive_list_push_back<BigSize, normal_link>();
test_intrusive_list_push_back<BigSize, safe_link>(); test_intrusive_list_push_back<BigSize, safe_link>();
test_intrusive_list_push_back<BigSize, auto_unlink>(); test_intrusive_list_push_back<BigSize, auto_unlink>();
@ -499,7 +512,7 @@ void do_all_tests()
test_compact_std_ptrlist_push_back<BigSize>(); test_compact_std_ptrlist_push_back<BigSize>();
test_disperse_std_ptrlist_push_back<BigSize>(); test_disperse_std_ptrlist_push_back<BigSize>();
//reverse //reverse
std::cout << "Testing reverse() with BigSize:" << BigSize << std::endl; std::cout << "\n\nTesting reverse() with BigSize:" << BigSize << std::endl;
test_intrusive_list_reverse<BigSize, normal_link>(); test_intrusive_list_reverse<BigSize, normal_link>();
test_intrusive_list_reverse<BigSize, safe_link>(); test_intrusive_list_reverse<BigSize, safe_link>();
test_intrusive_list_reverse<BigSize, auto_unlink>(); test_intrusive_list_reverse<BigSize, auto_unlink>();
@ -507,7 +520,7 @@ void do_all_tests()
test_compact_std_ptrlist_reverse<BigSize>(); test_compact_std_ptrlist_reverse<BigSize>();
test_disperse_std_ptrlist_reverse<BigSize>(); test_disperse_std_ptrlist_reverse<BigSize>();
//sort //sort
std::cout << "Testing sort() with BigSize:" << BigSize << std::endl; std::cout << "\n\nTesting sort() with BigSize:" << BigSize << std::endl;
test_intrusive_list_sort<BigSize, normal_link>(); test_intrusive_list_sort<BigSize, normal_link>();
test_intrusive_list_sort<BigSize, safe_link>(); test_intrusive_list_sort<BigSize, safe_link>();
test_intrusive_list_sort<BigSize, auto_unlink>(); test_intrusive_list_sort<BigSize, auto_unlink>();
@ -515,7 +528,7 @@ void do_all_tests()
test_compact_std_ptrlist_sort<BigSize>(); test_compact_std_ptrlist_sort<BigSize>();
test_disperse_std_ptrlist_sort<BigSize>(); test_disperse_std_ptrlist_sort<BigSize>();
//write_access //write_access
std::cout << "Testing write_access() with BigSize:" << BigSize << std::endl; std::cout << "\n\nTesting write_access() with BigSize:" << BigSize << std::endl;
test_intrusive_list_write_access<BigSize, normal_link>(); test_intrusive_list_write_access<BigSize, normal_link>();
test_intrusive_list_write_access<BigSize, safe_link>(); test_intrusive_list_write_access<BigSize, safe_link>();
test_intrusive_list_write_access<BigSize, auto_unlink>(); test_intrusive_list_write_access<BigSize, auto_unlink>();

View File

@ -0,0 +1,127 @@
/////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2007
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/intrusive for documentation.
//
/////////////////////////////////////////////////////////////////////////////
#include <boost/intrusive/unordered_set.hpp>
#include <boost/intrusive/detail/mpl.hpp>
#include <boost/functional/hash.hpp>
#include <vector>
using namespace boost::intrusive;
class MyClass : public unordered_set_base_hook<>
{
int int_;
public:
MyClass(int i = 0) : int_(i)
{}
unordered_set_member_hook<> member_hook_;
friend bool operator==(const MyClass &l, const MyClass &r)
{ return l.int_ == r.int_; }
friend std::size_t hash_value(const MyClass &v)
{ return boost::hash_value(v.int_); }
};
struct uset_value_traits
{
typedef slist_node_traits<void*> node_traits;
typedef node_traits::node_ptr node_ptr;
typedef node_traits::const_node_ptr const_node_ptr;
typedef MyClass value_type;
typedef MyClass * pointer;
typedef const MyClass * const_pointer;
static const link_mode_type link_mode = normal_link;
static node_ptr to_node_ptr (value_type &value)
{ return node_ptr(&value); }
static const_node_ptr to_node_ptr (const value_type &value)
{ return const_node_ptr(&value); }
static pointer to_value_ptr(node_ptr n)
{ return static_cast<value_type*>(n); }
static const_pointer to_value_ptr(const_node_ptr n)
{ return static_cast<const value_type*>(n); }
};
//Base
typedef base_hook< unordered_set_base_hook<> > BaseHook;
typedef unordered_bucket<BaseHook>::type BaseBucketType;
typedef unordered_set<MyClass, BaseHook> BaseUset;
//Member
typedef member_hook
< MyClass, unordered_set_member_hook<>
, &MyClass::member_hook_ > MemberHook;
typedef unordered_bucket<MemberHook>::type MemberBucketType;
typedef unordered_set<MyClass, MemberHook> MemberUset;
//Explicit
typedef value_traits< uset_value_traits > Traits;
typedef unordered_bucket<Traits>::type TraitsBucketType;
typedef unordered_set<MyClass, Traits> TraitsUset;
struct uset_bucket_traits
{
//Power of two bucket length
static const std::size_t NumBuckets = 128;
uset_bucket_traits(BaseBucketType *buckets)
: buckets_(buckets)
{}
uset_bucket_traits(const uset_bucket_traits &other)
: buckets_(other.buckets_)
{}
BaseBucketType * bucket_begin() const
{ return buckets_; }
std::size_t bucket_count() const
{ return NumBuckets; }
BaseBucketType *buckets_;
};
typedef unordered_set
<MyClass, bucket_traits<uset_bucket_traits>, power_2_buckets<true> >
BucketTraitsUset;
int main()
{
if(!detail::is_same<BaseUset::bucket_type, BaseBucketType>::value)
return 1;
if(!detail::is_same<MemberUset::bucket_type, MemberBucketType>::value)
return 1;
if(!detail::is_same<TraitsUset::bucket_type, TraitsBucketType>::value)
return 1;
if(!detail::is_same<BaseBucketType, MemberBucketType>::value)
return 1;
if(!detail::is_same<BaseBucketType, TraitsBucketType>::value)
return 1;
typedef std::vector<MyClass>::iterator VectIt;
typedef std::vector<MyClass>::reverse_iterator VectRit;
std::vector<MyClass> values;
for(int i = 0; i < 100; ++i) values.push_back(MyClass(i));
BaseBucketType buckets[uset_bucket_traits::NumBuckets];
uset_bucket_traits btraits(buckets);
BucketTraitsUset uset(btraits);
for(VectIt it(values.begin()), itend(values.end()); it != itend; ++it)
uset.insert(*it);
for( VectRit it(values.rbegin()), itend(values.rend()); it != itend; ++it){
if(uset.find(*it) == uset.cend()) return 1;
}
return 0;
}

View File

@ -0,0 +1,97 @@
/////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2007
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/intrusive for documentation.
//
/////////////////////////////////////////////////////////////////////////////
#include <boost/intrusive/list.hpp>
#include <boost/intrusive/slist.hpp>
#include <boost/intrusive/set.hpp>
#include <boost/intrusive/unordered_set.hpp>
#include "smart_ptr.hpp"
#include <vector>
using namespace boost::intrusive;
class MyClass
: public list_base_hook
< void_pointer<smart_ptr<void> >, link_mode<normal_link> >
, public slist_base_hook
< void_pointer<smart_ptr<void> >, link_mode<normal_link> >
, public set_base_hook
< void_pointer<smart_ptr<void> >, link_mode<normal_link> >
, public unordered_set_base_hook
< void_pointer<smart_ptr<void> >, link_mode<normal_link> >
{
int int_;
public:
MyClass(int i)
: int_(i)
{}
friend bool operator<(const MyClass &l, const MyClass &r)
{ return l.int_ < r.int_; }
friend bool operator==(const MyClass &l, const MyClass &r)
{ return l.int_ == r.int_; }
friend std::size_t hash_value(const MyClass &v)
{ return boost::hash_value(v.int_); }
};
//Define a list that will store MyClass using the public base hook
typedef list<MyClass> List;
typedef slist<MyClass> Slist;
typedef set<MyClass> Set;
typedef unordered_set<MyClass> USet;
int main()
{
typedef std::vector<MyClass>::iterator VectIt;
typedef std::vector<MyClass>::reverse_iterator VectRit;
//Create several MyClass objects, each one with a different value
std::vector<MyClass> values;
for(int i = 0; i < 100; ++i) values.push_back(MyClass(i));
USet::bucket_type buckets[100];
List my_list;
Slist my_slist;
Set my_set;
USet my_uset(USet::bucket_traits(buckets, 100));
//Now insert them in the reverse order
//in the base hook intrusive list
for(VectIt it(values.begin()), itend(values.end()); it != itend; ++it){
my_list.push_front(*it);
my_slist.push_front(*it);
my_set.insert(*it);
my_uset.insert(*it);
}
//Now test lists
{
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());
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){
if(&*list_it != &*vect_it) return 1;
if(&*slist_it != &*vect_it) return 1;
if(&*set_rit != &*vect_it) return 1;
if(my_uset.find(*set_rit) == my_uset.cend()) return 1;
}
}
return 0;
}

View File

@ -0,0 +1,240 @@
/////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2007
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/intrusive for documentation.
//
/////////////////////////////////////////////////////////////////////////////
#include <boost/intrusive/list.hpp>
#include <boost/intrusive/slist.hpp>
#include <boost/intrusive/rbtree.hpp>
#include <boost/intrusive/hashtable.hpp>
#include <boost/pointer_to_other.hpp>
#include <functional>
#include <vector>
using namespace boost::intrusive;
class MyClass
{
public:
int int_;
MyClass(int i = 0)
: int_(i)
{}
friend bool operator > (const MyClass &l, const MyClass &r)
{ return l.int_ > r.int_; }
friend bool operator == (const MyClass &l, const MyClass &r)
{ return l.int_ == r.int_; }
friend std::size_t hash_value(const MyClass &v)
{ return boost::hash_value(v.int_); }
};
const int NumElements = 100;
template<class NodeTraits>
struct external_traits
{
typedef NodeTraits node_traits;
typedef typename node_traits::node node;
typedef typename node_traits::node_ptr node_ptr;
typedef typename node_traits::const_node_ptr const_node_ptr;
typedef MyClass value_type;
typedef typename boost::pointer_to_other
<node_ptr, MyClass>::type pointer;
typedef typename boost::pointer_to_other
<node_ptr, const MyClass>::type const_pointer;
static const link_mode_type link_mode = normal_link;
external_traits(pointer values, std::size_t NumElem)
: values_(values), node_array_(NumElem)
{}
node_ptr to_node_ptr (value_type &value)
{ return (&node_array_[0]) + (&value - values_); }
const_node_ptr to_node_ptr (const value_type &value) const
{ return &node_array_[0] + (&value - values_); }
pointer to_value_ptr(node_ptr n)
{ return values_ + (n - &node_array_[0]); }
const_pointer to_value_ptr(const_node_ptr n) const
{ return values_ + (n - &node_array_[0]); }
pointer values_;
std::vector<node> node_array_;
};
template<class NodeTraits>
struct value_traits_proxy;
template<class T>
struct traits_holder
: public T
{};
typedef value_traits_proxy<list_node_traits<void*> > list_value_traits_proxy;
typedef value_traits_proxy<slist_node_traits<void*> > slist_value_traits_proxy;
typedef value_traits_proxy<rbtree_node_traits<void*> > rbtree_value_traits_proxy;
typedef value_traits_proxy<traits_holder<slist_node_traits<void*> > > hash_value_traits_proxy;
struct uset_bucket_traits
{
private:
typedef unordered_bucket<value_traits<external_traits
<traits_holder<slist_node_traits<void*> > > > >::type bucket_type;
//Non-copyable
uset_bucket_traits(const uset_bucket_traits &other);
uset_bucket_traits & operator=(const uset_bucket_traits &other);
public:
static const std::size_t NumBuckets = 100;
uset_bucket_traits(){}
bucket_type * bucket_begin() const
{ return buckets_; }
std::size_t bucket_count() const
{ return NumBuckets; }
mutable bucket_type buckets_[NumBuckets];
};
struct bucket_traits_proxy
{
static const bool external_bucket_traits = true;
typedef uset_bucket_traits bucket_traits;
template<class Container>
bucket_traits &get_bucket_traits(Container &cont);
template<class Container>
const bucket_traits &get_bucket_traits(const Container &cont) const;
};
//Define a list that will store MyClass using the external hook
typedef list<MyClass, value_traits<list_value_traits_proxy> > List;
//Define a slist that will store MyClass using the external hook
typedef slist<MyClass, value_traits<slist_value_traits_proxy> > Slist;
//Define a rbtree that will store MyClass using the external hook
typedef rbtree< MyClass
, value_traits<rbtree_value_traits_proxy>
, compare<std::greater<MyClass> > > Rbtree;
//Define a hashtable that will store MyClass using the external hook
typedef hashtable< MyClass
, value_traits<hash_value_traits_proxy>
, bucket_traits<bucket_traits_proxy>
> Hash;
template<class NodeTraits>
struct value_traits_proxy
{
static const bool external_value_traits = true;
typedef external_traits<NodeTraits> value_traits;
template<class Container>
const value_traits &get_value_traits(const Container &cont) const;
template<class Container>
value_traits &get_value_traits(Container &cont);
};
struct ContainerHolder
: public uset_bucket_traits
, public List
, public external_traits<list_node_traits<void*> >
, public Slist
, public external_traits<slist_node_traits<void*> >
, public Rbtree
, public external_traits<rbtree_node_traits<void*> >
, public Hash
, public external_traits<traits_holder<slist_node_traits<void*> > >
{
static const std::size_t NumBucket = 100;
ContainerHolder(MyClass *values, std::size_t num_elem)
: uset_bucket_traits()
, List()
, external_traits<list_node_traits<void*> >(values, num_elem)
, Slist()
, external_traits<slist_node_traits<void*> >(values, num_elem)
, Rbtree()
, external_traits<rbtree_node_traits<void*> >(values, num_elem)
, Hash(Hash::bucket_traits())
, external_traits<traits_holder<slist_node_traits<void*> > >(values, num_elem)
{}
};
template<class NodeTraits>
template<class Container>
typename value_traits_proxy<NodeTraits>::value_traits &
value_traits_proxy<NodeTraits>::get_value_traits(Container &cont)
{ return static_cast<value_traits&>(static_cast<ContainerHolder&>(cont)); }
template<class NodeTraits>
template<class Container>
const typename value_traits_proxy<NodeTraits>::value_traits &
value_traits_proxy<NodeTraits>::get_value_traits(const Container &cont) const
{ return static_cast<const value_traits&>(static_cast<const ContainerHolder&>(cont)); }
template<class Container>
typename bucket_traits_proxy::bucket_traits &
bucket_traits_proxy::get_bucket_traits(Container &cont)
{ return static_cast<bucket_traits&>(static_cast<ContainerHolder&>(cont)); }
template<class Container>
const typename bucket_traits_proxy::bucket_traits &
bucket_traits_proxy::get_bucket_traits(const Container &cont) const
{ return static_cast<const bucket_traits&>(static_cast<const ContainerHolder&>(cont)); }
int main()
{
MyClass values [NumElements];
//Create several MyClass objects, each one with a different value
for(int i = 0; i < NumElements; ++i)
values[i].int_ = i;
ContainerHolder cont_holder(values, NumElements);
List &my_list = static_cast<List &> (cont_holder);
Slist &my_slist = static_cast<Slist &> (cont_holder);
Rbtree &my_rbtree = static_cast<Rbtree &> (cont_holder);
Hash &my_hash = static_cast<Hash &> (cont_holder);
//Now insert them in the reverse order
//in the base hook intrusive list
for(MyClass * it(&values[0]), *itend(&values[NumElements])
; it != itend; ++it){
my_list.push_front(*it);
my_slist.push_front(*it);
my_rbtree.insert_unique(*it);
my_hash.insert_unique(*it);
}
//Now test lists
{
List::const_iterator list_it (my_list.cbegin());
Slist::const_iterator slist_it (my_slist.cbegin());
Rbtree::const_iterator rbtree_it (my_rbtree.cbegin());
Hash::const_iterator hash_it (my_hash.cbegin());
MyClass *it_val(&values[NumElements] - 1), *it_rbeg_val(&values[0]-1);
//Test the objects inserted in the base hook list
for(; it_val != it_rbeg_val; --it_val, ++list_it, ++slist_it, ++rbtree_it){
if(&*list_it != &*it_val) return 1;
if(&*slist_it != &*it_val) return 1;
if(&*rbtree_it != &*it_val) return 1;
hash_it = my_hash.find(*it_val);
if(hash_it == my_hash.cend() || &*hash_it != &*it_val)
return 1;
}
}
return 0;
}

View File

@ -35,17 +35,19 @@ struct test_list
static void test_shift(std::vector<value_type>& values); static void test_shift(std::vector<value_type>& values);
static void test_swap(std::vector<value_type>& values); static void test_swap(std::vector<value_type>& values);
static void test_clone(std::vector<value_type>& values); static void test_clone(std::vector<value_type>& values);
static void test_container_from_end(std::vector<value_type>& values);
}; };
template<class ValueTraits> template<class ValueTraits>
void test_list<ValueTraits>::test_all(std::vector<typename ValueTraits::value_type>& values) void test_list<ValueTraits>::test_all(std::vector<typename ValueTraits::value_type>& values)
{ {
typedef boost::intrusive::list typedef typename ValueTraits::value_type value_type;
< ValueTraits typedef list
, ValueTraits::value_type::constant_time_size < value_type
, std::size_t , value_traits<ValueTraits>
, size_type<std::size_t>
, constant_time_size<value_type::constant_time_size>
> list_type; > list_type;
{ {
list_type list(values.begin(), values.end()); list_type list(values.begin(), values.end());
test::test_container(list); test::test_container(list);
@ -60,9 +62,15 @@ void test_list<ValueTraits>::test_all(std::vector<typename ValueTraits::value_ty
test_shift(values); test_shift(values);
test_swap(values); test_swap(values);
test_clone(values); test_clone(values);
test_container_from_end(values);
list_type testlist(values.begin(), values.end()); /*
list_type testlist2; const char *list_name = typeid(list_type).name();
std::cout << list_name << std::endl << strlen(list_name) << std::endl;
const char *value_t = typeid(typename list_type::value_traits).name();
std::cout << value_t << std::endl << strlen(value_t) << std::endl;
const char *list_it_name = typeid(typename list_type::iterator).name();
std::cout << list_it_name << std::endl << strlen(list_it_name ) << std::endl;
*/
} }
//test: push_front, pop_front, push_back, pop_back, front, back, size, empty: //test: push_front, pop_front, push_back, pop_back, front, back, size, empty:
@ -70,10 +78,12 @@ template<class ValueTraits>
void test_list<ValueTraits> void test_list<ValueTraits>
::test_front_back(std::vector<typename ValueTraits::value_type>& values) ::test_front_back(std::vector<typename ValueTraits::value_type>& values)
{ {
typedef boost::intrusive::list typedef typename ValueTraits::value_type value_type;
< ValueTraits typedef list
, ValueTraits::value_type::constant_time_size < value_type
, std::size_t , value_traits<ValueTraits>
, size_type<std::size_t>
, constant_time_size<value_type::constant_time_size>
> list_type; > list_type;
list_type testlist; list_type testlist;
BOOST_TEST (testlist.empty()); BOOST_TEST (testlist.empty());
@ -104,12 +114,12 @@ template<class ValueTraits>
void test_list<ValueTraits> void test_list<ValueTraits>
::test_sort(std::vector<typename ValueTraits::value_type>& values) ::test_sort(std::vector<typename ValueTraits::value_type>& values)
{ {
typedef typename ValueTraits::value_type testvalue_t; typedef typename ValueTraits::value_type value_type;
std::vector<int> expected; typedef list
typedef boost::intrusive::list < value_type
< ValueTraits , value_traits<ValueTraits>
, ValueTraits::value_type::constant_time_size , size_type<std::size_t>
, std::size_t , constant_time_size<value_type::constant_time_size>
> list_type; > list_type;
list_type testlist(values.begin(), values.end()); list_type testlist(values.begin(), values.end());
@ -125,17 +135,17 @@ void test_list<ValueTraits>
TEST_INTRUSIVE_SEQUENCE( init_values, testlist.begin() ); } TEST_INTRUSIVE_SEQUENCE( init_values, testlist.begin() ); }
} }
//test: assign, insert, const_iterator, const_reverse_iterator, erase, iterator_to: //test: assign, insert, const_iterator, const_reverse_iterator, erase, s_iterator_to:
template<class ValueTraits> template<class ValueTraits>
void test_list<ValueTraits> void test_list<ValueTraits>
::test_insert(std::vector<typename ValueTraits::value_type>& values) ::test_insert(std::vector<typename ValueTraits::value_type>& values)
{ {
typedef typename ValueTraits::value_type testvalue_t; typedef typename ValueTraits::value_type value_type;
std::vector<int> expected; typedef list
typedef boost::intrusive::list < value_type
< ValueTraits , value_traits<ValueTraits>
, ValueTraits::value_type::constant_time_size , size_type<std::size_t>
, std::size_t , constant_time_size<value_type::constant_time_size>
> list_type; > list_type;
list_type testlist; list_type testlist;
testlist.assign (&values[0] + 2, &values[0] + 5); testlist.assign (&values[0] + 2, &values[0] + 5);
@ -159,6 +169,9 @@ void test_list<ValueTraits>
i = testlist.iterator_to (values[4]); i = testlist.iterator_to (values[4]);
BOOST_TEST (&*i == &values[4]); BOOST_TEST (&*i == &values[4]);
i = list_type::s_iterator_to (values[4]);
BOOST_TEST (&*i == &values[4]);
i = testlist.erase (i); i = testlist.erase (i);
BOOST_TEST (i == testlist.end()); BOOST_TEST (i == testlist.end());
@ -170,15 +183,14 @@ template<class ValueTraits>
void test_list<ValueTraits> void test_list<ValueTraits>
::test_shift(std::vector<typename ValueTraits::value_type>& values) ::test_shift(std::vector<typename ValueTraits::value_type>& values)
{ {
typedef typename ValueTraits::value_type testvalue_t; typedef typename ValueTraits::value_type value_type;
typedef boost::intrusive::list typedef list
< ValueTraits < value_type
, ValueTraits::value_type::constant_time_size , value_traits<ValueTraits>
, std::size_t , size_type<std::size_t>
, constant_time_size<value_type::constant_time_size>
> list_type; > list_type;
list_type testlist; list_type testlist;
std::vector<int> expected;
const int num_values = (int)values.size(); const int num_values = (int)values.size();
std::vector<int> expected_values(num_values); std::vector<int> expected_values(num_values);
@ -210,12 +222,13 @@ template<class ValueTraits>
void test_list<ValueTraits> void test_list<ValueTraits>
::test_swap(std::vector<typename ValueTraits::value_type>& values) ::test_swap(std::vector<typename ValueTraits::value_type>& values)
{ {
typedef typename ValueTraits::value_type testvalue_t; typedef typename ValueTraits::value_type value_type;
typedef boost::intrusive::list typedef list
<ValueTraits < value_type
,ValueTraits::value_type::constant_time_size, std::size_t , value_traits<ValueTraits>
, size_type<std::size_t>
, constant_time_size<value_type::constant_time_size>
> list_type; > list_type;
std::vector<int> expected;
{ {
list_type testlist1 (&values[0], &values[0] + 2); list_type testlist1 (&values[0], &values[0] + 2);
list_type testlist2; list_type testlist2;
@ -267,23 +280,40 @@ void test_list<ValueTraits>
} }
} }
template<class ValueTraits>
void test_list<ValueTraits>
::test_container_from_end(std::vector<typename ValueTraits::value_type>& values)
{
typedef typename ValueTraits::value_type value_type;
typedef list
< value_type
, value_traits<ValueTraits>
, size_type<std::size_t>
, constant_time_size<value_type::constant_time_size>
> list_type;
list_type testlist1 (&values[0], &values[0] + values.size());
BOOST_TEST (testlist1 == list_type::container_from_end_iterator(testlist1.end()));
BOOST_TEST (testlist1 == list_type::container_from_end_iterator(testlist1.cend()));
}
template<class ValueTraits> template<class ValueTraits>
void test_list<ValueTraits> void test_list<ValueTraits>
::test_clone(std::vector<typename ValueTraits::value_type>& values) ::test_clone(std::vector<typename ValueTraits::value_type>& values)
{ {
typedef typename ValueTraits::value_type testvalue_t; typedef typename ValueTraits::value_type value_type;
std::vector<int> expected; typedef list
typedef boost::intrusive::list < value_type
<ValueTraits , value_traits<ValueTraits>
,ValueTraits::value_type::constant_time_size, std::size_t , size_type<std::size_t>
, constant_time_size<value_type::constant_time_size>
> list_type; > list_type;
list_type testlist1 (&values[0], &values[0] + values.size()); list_type testlist1 (&values[0], &values[0] + values.size());
list_type testlist2; list_type testlist2;
testlist2.clone_from(testlist1, test::new_cloner(), test::delete_disposer()); testlist2.clone_from(testlist1, test::new_cloner<value_type>(), test::delete_disposer<value_type>());
BOOST_TEST (testlist2 == testlist1); BOOST_TEST (testlist2 == testlist1);
testlist2.clear_and_dispose(test::delete_disposer()); testlist2.clear_and_dispose(test::delete_disposer<value_type>());
BOOST_TEST (testlist2.empty()); BOOST_TEST (testlist2.empty());
} }
@ -293,17 +323,24 @@ class test_main_template
public: public:
int operator()() int operator()()
{ {
typedef testvalue<VoidPointer, constant_time_size> testvalue_t; typedef testvalue<VoidPointer, constant_time_size> value_type;
std::vector<testvalue_t> data (5); std::vector<value_type> data (5);
for (int i = 0; i < 5; ++i) for (int i = 0; i < 5; ++i)
data[i].value_ = i + 1; data[i].value_ = i + 1;
test_list <typename testvalue_t::list_base_hook_t::template test_list < typename detail::get_base_value_traits
value_traits<testvalue_t> >::test_all(data); < value_type
, typename value_type::list_base_hook_t
test_list <typename testvalue_t::list_member_hook_t::template >::type
value_traits<testvalue_t, &testvalue_t::list_node_> >::test_all(data); >::test_all(data);
test_list < typename detail::get_member_value_traits
< value_type
, member_hook< value_type
, typename value_type::list_member_hook_t
, &value_type::list_node_
>
>::type
>::test_all(data);
return 0; return 0;
} }
}; };
@ -314,48 +351,64 @@ class test_main_template<VoidPointer, false>
public: public:
int operator()() int operator()()
{ {
typedef testvalue<VoidPointer, false> testvalue_t; typedef testvalue<VoidPointer, false> value_type;
std::vector<testvalue_t> data (5); std::vector<value_type> data (5);
for (int i = 0; i < 5; ++i) for (int i = 0; i < 5; ++i)
data[i].value_ = i + 1; data[i].value_ = i + 1;
test_list <typename testvalue_t::list_base_hook_t::template test_list < typename detail::get_base_value_traits
value_traits<testvalue_t> >::test_all(data); < value_type
, typename value_type::list_base_hook_t
>::type
>::test_all(data);
test_list <typename testvalue_t::list_member_hook_t::template test_list < typename detail::get_member_value_traits
value_traits<testvalue_t, &testvalue_t::list_node_> >::test_all(data); < value_type
, member_hook< value_type
, typename value_type::list_member_hook_t
, &value_type::list_node_
>
>::type
>::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
>::type
>::test_all(data);
test_list <typename testvalue_t::list_auto_base_hook_t::template test_list < typename detail::get_member_value_traits
value_traits<testvalue_t> >::test_all(data); < value_type
, member_hook< value_type
test_list <typename testvalue_t::list_auto_member_hook_t::template , typename value_type::list_auto_member_hook_t
value_traits<testvalue_t, &testvalue_t::list_auto_node_> >::test_all(data); , &value_type::list_auto_node_
>
>::type
>::test_all(data);
/*
test_list<stateful_value_traits
< value_type
, list_node_traits<VoidPointer>
, auto_unlink>
>::test_all(data);
*/
return 0; return 0;
} }
}; };
//Explicit instantiations of non-counted classes
//template class boost::intrusive::list<list_base_raw, false>;
//template class boost::intrusive::list<list_member_raw, false>;
//template class boost::intrusive::list<list_auto_base_raw, false>;
//template class boost::intrusive::list<list_auto_member_raw, false>;
//template class boost::intrusive::list<list_base_smart, false>;
//template class boost::intrusive::list<list_member_smart, false>;
//template class boost::intrusive::list<list_auto_base_smart, false>;
//template class boost::intrusive::list<list_auto_member_smart, false>;
//Explicit instantiation of counted classes
//template class boost::intrusive::list<list_base_raw_t, true>;
//template class boost::intrusive::list<list_member_raw_t, true>;
//template class boost::intrusive::list<list_base_smart_t, true>;
//template class boost::intrusive::list<list_member_smart_t, true>;
int main( int, char* [] ) int main( int, char* [] )
{ {
test_main_template<void*, false>()(); test_main_template<void*, false>()();
test_main_template<boost::intrusive::smart_ptr<void>, false>()(); test_main_template<smart_ptr<void>, false>()();
test_main_template<void*, true>()(); test_main_template<void*, true>()();
test_main_template<boost::intrusive::smart_ptr<void>, true>()(); test_main_template<smart_ptr<void>, true>()();
return boost::report_errors(); return boost::report_errors();
} }
#include <boost/intrusive/detail/config_end.hpp> #include <boost/intrusive/detail/config_end.hpp>

View File

@ -0,0 +1,148 @@
/////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2007
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/intrusive for documentation.
//
/////////////////////////////////////////////////////////////////////////////
#include <boost/intrusive/list.hpp>
#include <boost/intrusive/slist.hpp>
#include <boost/intrusive/set.hpp>
#include <boost/intrusive/unordered_set.hpp>
#include <boost/intrusive/detail/mpl.hpp>
#include "smart_ptr.hpp"
#include <vector>
using namespace boost::intrusive;
class MyClass
: public make_list_base_hook
< void_pointer<smart_ptr<void> >, link_mode<normal_link> >::type
, public make_slist_base_hook
< void_pointer<smart_ptr<void> >, link_mode<normal_link> >::type
, public make_set_base_hook
< void_pointer<smart_ptr<void> >, link_mode<normal_link> >::type
, public make_unordered_set_base_hook
< void_pointer<smart_ptr<void> >, link_mode<normal_link> >::type
{
int int_;
public:
MyClass(int i)
: int_(i)
{}
friend bool operator<(const MyClass &l, const MyClass &r)
{ return l.int_ < r.int_; }
friend bool operator==(const MyClass &l, const MyClass &r)
{ return l.int_ == r.int_; }
friend std::size_t hash_value(const MyClass &v)
{ return boost::hash_value(v.int_); }
};
//Define a list that will store MyClass using the public base hook
typedef make_list<MyClass>::type List;
typedef make_slist<MyClass>::type Slist;
typedef make_set<MyClass>::type Set;
typedef make_unordered_set<MyClass>::type USet;
int main()
{
typedef std::vector<MyClass>::iterator VectIt;
typedef std::vector<MyClass>::reverse_iterator VectRit;
//Create several MyClass objects, each one with a different value
std::vector<MyClass> values;
for(int i = 0; i < 100; ++i) values.push_back(MyClass(i));
USet::bucket_type buckets[100];
List my_list;
Slist my_slist;
Set my_set;
USet my_uset(USet::bucket_traits(buckets, 100));
//Now insert them in the reverse order
//in the base hook intrusive list
for(VectIt it(values.begin()), itend(values.end()); it != itend; ++it){
my_list.push_front(*it);
my_slist.push_front(*it);
my_set.insert(*it);
my_uset.insert(*it);
}
//Now test lists
{
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());
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){
if(&*list_it != &*vect_it) return 1;
if(&*slist_it != &*vect_it) return 1;
if(&*set_rit != &*vect_it) return 1;
if(my_uset.find(*set_rit) == my_uset.cend()) return 1;
}
}
//Check defined types and implicitly defined types are equal
if(detail::is_same<make_list_base_hook<void_pointer<void*>, link_mode<safe_link> >::type
,make_list_base_hook<>::type
>::value == false){
return 1;
}
if(detail::is_same<make_slist_base_hook<void_pointer<void*>, link_mode<safe_link> >::type
,make_slist_base_hook<>::type
>::value == false){
return 1;
}
if(detail::is_same<make_set_base_hook<void_pointer<void*>, link_mode<safe_link> >::type
,make_set_base_hook<>::type
>::value == false){
return 1;
}
if(detail::is_same<make_unordered_set_base_hook<void_pointer<void*>, link_mode<safe_link> >::type
,make_unordered_set_base_hook<>::type
>::value == false){
return 1;
}
//Check defined types and implicitly defined types are unequal
if(detail::is_same<make_list_base_hook<void_pointer<void*>, link_mode<normal_link> >::type
,make_list_base_hook<>::type
>::value == true){
return 1;
}
if(detail::is_same<make_slist_base_hook<void_pointer<void*>, link_mode<normal_link> >::type
,make_slist_base_hook<>::type
>::value == true){
return 1;
}
if(detail::is_same<make_set_base_hook<void_pointer<void*>, link_mode<normal_link> >::type
,make_set_base_hook<>::type
>::value == true){
return 1;
}
if(detail::is_same<make_unordered_set_base_hook<void_pointer<void*>, link_mode<normal_link> >::type
,make_unordered_set_base_hook<>::type
>::value == true){
return 1;
}
return 0;
}

View File

@ -10,6 +10,7 @@
// See http://www.boost.org/libs/intrusive for documentation. // See http://www.boost.org/libs/intrusive for documentation.
// //
///////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////
#include <boost/intrusive/detail/config_begin.hpp> #include <boost/intrusive/detail/config_begin.hpp>
#include <boost/intrusive/set.hpp> #include <boost/intrusive/set.hpp>
#include <boost/intrusive/detail/pointer_to_other.hpp> #include <boost/intrusive/detail/pointer_to_other.hpp>
@ -22,7 +23,6 @@
#include "test_container.hpp" #include "test_container.hpp"
using namespace boost::intrusive; using namespace boost::intrusive;
template<class ValueTraits> template<class ValueTraits>
struct test_multiset struct test_multiset
{ {
@ -34,15 +34,17 @@ struct test_multiset
static void test_find(std::vector<value_type>& values); static void test_find(std::vector<value_type>& values);
static void test_impl(); static void test_impl();
static void test_clone(std::vector<value_type>& values); static void test_clone(std::vector<value_type>& values);
static void test_container_from_end(std::vector<value_type>& values);
}; };
template<class ValueTraits> template<class ValueTraits>
void test_multiset<ValueTraits>::test_all (std::vector<typename ValueTraits::value_type>& values) void test_multiset<ValueTraits>::test_all (std::vector<typename ValueTraits::value_type>& values)
{ {
typedef typename ValueTraits::value_type value_type;
typedef multiset typedef multiset
<ValueTraits < value_type
,std::less<typename ValueTraits::value_type> , value_traits<ValueTraits>
,ValueTraits::value_type::constant_time_size, std::size_t , constant_time_size<value_type::constant_time_size>
> multiset_type; > multiset_type;
{ {
multiset_type testset(values.begin(), values.end()); multiset_type testset(values.begin(), values.end());
@ -63,21 +65,24 @@ void test_multiset<ValueTraits>::test_all (std::vector<typename ValueTraits::val
test_find(values); test_find(values);
test_impl(); test_impl();
test_clone(values); test_clone(values);
test_container_from_end(values);
} }
//test case due to an error in tree implementation: //test case due to an error in tree implementation:
template<class ValueTraits> template<class ValueTraits>
void test_multiset<ValueTraits>::test_impl() void test_multiset<ValueTraits>::test_impl()
{ {
typedef typename ValueTraits::value_type testvalue_t; typedef typename ValueTraits::value_type value_type;
std::vector<testvalue_t> values (5); std::vector<value_type> values (5);
for (int i = 0; i < 5; ++i) for (int i = 0; i < 5; ++i)
values[i].value_ = i; values[i].value_ = i;
typedef typename ValueTraits::value_type value_type;
typedef multiset typedef multiset
<ValueTraits < value_type
,std::less<typename ValueTraits::value_type> , value_traits<ValueTraits>
,ValueTraits::value_type::constant_time_size, std::size_t , constant_time_size<value_type::constant_time_size>
> multiset_type; > multiset_type;
multiset_type testset; multiset_type testset;
for (int i = 0; i < 5; ++i) for (int i = 0; i < 5; ++i)
testset.insert (values[i]); testset.insert (values[i]);
@ -94,12 +99,13 @@ void test_multiset<ValueTraits>::test_impl()
template<class ValueTraits> template<class ValueTraits>
void test_multiset<ValueTraits>::test_sort(std::vector<typename ValueTraits::value_type>& values) void test_multiset<ValueTraits>::test_sort(std::vector<typename ValueTraits::value_type>& values)
{ {
typedef typename ValueTraits::value_type testvalue_t; typedef typename ValueTraits::value_type value_type;
typedef multiset typedef multiset
<ValueTraits < value_type
,std::less<typename ValueTraits::value_type> , value_traits<ValueTraits>
,ValueTraits::value_type::constant_time_size, std::size_t , constant_time_size<value_type::constant_time_size>
> multiset_type; > multiset_type;
multiset_type testset1 (values.begin(), values.end()); multiset_type testset1 (values.begin(), values.end());
{ int init_values [] = { 1, 2, 2, 3, 4, 5 }; { int init_values [] = { 1, 2, 2, 3, 4, 5 };
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); } TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
@ -108,9 +114,10 @@ void test_multiset<ValueTraits>::test_sort(std::vector<typename ValueTraits::val
BOOST_TEST (testset1.empty()); BOOST_TEST (testset1.empty());
typedef multiset typedef multiset
<ValueTraits <value_type
,even_odd , compare<even_odd>
,ValueTraits::value_type::constant_time_size, std::size_t , value_traits<ValueTraits>
, constant_time_size<value_type::constant_time_size>
> multiset_type2; > multiset_type2;
multiset_type2 testset2 (&values[0], &values[0] + 6); multiset_type2 testset2 (&values[0], &values[0] + 6);
{ int init_values [] = { 5, 3, 1, 4, 2, 2 }; { int init_values [] = { 5, 3, 1, 4, 2, 2 };
@ -124,11 +131,12 @@ void test_multiset<ValueTraits>::test_sort(std::vector<typename ValueTraits::val
template<class ValueTraits> template<class ValueTraits>
void test_multiset<ValueTraits>::test_insert(std::vector<typename ValueTraits::value_type>& values) void test_multiset<ValueTraits>::test_insert(std::vector<typename ValueTraits::value_type>& values)
{ {
typedef typename ValueTraits::value_type testvalue_t; typedef typename ValueTraits::value_type value_type;
typedef multiset typedef multiset
<ValueTraits < value_type
,std::less<typename ValueTraits::value_type> , value_traits<ValueTraits>
,ValueTraits::value_type::constant_time_size, std::size_t , size_type<std::size_t>
, constant_time_size<value_type::constant_time_size>
> multiset_type; > multiset_type;
multiset_type testset; multiset_type testset;
@ -147,6 +155,10 @@ void test_multiset<ValueTraits>::test_insert(std::vector<typename ValueTraits::v
i = testset.iterator_to (values[2]); i = testset.iterator_to (values[2]);
BOOST_TEST (&*i == &values[2]); BOOST_TEST (&*i == &values[2]);
i = multiset_type::s_iterator_to (values[2]);
BOOST_TEST (&*i == &values[2]);
testset.erase(i); testset.erase(i);
{ int init_values [] = { 1, 3, 5 }; { int init_values [] = { 1, 3, 5 };
@ -157,11 +169,12 @@ void test_multiset<ValueTraits>::test_insert(std::vector<typename ValueTraits::v
template<class ValueTraits> template<class ValueTraits>
void test_multiset<ValueTraits>::test_swap(std::vector<typename ValueTraits::value_type>& values) void test_multiset<ValueTraits>::test_swap(std::vector<typename ValueTraits::value_type>& values)
{ {
typedef typename ValueTraits::value_type testvalue_t; typedef typename ValueTraits::value_type value_type;
typedef multiset typedef multiset
<ValueTraits < value_type
,std::less<typename ValueTraits::value_type> , value_traits<ValueTraits>
,ValueTraits::value_type::constant_time_size, std::size_t , size_type<std::size_t>
, constant_time_size<value_type::constant_time_size>
> multiset_type; > multiset_type;
multiset_type testset1 (&values[0], &values[0] + 2); multiset_type testset1 (&values[0], &values[0] + 2);
multiset_type testset2; multiset_type testset2;
@ -182,16 +195,17 @@ void test_multiset<ValueTraits>::test_swap(std::vector<typename ValueTraits::val
template<class ValueTraits> template<class ValueTraits>
void test_multiset<ValueTraits>::test_find(std::vector<typename ValueTraits::value_type>& values) void test_multiset<ValueTraits>::test_find(std::vector<typename ValueTraits::value_type>& values)
{ {
typedef typename ValueTraits::value_type testvalue_t; typedef typename ValueTraits::value_type value_type;
typedef multiset typedef multiset
<ValueTraits < value_type
,std::less<typename ValueTraits::value_type> , value_traits<ValueTraits>
,ValueTraits::value_type::constant_time_size, std::size_t , size_type<std::size_t>
, constant_time_size<value_type::constant_time_size>
> multiset_type; > multiset_type;
multiset_type testset (values.begin(), values.end()); multiset_type testset (values.begin(), values.end());
typedef typename multiset_type::iterator iterator; typedef typename multiset_type::iterator iterator;
testvalue_t cmp_val; value_type cmp_val;
cmp_val.value_ = 2; cmp_val.value_ = 2;
iterator i = testset.find (cmp_val); iterator i = testset.find (cmp_val);
BOOST_TEST (i->value_ == 2); BOOST_TEST (i->value_ == 2);
@ -210,20 +224,37 @@ template<class ValueTraits>
void test_multiset<ValueTraits> void test_multiset<ValueTraits>
::test_clone(std::vector<typename ValueTraits::value_type>& values) ::test_clone(std::vector<typename ValueTraits::value_type>& values)
{ {
typedef typename ValueTraits::value_type testvalue_t; typedef typename ValueTraits::value_type value_type;
typedef multiset typedef multiset
<ValueTraits < value_type
,std::less<typename ValueTraits::value_type> , value_traits<ValueTraits>
,ValueTraits::value_type::constant_time_size, std::size_t , size_type<std::size_t>
, constant_time_size<value_type::constant_time_size>
> multiset_type;
multiset_type testmultiset1 (&values[0], &values[0] + values.size());
multiset_type testmultiset2;
testmultiset2.clone_from(testmultiset1, test::new_cloner<value_type>(), test::delete_disposer<value_type>());
BOOST_TEST (testmultiset2 == testmultiset1);
testmultiset2.clear_and_dispose(test::delete_disposer<value_type>());
BOOST_TEST (testmultiset2.empty());
}
template<class ValueTraits>
void test_multiset<ValueTraits>
::test_container_from_end(std::vector<typename ValueTraits::value_type>& values)
{
typedef typename ValueTraits::value_type value_type;
typedef multiset
< value_type
, value_traits<ValueTraits>
, size_type<std::size_t>
, constant_time_size<value_type::constant_time_size>
> multiset_type; > multiset_type;
multiset_type testmultiset1 (&values[0], &values[0] + values.size()); multiset_type testmultiset (&values[0], &values[0] + values.size());
multiset_type testmultiset2; BOOST_TEST (testmultiset == multiset_type::container_from_end_iterator(testmultiset.end()));
BOOST_TEST (testmultiset == multiset_type::container_from_end_iterator(testmultiset.cend()));
testmultiset2.clone_from(testmultiset1, test::new_cloner(), test::delete_disposer());
BOOST_TEST (testmultiset2 == testmultiset1);
testmultiset2.clear_and_dispose(test::delete_disposer());
BOOST_TEST (testmultiset2.empty());
} }
template<class VoidPointer, bool constant_time_size> template<class VoidPointer, bool constant_time_size>
@ -232,18 +263,25 @@ class test_main_template
public: public:
int operator()() int operator()()
{ {
typedef testvalue<VoidPointer, constant_time_size> testvalue_t; typedef testvalue<VoidPointer, constant_time_size> value_type;
static const int random_init[6] = { 3, 2, 4, 1, 5, 2 }; static const int random_init[6] = { 3, 2, 4, 1, 5, 2 };
std::vector<testvalue<VoidPointer, constant_time_size> > data (6); std::vector<testvalue<VoidPointer, constant_time_size> > data (6);
for (int i = 0; i < 6; ++i) for (int i = 0; i < 6; ++i)
data[i].value_ = random_init[i]; data[i].value_ = random_init[i];
test_multiset <typename testvalue_t::set_base_hook_t::template test_multiset < typename detail::get_base_value_traits
value_traits<testvalue_t> >::test_all(data); < value_type
, typename value_type::set_base_hook_t
test_multiset <typename testvalue_t::set_member_hook_t::template >::type
value_traits<testvalue_t, &testvalue_t::set_node_> >::test_all(data); >::test_all(data);
test_multiset < typename detail::get_member_value_traits
< value_type
, member_hook< value_type
, typename value_type::set_member_hook_t
, &value_type::set_node_
>
>::type
>::test_all(data);
return 0; return 0;
} }
}; };
@ -254,55 +292,73 @@ class test_main_template<VoidPointer, false>
public: public:
int operator()() int operator()()
{ {
typedef testvalue<VoidPointer, false> testvalue_t; typedef testvalue<VoidPointer, false> value_type;
static const int random_init[6] = { 3, 2, 4, 1, 5, 2 }; static const int random_init[6] = { 3, 2, 4, 1, 5, 2 };
std::vector<testvalue<VoidPointer, false> > data (6); std::vector<testvalue<VoidPointer, false> > data (6);
for (int i = 0; i < 6; ++i) for (int i = 0; i < 6; ++i)
data[i].value_ = random_init[i]; data[i].value_ = random_init[i];
test_multiset <typename testvalue_t::set_base_hook_t::template test_multiset < typename detail::get_base_value_traits
value_traits<testvalue_t> >::test_all(data); < value_type
, typename value_type::set_base_hook_t
>::type
>::test_all(data);
test_multiset <typename testvalue_t::set_member_hook_t::template test_multiset < typename detail::get_member_value_traits
value_traits<testvalue_t, &testvalue_t::set_node_> >::test_all(data); < value_type
, member_hook< value_type
, typename value_type::set_member_hook_t
, &value_type::set_node_
>
>::type
>::test_all(data);
test_multiset <typename testvalue_t::set_auto_base_hook_t::template test_multiset < typename detail::get_base_value_traits
value_traits<testvalue_t> >::test_all(data); < value_type
, typename value_type::set_auto_base_hook_t
>::type
>::test_all(data);
test_multiset <typename testvalue_t::set_auto_member_hook_t::template test_multiset < typename detail::get_member_value_traits
value_traits<testvalue_t, &testvalue_t::set_auto_node_> >::test_all(data); < value_type
, member_hook< value_type
, typename value_type::set_auto_member_hook_t
, &value_type::set_auto_node_
>
>::type
>::test_all(data);
return 0; return 0;
} }
}; };
/*
//Explicit instantiations of non-counted classes //Explicit instantiations of non-counted classes
template class multiset //template class multiset
<set_base_raw, std::less<set_base_raw::value_type>, false>; // <set_base_raw, std::less<set_base_raw::value_type>, false>;
template class multiset //template class multiset
<set_member_raw, std::less<set_member_raw::value_type>, false>; // <set_member_raw, std::less<set_member_raw::value_type>, false>;
template class multiset //template class multiset
<set_auto_base_raw, std::less<set_auto_base_raw::value_type>, false>; // <set_auto_base_raw, std::less<set_auto_base_raw::value_type>, false>;
template class multiset //template class multiset
<set_auto_member_raw, std::less<set_auto_member_raw::value_type>, false>; // <set_auto_member_raw, std::less<set_auto_member_raw::value_type>, false>;
template class multiset //template class multiset
<set_base_smart, std::less<set_base_smart::value_type>, false>; // <set_base_smart, std::less<set_base_smart::value_type>, false>;
template class multiset //template class multiset
<set_member_smart, std::less<set_member_smart::value_type>, false>; // <set_member_smart, std::less<set_member_smart::value_type>, false>;
template class multiset //template class multiset
<set_auto_base_smart, std::less<set_auto_base_smart::value_type>, false>; // <set_auto_base_smart, std::less<set_auto_base_smart::value_type>, false>;
template class multiset //template class multiset
<set_auto_member_smart, std::less<set_auto_member_smart::value_type>, false>; // <set_auto_member_smart, std::less<set_auto_member_smart::value_type>, false>;
//Explicit instantiation of counted classes //Explicit instantiation of counted classes
template class multiset //template class multiset
<set_base_raw_t, std::less<set_base_raw_t::value_type>, true>; // <set_base_raw_t, std::less<set_base_raw_t::value_type>, true>;
template class multiset //template class multiset
<set_member_raw_t, std::less<set_member_raw_t::value_type>, true>; // <set_member_raw_t, std::less<set_member_raw_t::value_type>, true>;
template class multiset //template class multiset
<set_base_smart_t, std::less<set_base_smart_t::value_type>, true>; // <set_base_smart_t, std::less<set_base_smart_t::value_type>, true>;
template class multiset //template class multiset
<set_member_smart_t, std::less<set_member_smart_t::value_type>, true>; // <set_member_smart_t, std::less<set_member_smart_t::value_type>, true>;
*/
int main( int, char* [] ) int main( int, char* [] )
{ {
test_main_template<void*, false>()(); test_main_template<void*, false>()();
@ -311,5 +367,3 @@ int main( int, char* [] )
test_main_template<smart_ptr<void>, true>()(); test_main_template<smart_ptr<void>, true>()();
return boost::report_errors(); return boost::report_errors();
} }
#include <boost/intrusive/detail/config_end.hpp>

View File

@ -34,15 +34,17 @@ struct test_set
static void test_find(std::vector<value_type>& values); static void test_find(std::vector<value_type>& values);
static void test_impl(); static void test_impl();
static void test_clone(std::vector<value_type>& values); static void test_clone(std::vector<value_type>& values);
static void test_container_from_end(std::vector<value_type>& values);
}; };
template<class ValueTraits> template<class ValueTraits>
void test_set<ValueTraits>::test_all(std::vector<typename ValueTraits::value_type>& values) void test_set<ValueTraits>::test_all(std::vector<typename ValueTraits::value_type>& values)
{ {
typedef boost::intrusive::set typedef typename ValueTraits::value_type value_type;
<ValueTraits typedef set
,std::less<typename ValueTraits::value_type> < value_type
,ValueTraits::value_type::constant_time_size, std::size_t , value_traits<ValueTraits>
, constant_time_size<value_type::constant_time_size>
> set_type; > set_type;
{ {
set_type testset(values.begin(), values.end()); set_type testset(values.begin(), values.end());
@ -63,21 +65,23 @@ void test_set<ValueTraits>::test_all(std::vector<typename ValueTraits::value_typ
test_find(values); test_find(values);
test_impl(); test_impl();
test_clone(values); test_clone(values);
test_container_from_end(values);
} }
//test case due to an error in tree implementation: //test case due to an error in tree implementation:
template<class ValueTraits> template<class ValueTraits>
void test_set<ValueTraits>::test_impl() void test_set<ValueTraits>::test_impl()
{ {
typedef typename ValueTraits::value_type testvalue_t; typedef typename ValueTraits::value_type value_type;
std::vector<testvalue_t> values (5); std::vector<value_type> values (5);
for (int i = 0; i < 5; ++i) for (int i = 0; i < 5; ++i)
values[i].value_ = i; values[i].value_ = i;
typedef boost::intrusive::set typedef typename ValueTraits::value_type value_type;
<ValueTraits typedef set
,std::less<typename ValueTraits::value_type> < value_type
,ValueTraits::value_type::constant_time_size, std::size_t , value_traits<ValueTraits>
, constant_time_size<value_type::constant_time_size>
> set_type; > set_type;
set_type testset; set_type testset;
for (int i = 0; i < 5; ++i) for (int i = 0; i < 5; ++i)
@ -95,11 +99,11 @@ void test_set<ValueTraits>::test_impl()
template<class ValueTraits> template<class ValueTraits>
void test_set<ValueTraits>::test_sort(std::vector<typename ValueTraits::value_type>& values) void test_set<ValueTraits>::test_sort(std::vector<typename ValueTraits::value_type>& values)
{ {
typedef typename ValueTraits::value_type testvalue_t; typedef typename ValueTraits::value_type value_type;
typedef boost::intrusive::set typedef set
<ValueTraits < value_type
,std::less<typename ValueTraits::value_type> , value_traits<ValueTraits>
,ValueTraits::value_type::constant_time_size, std::size_t , constant_time_size<value_type::constant_time_size>
> set_type; > set_type;
set_type testset1 (values.begin(), values.end()); set_type testset1 (values.begin(), values.end());
{ int init_values [] = { 1, 2, 3, 4, 5 }; { int init_values [] = { 1, 2, 3, 4, 5 };
@ -108,10 +112,12 @@ void test_set<ValueTraits>::test_sort(std::vector<typename ValueTraits::value_ty
testset1.clear(); testset1.clear();
BOOST_TEST (testset1.empty()); BOOST_TEST (testset1.empty());
typedef boost::intrusive::set typedef typename ValueTraits::value_type value_type;
<ValueTraits typedef set
,even_odd < value_type
,ValueTraits::value_type::constant_time_size, std::size_t , compare<even_odd>
, value_traits<ValueTraits>
, constant_time_size<value_type::constant_time_size>
> set_type2; > set_type2;
set_type2 testset2 (&values[0], &values[0] + 6); set_type2 testset2 (&values[0], &values[0] + 6);
{ int init_values [] = { 5, 3, 1, 4, 2 }; { int init_values [] = { 5, 3, 1, 4, 2 };
@ -120,15 +126,15 @@ void test_set<ValueTraits>::test_sort(std::vector<typename ValueTraits::value_ty
BOOST_TEST (testset2.rbegin()->value_ == 5); BOOST_TEST (testset2.rbegin()->value_ == 5);
} }
//test: insert, const_iterator, const_reverse_iterator, erase, iterator_to: //test: insert, const_iterator, const_reverse_iterator, erase, s_iterator_to:
template<class ValueTraits> template<class ValueTraits>
void test_set<ValueTraits>::test_insert(std::vector<typename ValueTraits::value_type>& values) void test_set<ValueTraits>::test_insert(std::vector<typename ValueTraits::value_type>& values)
{ {
typedef typename ValueTraits::value_type testvalue_t; typedef typename ValueTraits::value_type value_type;
typedef boost::intrusive::set typedef set
<ValueTraits < value_type
,std::less<typename ValueTraits::value_type> , value_traits<ValueTraits>
,ValueTraits::value_type::constant_time_size, std::size_t , constant_time_size<value_type::constant_time_size>
> set_type; > set_type;
set_type testset; set_type testset;
testset.insert(&values[0] + 2, &values[0] + 5); testset.insert(&values[0] + 2, &values[0] + 5);
@ -149,6 +155,9 @@ void test_set<ValueTraits>::test_insert(std::vector<typename ValueTraits::value_
i = testset.iterator_to (values[2]); i = testset.iterator_to (values[2]);
BOOST_TEST (&*i == &values[2]); BOOST_TEST (&*i == &values[2]);
i = set_type::s_iterator_to(values[2]);
BOOST_TEST (&*i == &values[2]);
testset.erase (i); testset.erase (i);
{ int init_values [] = { 1, 3, 5 }; { int init_values [] = { 1, 3, 5 };
TEST_INTRUSIVE_SEQUENCE( init_values, testset.begin() ); } TEST_INTRUSIVE_SEQUENCE( init_values, testset.begin() ); }
@ -158,11 +167,11 @@ void test_set<ValueTraits>::test_insert(std::vector<typename ValueTraits::value_
template<class ValueTraits> template<class ValueTraits>
void test_set<ValueTraits>::test_swap(std::vector<typename ValueTraits::value_type>& values) void test_set<ValueTraits>::test_swap(std::vector<typename ValueTraits::value_type>& values)
{ {
typedef typename ValueTraits::value_type testvalue_t; typedef typename ValueTraits::value_type value_type;
typedef boost::intrusive::set typedef set
<ValueTraits < value_type
,std::less<typename ValueTraits::value_type> , value_traits<ValueTraits>
,ValueTraits::value_type::constant_time_size, std::size_t , constant_time_size<value_type::constant_time_size>
> set_type; > set_type;
set_type testset1 (&values[0], &values[0] + 2); set_type testset1 (&values[0], &values[0] + 2);
set_type testset2; set_type testset2;
@ -185,16 +194,16 @@ void test_set<ValueTraits>::test_swap(std::vector<typename ValueTraits::value_ty
template<class ValueTraits> template<class ValueTraits>
void test_set<ValueTraits>::test_find(std::vector<typename ValueTraits::value_type>& values) void test_set<ValueTraits>::test_find(std::vector<typename ValueTraits::value_type>& values)
{ {
typedef typename ValueTraits::value_type testvalue_t; typedef typename ValueTraits::value_type value_type;
typedef boost::intrusive::set typedef set
<ValueTraits < value_type
,std::less<typename ValueTraits::value_type> , value_traits<ValueTraits>
,ValueTraits::value_type::constant_time_size, std::size_t , constant_time_size<value_type::constant_time_size>
> set_type; > set_type;
set_type testset (values.begin(), values.end()); set_type testset (values.begin(), values.end());
typedef typename set_type::iterator iterator; typedef typename set_type::iterator iterator;
testvalue_t cmp_val; value_type cmp_val;
cmp_val.value_ = 2; cmp_val.value_ = 2;
iterator i = testset.find (cmp_val); iterator i = testset.find (cmp_val);
BOOST_TEST (i->value_ == 2); BOOST_TEST (i->value_ == 2);
@ -213,20 +222,35 @@ template<class ValueTraits>
void test_set<ValueTraits> void test_set<ValueTraits>
::test_clone(std::vector<typename ValueTraits::value_type>& values) ::test_clone(std::vector<typename ValueTraits::value_type>& values)
{ {
typedef typename ValueTraits::value_type testvalue_t; typedef typename ValueTraits::value_type value_type;
typedef boost::intrusive::set typedef set
<ValueTraits < value_type
,std::less<typename ValueTraits::value_type> , value_traits<ValueTraits>
,ValueTraits::value_type::constant_time_size, std::size_t , constant_time_size<value_type::constant_time_size>
> set_type; > set_type;
set_type testset1 (&values[0], &values[0] + values.size()); set_type testset1 (&values[0], &values[0] + values.size());
set_type testset2; set_type testset2;
testset2.clone_from(testset1, test::new_cloner(), test::delete_disposer()); testset2.clone_from(testset1, test::new_cloner<value_type>(), test::delete_disposer<value_type>());
BOOST_TEST (testset2 == testset1); BOOST_TEST (testset2 == testset1);
testset2.clear_and_dispose(test::delete_disposer()); testset2.clear_and_dispose(test::delete_disposer<value_type>());
BOOST_TEST (testset2.empty()); BOOST_TEST (testset2.empty());
}
template<class ValueTraits>
void test_set<ValueTraits>
::test_container_from_end(std::vector<typename ValueTraits::value_type>& values)
{
typedef typename ValueTraits::value_type value_type;
typedef set
< value_type
, value_traits<ValueTraits>
, constant_time_size<value_type::constant_time_size>
> set_type;
set_type testset (&values[0], &values[0] + values.size());
BOOST_TEST (testset == set_type::container_from_end_iterator(testset.end()));
BOOST_TEST (testset == set_type::container_from_end_iterator(testset.cend()));
} }
template<class VoidPointer, bool constant_time_size> template<class VoidPointer, bool constant_time_size>
@ -235,18 +259,25 @@ class test_main_template
public: public:
int operator()() int operator()()
{ {
typedef testvalue<VoidPointer, constant_time_size> testvalue_t; typedef testvalue<VoidPointer, constant_time_size> value_type;
static const int random_init[6] = { 3, 2, 4, 1, 5, 2 }; static const int random_init[6] = { 3, 2, 4, 1, 5, 2 };
std::vector<testvalue<VoidPointer, constant_time_size> > data (6); std::vector<testvalue<VoidPointer, constant_time_size> > data (6);
for (int i = 0; i < 6; ++i) for (int i = 0; i < 6; ++i)
data[i].value_ = random_init[i]; data[i].value_ = random_init[i];
test_set <typename testvalue_t::set_base_hook_t::template test_set < typename detail::get_base_value_traits
value_traits<testvalue_t> >::test_all(data); < value_type
, typename value_type::set_base_hook_t
test_set <typename testvalue_t::set_member_hook_t::template >::type
value_traits<testvalue_t, &testvalue_t::set_node_> >::test_all(data); >::test_all(data);
test_set < typename detail::get_member_value_traits
< value_type
, member_hook< value_type
, typename value_type::set_member_hook_t
, &value_type::set_node_
>
>::type
>::test_all(data);
return 0; return 0;
} }
}; };
@ -257,61 +288,53 @@ class test_main_template<VoidPointer, false>
public: public:
int operator()() int operator()()
{ {
typedef testvalue<VoidPointer, false> testvalue_t; typedef testvalue<VoidPointer, false> value_type;
static const int random_init[6] = { 3, 2, 4, 1, 5, 2 }; static const int random_init[6] = { 3, 2, 4, 1, 5, 2 };
std::vector<testvalue<VoidPointer, false> > data (6); std::vector<testvalue<VoidPointer, false> > data (6);
for (int i = 0; i < 6; ++i) for (int i = 0; i < 6; ++i)
data[i].value_ = random_init[i]; data[i].value_ = random_init[i];
test_set <typename testvalue_t::set_base_hook_t::template test_set < typename detail::get_base_value_traits
value_traits<testvalue_t> >::test_all(data); < value_type
, typename value_type::set_base_hook_t
>::type
>::test_all(data);
test_set <typename testvalue_t::set_member_hook_t::template test_set < typename detail::get_member_value_traits
value_traits<testvalue_t, &testvalue_t::set_node_> >::test_all(data); < value_type
, member_hook< value_type
, typename value_type::set_member_hook_t
, &value_type::set_node_
>
>::type
>::test_all(data);
test_set <typename testvalue_t::set_auto_base_hook_t::template test_set < typename detail::get_base_value_traits
value_traits<testvalue_t> >::test_all(data); < value_type
, typename value_type::set_auto_base_hook_t
>::type
>::test_all(data);
test_set < typename detail::get_member_value_traits
< value_type
, member_hook< value_type
, typename value_type::set_auto_member_hook_t
, &value_type::set_auto_node_
>
>::type
>::test_all(data);
test_set <typename testvalue_t::set_auto_member_hook_t::template
value_traits<testvalue_t, &testvalue_t::set_auto_node_> >::test_all(data);
return 0; return 0;
} }
}; };
/*
//Explicit instantiations of non-counted classes
template class boost::intrusive::set
<set_base_raw, std::less<set_base_raw::value_type>, false>;
template class boost::intrusive::set
<set_member_raw, std::less<set_member_raw::value_type>, false>;
template class boost::intrusive::set
<set_auto_base_raw, std::less<set_auto_base_raw::value_type>, false>;
template class boost::intrusive::set
<set_auto_member_raw, std::less<set_auto_member_raw::value_type>, false>;
template class boost::intrusive::set
<set_base_smart, std::less<set_base_smart::value_type>, false>;
template class boost::intrusive::set
<set_member_smart, std::less<set_member_smart::value_type>, false>;
template class boost::intrusive::set
<set_auto_base_smart, std::less<set_auto_base_smart::value_type>, false>;
template class boost::intrusive::set
<set_auto_member_smart, std::less<set_auto_member_smart::value_type>, false>;
//Explicit instantiation of counted classes
template class boost::intrusive::set
<set_base_raw_t, std::less<set_base_raw_t::value_type>, true>;
template class boost::intrusive::set
<set_member_raw_t, std::less<set_member_raw_t::value_type>, true>;
template class boost::intrusive::set
<set_base_smart_t, std::less<set_base_smart_t::value_type>, true>;
template class boost::intrusive::set
<set_member_smart_t, std::less<set_member_smart_t::value_type>, true>;
*/
int main( int, char* [] ) int main( int, char* [] )
{ {
test_main_template<void*, false>()(); test_main_template<void*, false>()();
test_main_template<boost::intrusive::smart_ptr<void>, false>()(); test_main_template<smart_ptr<void>, false>()();
test_main_template<void*, true>()(); test_main_template<void*, true>()();
test_main_template<boost::intrusive::smart_ptr<void>, true>()(); test_main_template<smart_ptr<void>, true>()();
return boost::report_errors(); return boost::report_errors();
} }
#include <boost/intrusive/detail/config_end.hpp> #include <boost/intrusive/detail/config_end.hpp>

View File

@ -10,6 +10,7 @@
// See http://www.boost.org/libs/intrusive for documentation. // See http://www.boost.org/libs/intrusive for documentation.
// //
///////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////
#include <boost/intrusive/detail/config_begin.hpp> #include <boost/intrusive/detail/config_begin.hpp>
#include <boost/intrusive/slist.hpp> #include <boost/intrusive/slist.hpp>
#include <boost/intrusive/detail/pointer_to_other.hpp> #include <boost/intrusive/detail/pointer_to_other.hpp>
@ -36,15 +37,19 @@ struct test_slist
static void test_swap(std::vector<value_type>& values); static void test_swap(std::vector<value_type>& values);
static void test_slow_insert (std::vector<value_type>& values); static void test_slow_insert (std::vector<value_type>& values);
static void test_clone (std::vector<value_type>& values); static void test_clone (std::vector<value_type>& values);
static void test_container_from_end(std::vector<value_type> &values);
}; };
template<class ValueTraits> template<class ValueTraits>
void test_slist<ValueTraits> void test_slist<ValueTraits>
::test_all (std::vector<typename ValueTraits::value_type>& values) ::test_all (std::vector<typename ValueTraits::value_type>& values)
{ {
typedef boost::intrusive::slist typedef typename ValueTraits::value_type value_type;
<ValueTraits typedef slist
,ValueTraits::value_type::constant_time_size, std::size_t < value_type
, value_traits<ValueTraits>
, size_type<std::size_t>
, constant_time_size<value_type::constant_time_size>
> list_type; > list_type;
{ {
list_type list(values.begin(), values.end()); list_type list(values.begin(), values.end());
@ -61,6 +66,7 @@ void test_slist<ValueTraits>
test_slow_insert (values); test_slow_insert (values);
test_swap(values); test_swap(values);
test_clone(values); test_clone(values);
test_container_from_end(values);
} }
//test: push_front, pop_front, front, size, empty: //test: push_front, pop_front, front, size, empty:
@ -68,9 +74,12 @@ template<class ValueTraits>
void test_slist<ValueTraits> void test_slist<ValueTraits>
::test_front_back (std::vector<typename ValueTraits::value_type>& values) ::test_front_back (std::vector<typename ValueTraits::value_type>& values)
{ {
typedef boost::intrusive::slist typedef typename ValueTraits::value_type value_type;
<ValueTraits typedef slist
,ValueTraits::value_type::constant_time_size, std::size_t < value_type
, value_traits<ValueTraits>
, size_type<std::size_t>
, constant_time_size<value_type::constant_time_size>
> list_type; > list_type;
list_type testlist; list_type testlist;
BOOST_TEST (testlist.empty()); BOOST_TEST (testlist.empty());
@ -96,10 +105,12 @@ template<class ValueTraits>
void test_slist<ValueTraits> void test_slist<ValueTraits>
::test_merge (std::vector<typename ValueTraits::value_type>& values) ::test_merge (std::vector<typename ValueTraits::value_type>& values)
{ {
typedef typename ValueTraits::value_type testvalue_t; typedef typename ValueTraits::value_type value_type;
typedef boost::intrusive::slist typedef slist
<ValueTraits < value_type
,ValueTraits::value_type::constant_time_size, std::size_t , value_traits<ValueTraits>
, size_type<std::size_t>
, constant_time_size<value_type::constant_time_size>
> list_type; > list_type;
list_type testlist1, testlist2; list_type testlist1, testlist2;
testlist1.push_front (values[0]); testlist1.push_front (values[0]);
@ -117,10 +128,12 @@ template<class ValueTraits>
void test_slist<ValueTraits> void test_slist<ValueTraits>
::test_sort(std::vector<typename ValueTraits::value_type>& values) ::test_sort(std::vector<typename ValueTraits::value_type>& values)
{ {
typedef typename ValueTraits::value_type testvalue_t; typedef typename ValueTraits::value_type value_type;
typedef boost::intrusive::slist typedef slist
<ValueTraits < value_type
,ValueTraits::value_type::constant_time_size, std::size_t , value_traits<ValueTraits>
, size_type<std::size_t>
, constant_time_size<value_type::constant_time_size>
> list_type; > list_type;
list_type testlist (values.begin(), values.end()); list_type testlist (values.begin(), values.end());
@ -136,15 +149,17 @@ void test_slist<ValueTraits>
TEST_INTRUSIVE_SEQUENCE( init_values, testlist.begin() ); } TEST_INTRUSIVE_SEQUENCE( init_values, testlist.begin() ); }
} }
//test: assign, insert_after, const_iterator, erase_after, iterator_to, previous: //test: assign, insert_after, const_iterator, erase_after, s_iterator_to, previous:
template<class ValueTraits> template<class ValueTraits>
void test_slist<ValueTraits> void test_slist<ValueTraits>
::test_insert(std::vector<typename ValueTraits::value_type>& values) ::test_insert(std::vector<typename ValueTraits::value_type>& values)
{ {
typedef typename ValueTraits::value_type testvalue_t; typedef typename ValueTraits::value_type value_type;
typedef boost::intrusive::slist typedef slist
<ValueTraits < value_type
,ValueTraits::value_type::constant_time_size, std::size_t , value_traits<ValueTraits>
, size_type<std::size_t>
, constant_time_size<value_type::constant_time_size>
> list_type; > list_type;
list_type testlist; list_type testlist;
testlist.assign (&values[0] + 2, &values[0] + 5); testlist.assign (&values[0] + 2, &values[0] + 5);
@ -162,6 +177,8 @@ void test_slist<ValueTraits>
i = testlist.iterator_to (values[4]); i = testlist.iterator_to (values[4]);
BOOST_TEST (&*i == &values[4]); BOOST_TEST (&*i == &values[4]);
i = list_type::s_iterator_to (values[4]);
BOOST_TEST (&*i == &values[4]);
i = testlist.previous (i); i = testlist.previous (i);
BOOST_TEST (&*i == &values[0]); BOOST_TEST (&*i == &values[0]);
@ -171,15 +188,17 @@ void test_slist<ValueTraits>
TEST_INTRUSIVE_SEQUENCE( init_values, const_testlist.begin() ); } TEST_INTRUSIVE_SEQUENCE( init_values, const_testlist.begin() ); }
} }
//test: insert, const_iterator, erase, iterator_to: //test: insert, const_iterator, erase, siterator_to:
template<class ValueTraits> template<class ValueTraits>
void test_slist<ValueTraits> void test_slist<ValueTraits>
::test_slow_insert (std::vector<typename ValueTraits::value_type>& values) ::test_slow_insert (std::vector<typename ValueTraits::value_type>& values)
{ {
typedef typename ValueTraits::value_type testvalue_t; typedef typename ValueTraits::value_type value_type;
typedef boost::intrusive::slist typedef slist
<ValueTraits < value_type
,ValueTraits::value_type::constant_time_size, std::size_t , value_traits<ValueTraits>
, size_type<std::size_t>
, constant_time_size<value_type::constant_time_size>
> list_type; > list_type;
list_type testlist; list_type testlist;
testlist.push_front (values[4]); testlist.push_front (values[4]);
@ -199,6 +218,9 @@ void test_slist<ValueTraits>
i = testlist.iterator_to (values[4]); i = testlist.iterator_to (values[4]);
BOOST_TEST (&*i == &values[4]); BOOST_TEST (&*i == &values[4]);
i = list_type::s_iterator_to (values[4]);
BOOST_TEST (&*i == &values[4]);
i = testlist.erase (i); i = testlist.erase (i);
BOOST_TEST (i == testlist.end()); BOOST_TEST (i == testlist.end());
@ -214,10 +236,12 @@ template<class ValueTraits>
void test_slist<ValueTraits> void test_slist<ValueTraits>
::test_shift(std::vector<typename ValueTraits::value_type>& values) ::test_shift(std::vector<typename ValueTraits::value_type>& values)
{ {
typedef typename ValueTraits::value_type testvalue_t; typedef typename ValueTraits::value_type value_type;
typedef boost::intrusive::slist typedef slist
<ValueTraits < value_type
,ValueTraits::value_type::constant_time_size, std::size_t , value_traits<ValueTraits>
, size_type<std::size_t>
, constant_time_size<value_type::constant_time_size>
> list_type; > list_type;
list_type testlist; list_type testlist;
@ -254,10 +278,12 @@ template<class ValueTraits>
void test_slist<ValueTraits> void test_slist<ValueTraits>
::test_swap(std::vector<typename ValueTraits::value_type>& values) ::test_swap(std::vector<typename ValueTraits::value_type>& values)
{ {
typedef typename ValueTraits::value_type testvalue_t; typedef typename ValueTraits::value_type value_type;
typedef boost::intrusive::slist typedef slist
<ValueTraits < value_type
,ValueTraits::value_type::constant_time_size, std::size_t , value_traits<ValueTraits>
, size_type<std::size_t>
, constant_time_size<value_type::constant_time_size>
> list_type; > list_type;
{ {
list_type testlist1 (&values[0], &values[0] + 2); list_type testlist1 (&values[0], &values[0] + 2);
@ -306,37 +332,63 @@ template<class ValueTraits>
void test_slist<ValueTraits> void test_slist<ValueTraits>
::test_clone(std::vector<typename ValueTraits::value_type>& values) ::test_clone(std::vector<typename ValueTraits::value_type>& values)
{ {
typedef typename ValueTraits::value_type testvalue_t; typedef typename ValueTraits::value_type value_type;
typedef boost::intrusive::slist typedef slist
<ValueTraits < value_type
,ValueTraits::value_type::constant_time_size, std::size_t , value_traits<ValueTraits>
, size_type<std::size_t>
, constant_time_size<value_type::constant_time_size>
> list_type; > list_type;
list_type testlist1 (&values[0], &values[0] + values.size()); list_type testlist1 (&values[0], &values[0] + values.size());
list_type testlist2; list_type testlist2;
testlist2.clone_from(testlist1, test::new_cloner(), test::delete_disposer()); testlist2.clone_from(testlist1, test::new_cloner<value_type>(), test::delete_disposer<value_type>());
BOOST_TEST (testlist2 == testlist1); BOOST_TEST (testlist2 == testlist1);
testlist2.clear_and_dispose(test::delete_disposer()); testlist2.clear_and_dispose(test::delete_disposer<value_type>());
BOOST_TEST (testlist2.empty()); BOOST_TEST (testlist2.empty());
} }
template<class ValueTraits>
void test_slist<ValueTraits>
::test_container_from_end(std::vector<typename ValueTraits::value_type>& values)
{
typedef typename ValueTraits::value_type value_type;
typedef slist
< value_type
, value_traits<ValueTraits>
, size_type<std::size_t>
, constant_time_size<value_type::constant_time_size>
> list_type;
list_type testlist1 (&values[0], &values[0] + values.size());
BOOST_TEST (testlist1 == list_type::container_from_end_iterator(testlist1.end()));
BOOST_TEST (testlist1 == list_type::container_from_end_iterator(testlist1.cend()));
}
template<class VoidPointer, bool constant_time_size> template<class VoidPointer, bool constant_time_size>
class test_main_template class test_main_template
{ {
public: public:
int operator()() int operator()()
{ {
typedef testvalue<VoidPointer, constant_time_size> testvalue_t; typedef testvalue<VoidPointer, constant_time_size> value_type;
std::vector<testvalue_t> data (5); std::vector<value_type> data (5);
for (int i = 0; i < 5; ++i) for (int i = 0; i < 5; ++i)
data[i].value_ = i + 1; data[i].value_ = i + 1;
test_slist <typename testvalue_t::slist_base_hook_t::template test_slist < typename detail::get_base_value_traits
value_traits<testvalue_t> >::test_all(data); < value_type
, typename value_type::slist_base_hook_t
test_slist <typename testvalue_t::slist_member_hook_t::template >::type
value_traits<testvalue_t, &testvalue_t::slist_node_> >::test_all(data); >::test_all(data);
test_slist < typename detail::get_member_value_traits
< value_type
, member_hook< value_type
, typename value_type::slist_member_hook_t
, &value_type::slist_node_
>
>::type
>::test_all(data);
return 0; return 0;
} }
@ -348,48 +400,50 @@ class test_main_template<VoidPointer, false>
public: public:
int operator()() int operator()()
{ {
typedef testvalue<VoidPointer, false> testvalue_t; typedef testvalue<VoidPointer, false> value_type;
std::vector<testvalue_t> data (5); std::vector<value_type> data (5);
for (int i = 0; i < 5; ++i) for (int i = 0; i < 5; ++i)
data[i].value_ = i + 1; data[i].value_ = i + 1;
test_slist <typename testvalue_t::slist_base_hook_t::template test_slist < typename detail::get_base_value_traits
value_traits<testvalue_t> >::test_all(data); < value_type
, typename value_type::slist_base_hook_t
>::type
>::test_all(data);
test_slist <typename testvalue_t::slist_member_hook_t::template test_slist < typename detail::get_member_value_traits
value_traits<testvalue_t, &testvalue_t::slist_node_> >::test_all(data); < value_type
, member_hook< value_type
, typename value_type::slist_member_hook_t
, &value_type::slist_node_
>
>::type
>::test_all(data);
test_slist <typename testvalue_t::slist_auto_base_hook_t::template test_slist < typename detail::get_base_value_traits
value_traits<testvalue_t> >::test_all(data); < value_type
, typename value_type::slist_auto_base_hook_t
>::type
>::test_all(data);
test_slist <typename testvalue_t::slist_auto_member_hook_t::template test_slist < typename detail::get_member_value_traits
value_traits<testvalue_t, &testvalue_t::slist_auto_node_> >::test_all(data); < value_type
, member_hook< value_type
, typename value_type::slist_auto_member_hook_t
, &value_type::slist_auto_node_
>
>::type
>::test_all(data);
return 0; return 0;
} }
}; };
/*
//Explicit instantiations of non-counted classes
template class boost::intrusive::slist<slist_base_raw, false>;
template class boost::intrusive::slist<slist_member_raw, false>;
template class boost::intrusive::slist<slist_auto_base_raw, false>;
template class boost::intrusive::slist<slist_auto_member_raw, false>;
template class boost::intrusive::slist<slist_base_smart, false>;
template class boost::intrusive::slist<slist_member_smart, false>;
template class boost::intrusive::slist<slist_auto_base_smart, false>;
template class boost::intrusive::slist<slist_auto_member_smart, false>;
//Explicit instantiation of counted classes
template class boost::intrusive::slist<slist_base_raw_t, true>;
template class boost::intrusive::slist<slist_member_raw_t, true>;
template class boost::intrusive::slist<slist_base_smart_t, true>;
template class boost::intrusive::slist<slist_member_smart_t, true>;
*/
int main(int, char* []) int main(int, char* [])
{ {
test_main_template<void*, false>()(); test_main_template<void*, false>()();
test_main_template<boost::intrusive::smart_ptr<void>, false>()(); test_main_template<smart_ptr<void>, false>()();
test_main_template<void*, true>()(); test_main_template<void*, true>()();
test_main_template<boost::intrusive::smart_ptr<void>, true>()(); test_main_template<smart_ptr<void>, true>()();
return boost::report_errors(); return boost::report_errors();
} }
#include <boost/intrusive/detail/config_end.hpp> #include <boost/intrusive/detail/config_end.hpp>

View File

@ -0,0 +1,148 @@
/////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2007
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/intrusive for documentation.
//
/////////////////////////////////////////////////////////////////////////////
#include <boost/intrusive/list.hpp>
#include <boost/intrusive/slist.hpp>
#include <boost/intrusive/set.hpp>
#include <boost/intrusive/unordered_set.hpp>
#include <boost/functional/hash.hpp>
#include <boost/pointer_to_other.hpp>
#include <vector>
using namespace boost::intrusive;
class MyClass
{
public:
int int_;
MyClass(int i = 0)
: int_(i)
{}
friend bool operator<(const MyClass &l, const MyClass &r)
{ return l.int_ < r.int_; }
friend bool operator==(const MyClass &l, const MyClass &r)
{ return l.int_ == r.int_; }
friend std::size_t hash_value(const MyClass &v)
{ return boost::hash_value(v.int_); }
};
template<class T, class NodeTraits>
struct stateful_value_traits
{
typedef NodeTraits node_traits;
typedef typename node_traits::node node;
typedef typename node_traits::node_ptr node_ptr;
typedef typename node_traits::const_node_ptr const_node_ptr;
typedef T value_type;
typedef typename boost::pointer_to_other
<node_ptr, T>::type pointer;
typedef typename boost::pointer_to_other
<node_ptr, const T>::type const_pointer;
static const link_mode_type link_mode = normal_link;
stateful_value_traits(pointer values, node_ptr node_array)
: values_(values), node_array_(node_array)
{}
node_ptr to_node_ptr (value_type &value)
{ return node_array_ + (&value - values_); }
const_node_ptr to_node_ptr (const value_type &value) const
{ return node_array_ + (&value - values_); }
pointer to_value_ptr(node_ptr n)
{ return values_ + (n - node_array_); }
const_pointer to_value_ptr(const_node_ptr n) const
{ return values_ + (n - node_array_); }
pointer values_;
node_ptr node_array_;
};
//Define a list that will store MyClass using the external hook
typedef stateful_value_traits< MyClass, list_node_traits<void*> > list_traits;
typedef list<MyClass, value_traits<list_traits> > List;
//Define a slist that will store MyClass using the external hook
typedef stateful_value_traits< MyClass, slist_node_traits<void*> > slist_traits;
typedef slist<MyClass, value_traits<slist_traits> > Slist;
//Define a set that will store MyClass using the external hook
typedef stateful_value_traits< MyClass, rbtree_node_traits<void*> > rbtree_traits;
typedef set<MyClass, value_traits<rbtree_traits> > Set;
//uset uses the same traits as slist
typedef unordered_set<MyClass, value_traits<slist_traits> > Uset;
typedef list_traits::node list_node_t;
typedef slist_traits::node slist_node_t;
typedef rbtree_traits::node rbtree_node_t;
const int NumElements = 100;
MyClass values [NumElements];
list_node_t list_hook_array [NumElements];
slist_node_t slist_hook_array [NumElements];
rbtree_node_t rbtree_hook_array [NumElements];
slist_node_t uset_hook_array [NumElements];
int main()
{
//Create several MyClass objects, each one with a different value
for(int i = 0; i < NumElements; ++i)
values[i].int_ = i;
Uset::bucket_type buckets[NumElements];
List my_list (list_traits (values, list_hook_array));
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>()
, slist_traits(values, uset_hook_array)
);
//Now insert them in the reverse order
//in the base hook intrusive list
for(MyClass * it(&values[0]), *itend(&values[NumElements])
; it != itend
; ++it){
my_list.push_front(*it);
my_slist.push_front(*it);
my_set.insert(*it);
my_uset.insert(*it);
}
//Now test lists
{
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());
MyClass *it_val(&values[NumElements-1]), *it_rbeg_val(&values[0]-1);
//Test the objects inserted in the base hook list
for(; it_val != it_rbeg_val; --it_val, ++list_it, ++slist_it, ++set_rit){
if(&*list_it != &*it_val) return 1;
if(&*slist_it != &*it_val) return 1;
if(&*set_rit != &*it_val) return 1;
if(my_uset.find(*it_val) == my_uset.cend()) return 1;
}
}
return 0;
}

View File

@ -44,15 +44,16 @@ struct test_unordered_multiset
template<class ValueTraits> template<class ValueTraits>
void test_unordered_multiset<ValueTraits>::test_all (std::vector<typename ValueTraits::value_type>& values) void test_unordered_multiset<ValueTraits>::test_all (std::vector<typename ValueTraits::value_type>& values)
{ {
typedef boost::intrusive::unordered_multiset typedef typename ValueTraits::value_type value_type;
<ValueTraits typedef unordered_multiset
,boost::hash<typename ValueTraits::value_type> <value_type
,std::equal_to<typename ValueTraits::value_type> , value_traits<ValueTraits>
,ValueTraits::value_type::constant_time_size, std::size_t , constant_time_size<value_type::constant_time_size>
> unordered_multiset_type; > 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 buckets [BucketSize];
unordered_multiset_type testset(buckets, BucketSize); unordered_multiset_type testset(bucket_traits(buckets, BucketSize));
testset.insert(values.begin(), values.end()); testset.insert(values.begin(), values.end());
test::test_container(testset); test::test_container(testset);
testset.clear(); testset.clear();
@ -78,18 +79,20 @@ void test_unordered_multiset<ValueTraits>::test_all (std::vector<typename ValueT
template<class ValueTraits> template<class ValueTraits>
void test_unordered_multiset<ValueTraits>::test_impl() void test_unordered_multiset<ValueTraits>::test_impl()
{ {
typedef typename ValueTraits::value_type testvalue_t; typedef typename ValueTraits::value_type value_type;
std::vector<testvalue_t> values (5); typedef unordered_multiset
<value_type
, value_traits<ValueTraits>
, constant_time_size<value_type::constant_time_size>
> unordered_multiset_type;
typedef typename unordered_multiset_type::bucket_traits bucket_traits;
std::vector<value_type> values (5);
for (int i = 0; i < 5; ++i) for (int i = 0; i < 5; ++i)
values[i].value_ = i; values[i].value_ = i;
typedef boost::intrusive::unordered_multiset
<ValueTraits
,boost::hash<typename ValueTraits::value_type>
,std::equal_to<typename ValueTraits::value_type>
,ValueTraits::value_type::constant_time_size, std::size_t
> unordered_multiset_type;
typename unordered_multiset_type::bucket_type buckets [BucketSize]; typename unordered_multiset_type::bucket_type buckets [BucketSize];
unordered_multiset_type testset(buckets, BucketSize); unordered_multiset_type testset(bucket_traits(buckets, BucketSize));
for (int i = 0; i < 5; ++i) for (int i = 0; i < 5; ++i)
testset.insert (values[i]); testset.insert (values[i]);
@ -106,15 +109,16 @@ void test_unordered_multiset<ValueTraits>::test_impl()
template<class ValueTraits> template<class ValueTraits>
void test_unordered_multiset<ValueTraits>::test_sort(std::vector<typename ValueTraits::value_type>& values) void test_unordered_multiset<ValueTraits>::test_sort(std::vector<typename ValueTraits::value_type>& values)
{ {
typedef typename ValueTraits::value_type testvalue_t; typedef typename ValueTraits::value_type value_type;
typedef boost::intrusive::unordered_multiset typedef unordered_multiset
<ValueTraits <value_type
,boost::hash<typename ValueTraits::value_type> , value_traits<ValueTraits>
,std::equal_to<typename ValueTraits::value_type> , constant_time_size<value_type::constant_time_size>
,ValueTraits::value_type::constant_time_size, std::size_t
> unordered_multiset_type; > 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 buckets [BucketSize];
unordered_multiset_type testset1(buckets, BucketSize, values.begin(), values.end()); unordered_multiset_type testset1(values.begin(), values.end(), bucket_traits(buckets, BucketSize));
{ int init_values [] = { 1, 2, 2, 3, 4, 5 }; { int init_values [] = { 1, 2, 2, 3, 4, 5 };
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); } TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
@ -126,16 +130,16 @@ void test_unordered_multiset<ValueTraits>::test_sort(std::vector<typename ValueT
template<class ValueTraits> template<class ValueTraits>
void test_unordered_multiset<ValueTraits>::test_insert(std::vector<typename ValueTraits::value_type>& values) void test_unordered_multiset<ValueTraits>::test_insert(std::vector<typename ValueTraits::value_type>& values)
{ {
typedef typename ValueTraits::value_type testvalue_t; typedef typename ValueTraits::value_type value_type;
typedef boost::intrusive::unordered_multiset typedef unordered_multiset
<ValueTraits <value_type
,boost::hash<typename ValueTraits::value_type> , value_traits<ValueTraits>
,std::equal_to<typename ValueTraits::value_type> , constant_time_size<value_type::constant_time_size>
,ValueTraits::value_type::constant_time_size, std::size_t
> unordered_multiset_type; > 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 buckets [BucketSize];
unordered_multiset_type testset(buckets, BucketSize); unordered_multiset_type testset(bucket_traits(buckets, BucketSize));
typedef typename unordered_multiset_type::value_type value_type;
testset.insert(&values[0] + 2, &values[0] + 5); testset.insert(&values[0] + 2, &values[0] + 5);
@ -170,7 +174,7 @@ void test_unordered_multiset<ValueTraits>::test_insert(std::vector<typename Valu
//Now with a single bucket //Now with a single bucket
typename unordered_multiset_type::bucket_type single_bucket[1]; typename unordered_multiset_type::bucket_type single_bucket[1];
unordered_multiset_type testset2(single_bucket, 1); unordered_multiset_type testset2(bucket_traits(single_bucket, 1));
testset2.insert(&values[0], &values[0] + values.size()); testset2.insert(&values[0], &values[0] + values.size());
BOOST_TEST (testset2.erase(5) == 1); BOOST_TEST (testset2.erase(5) == 1);
BOOST_TEST (testset2.erase(2) == 2); BOOST_TEST (testset2.erase(2) == 2);
@ -184,18 +188,18 @@ void test_unordered_multiset<ValueTraits>::test_insert(std::vector<typename Valu
template<class ValueTraits> template<class ValueTraits>
void test_unordered_multiset<ValueTraits>::test_swap(std::vector<typename ValueTraits::value_type>& values) void test_unordered_multiset<ValueTraits>::test_swap(std::vector<typename ValueTraits::value_type>& values)
{ {
typedef typename ValueTraits::value_type testvalue_t; typedef typename ValueTraits::value_type value_type;
typedef boost::intrusive::unordered_multiset typedef unordered_multiset
<ValueTraits <value_type
,boost::hash<typename ValueTraits::value_type> , value_traits<ValueTraits>
,std::equal_to<typename ValueTraits::value_type> , constant_time_size<value_type::constant_time_size>
,ValueTraits::value_type::constant_time_size, std::size_t
> unordered_multiset_type; > unordered_multiset_type;
typename unordered_multiset_type::bucket_type buckets [BucketSize]; typedef typename unordered_multiset_type::bucket_traits bucket_traits;
unordered_multiset_type testset1(buckets, BucketSize, &values[0], &values[0] + 2);
typename unordered_multiset_type::bucket_type buckets [BucketSize];
typename unordered_multiset_type::bucket_type buckets2 [BucketSize]; typename unordered_multiset_type::bucket_type buckets2 [BucketSize];
unordered_multiset_type testset2(buckets2, BucketSize); unordered_multiset_type testset1(&values[0], &values[0] + 2, bucket_traits(buckets, BucketSize));
unordered_multiset_type testset2(bucket_traits(buckets2, BucketSize));
testset2.insert (&values[0] + 2, &values[0] + 6); testset2.insert (&values[0] + 2, &values[0] + 6);
testset1.swap (testset2); testset1.swap (testset2);
@ -216,40 +220,41 @@ void test_unordered_multiset<ValueTraits>::test_swap(std::vector<typename ValueT
template<class ValueTraits> template<class ValueTraits>
void test_unordered_multiset<ValueTraits>::test_rehash(std::vector<typename ValueTraits::value_type>& values) void test_unordered_multiset<ValueTraits>::test_rehash(std::vector<typename ValueTraits::value_type>& values)
{ {
typedef typename ValueTraits::value_type testvalue_t; typedef typename ValueTraits::value_type value_type;
typedef boost::intrusive::unordered_multiset typedef unordered_multiset
<ValueTraits <value_type
,boost::hash<typename ValueTraits::value_type> , value_traits<ValueTraits>
,std::equal_to<typename ValueTraits::value_type> , constant_time_size<value_type::constant_time_size>
,ValueTraits::value_type::constant_time_size, std::size_t
> unordered_multiset_type; > unordered_multiset_type;
typedef typename unordered_multiset_type::bucket_traits bucket_traits;
typename unordered_multiset_type::bucket_type buckets1 [BucketSize]; typename unordered_multiset_type::bucket_type buckets1 [BucketSize];
unordered_multiset_type testset1(buckets1, BucketSize, &values[0], &values[0] + 6); typename unordered_multiset_type::bucket_type buckets2 [2];
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() == 6);
{ int init_values [] = { 1, 2, 2, 3, 4, 5 }; { int init_values [] = { 1, 2, 2, 3, 4, 5 };
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); } TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
typename unordered_multiset_type::bucket_type buckets2 [2]; testset1.rehash(bucket_traits(buckets2, 2));
testset1.rehash(buckets2, 2);
BOOST_TEST (testset1.size() == 6); BOOST_TEST (testset1.size() == 6);
{ int init_values [] = { 4, 2, 2, 5, 3, 1 }; { int init_values [] = { 4, 2, 2, 5, 3, 1 };
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); } TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
typename unordered_multiset_type::bucket_type buckets3 [BucketSize*2]; testset1.rehash(bucket_traits(buckets3, BucketSize*2));
testset1.rehash(buckets3, BucketSize*2);
BOOST_TEST (testset1.size() == 6); BOOST_TEST (testset1.size() == 6);
{ int init_values [] = { 1, 2, 2, 3, 4, 5 }; { int init_values [] = { 1, 2, 2, 3, 4, 5 };
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); } TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
//Now rehash reducing the buckets //Now rehash reducing the buckets
testset1.rehash(buckets3, 2); testset1.rehash(bucket_traits(buckets3, 2));
BOOST_TEST (testset1.size() == 6); BOOST_TEST (testset1.size() == 6);
{ int init_values [] = { 4, 2, 2, 5, 3, 1 }; { int init_values [] = { 4, 2, 2, 5, 3, 1 };
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); } TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
//Now rehash increasing the buckets //Now rehash increasing the buckets
testset1.rehash(buckets3, BucketSize*2); testset1.rehash(bucket_traits(buckets3, BucketSize*2));
BOOST_TEST (testset1.size() == 6); BOOST_TEST (testset1.size() == 6);
{ int init_values [] = { 1, 2, 2, 3, 4, 5 }; { int init_values [] = { 1, 2, 2, 3, 4, 5 };
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); } TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
@ -259,19 +264,20 @@ void test_unordered_multiset<ValueTraits>::test_rehash(std::vector<typename Valu
template<class ValueTraits> template<class ValueTraits>
void test_unordered_multiset<ValueTraits>::test_find(std::vector<typename ValueTraits::value_type>& values) void test_unordered_multiset<ValueTraits>::test_find(std::vector<typename ValueTraits::value_type>& values)
{ {
typedef typename ValueTraits::value_type testvalue_t; typedef typename ValueTraits::value_type value_type;
typedef boost::intrusive::unordered_multiset typedef unordered_multiset
<ValueTraits <value_type
,boost::hash<typename ValueTraits::value_type> , value_traits<ValueTraits>
,std::equal_to<typename ValueTraits::value_type> , constant_time_size<value_type::constant_time_size>
,ValueTraits::value_type::constant_time_size, std::size_t
> unordered_multiset_type; > 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 buckets[BucketSize];
unordered_multiset_type testset(buckets, BucketSize, values.begin(), values.end()); unordered_multiset_type testset(values.begin(), values.end(), bucket_traits(buckets, BucketSize));
typedef typename unordered_multiset_type::iterator iterator; typedef typename unordered_multiset_type::iterator iterator;
testvalue_t cmp_val; value_type cmp_val;
cmp_val.value_ = 2; cmp_val.value_ = 2;
iterator i = testset.find (cmp_val); iterator i = testset.find (cmp_val);
BOOST_TEST (i->value_ == 2); BOOST_TEST (i->value_ == 2);
@ -291,61 +297,62 @@ template<class ValueTraits>
void test_unordered_multiset<ValueTraits> void test_unordered_multiset<ValueTraits>
::test_clone(std::vector<typename ValueTraits::value_type>& values) ::test_clone(std::vector<typename ValueTraits::value_type>& values)
{ {
typedef boost::intrusive::unordered_multiset typedef typename ValueTraits::value_type value_type;
<ValueTraits typedef unordered_multiset
,boost::hash<typename ValueTraits::value_type> <value_type
,std::equal_to<typename ValueTraits::value_type> , value_traits<ValueTraits>
,ValueTraits::value_type::constant_time_size, std::size_t , constant_time_size<value_type::constant_time_size>
> unordered_multiset_type; > unordered_multiset_type;
typedef typename unordered_multiset_type::bucket_traits bucket_traits;
{ {
//Test with equal bucket arrays //Test with equal bucket arrays
typename unordered_multiset_type::bucket_type buckets1 [BucketSize]; typename unordered_multiset_type::bucket_type buckets1 [BucketSize];
typename unordered_multiset_type::bucket_type buckets2 [BucketSize]; typename unordered_multiset_type::bucket_type buckets2 [BucketSize];
unordered_multiset_type testset1 (buckets1, BucketSize, values.begin(), values.end()); unordered_multiset_type testset1 (values.begin(), values.end(), bucket_traits(buckets1, BucketSize));
unordered_multiset_type testset2 (buckets2, BucketSize); unordered_multiset_type testset2 (bucket_traits(buckets2, BucketSize));
testset2.clone_from(testset1, test::new_cloner(), test::delete_disposer()); 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 guarantee in the cloning so insert data in a set and test
std::multiset<typename ValueTraits::value_type> std::multiset<typename ValueTraits::value_type>
src(testset1.begin(), testset1.end()); src(testset1.begin(), testset1.end());
std::multiset<typename ValueTraits::value_type> std::multiset<typename ValueTraits::value_type>
dst(testset2.begin(), testset2.end()); dst(testset2.begin(), testset2.end());
BOOST_TEST (src == dst); BOOST_TEST (src == dst);
testset2.clear_and_dispose(test::delete_disposer()); testset2.clear_and_dispose(test::delete_disposer<value_type>());
BOOST_TEST (testset2.empty()); BOOST_TEST (testset2.empty());
} }
{ {
//Test with bigger source bucket arrays //Test with bigger source bucket arrays
typename unordered_multiset_type::bucket_type buckets1 [BucketSize*2]; typename unordered_multiset_type::bucket_type buckets1 [BucketSize*2];
typename unordered_multiset_type::bucket_type buckets2 [BucketSize]; typename unordered_multiset_type::bucket_type buckets2 [BucketSize];
unordered_multiset_type testset1 (buckets1, BucketSize*2, values.begin(), values.end()); unordered_multiset_type testset1 (values.begin(), values.end(), bucket_traits(buckets1, BucketSize*2));
unordered_multiset_type testset2 (buckets2, BucketSize); unordered_multiset_type testset2 (bucket_traits(buckets2, BucketSize));
testset2.clone_from(testset1, test::new_cloner(), test::delete_disposer()); 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 guarantee in the cloning so insert data in a set and test
std::multiset<typename ValueTraits::value_type> std::multiset<typename ValueTraits::value_type>
src(testset1.begin(), testset1.end()); src(testset1.begin(), testset1.end());
std::multiset<typename ValueTraits::value_type> std::multiset<typename ValueTraits::value_type>
dst(testset2.begin(), testset2.end()); dst(testset2.begin(), testset2.end());
BOOST_TEST (src == dst); BOOST_TEST (src == dst);
testset2.clear_and_dispose(test::delete_disposer()); testset2.clear_and_dispose(test::delete_disposer<value_type>());
BOOST_TEST (testset2.empty()); BOOST_TEST (testset2.empty());
} }
{ {
//Test with smaller source bucket arrays //Test with smaller source bucket arrays
typename unordered_multiset_type::bucket_type buckets1 [BucketSize]; typename unordered_multiset_type::bucket_type buckets1 [BucketSize];
typename unordered_multiset_type::bucket_type buckets2 [BucketSize*2]; typename unordered_multiset_type::bucket_type buckets2 [BucketSize*2];
unordered_multiset_type testset1 (buckets1, BucketSize, values.begin(), values.end()); unordered_multiset_type testset1 (values.begin(), values.end(), bucket_traits(buckets1, BucketSize));
unordered_multiset_type testset2 (buckets2, BucketSize*2); unordered_multiset_type testset2 (bucket_traits(buckets2, BucketSize*2));
testset2.clone_from(testset1, test::new_cloner(), test::delete_disposer()); 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 guarantee in the cloning so insert data in a set and test
std::multiset<typename ValueTraits::value_type> std::multiset<typename ValueTraits::value_type>
src(testset1.begin(), testset1.end()); src(testset1.begin(), testset1.end());
std::multiset<typename ValueTraits::value_type> std::multiset<typename ValueTraits::value_type>
dst(testset2.begin(), testset2.end()); dst(testset2.begin(), testset2.end());
BOOST_TEST (src == dst); BOOST_TEST (src == dst);
testset2.clear_and_dispose(test::delete_disposer()); testset2.clear_and_dispose(test::delete_disposer<value_type>());
BOOST_TEST (testset2.empty()); BOOST_TEST (testset2.empty());
} }
} }
@ -356,17 +363,26 @@ class test_main_template
public: public:
int operator()() int operator()()
{ {
typedef testvalue<VoidPointer, constant_time_size> testvalue_t; typedef testvalue<VoidPointer, constant_time_size> value_type;
static const int random_init[6] = { 3, 2, 4, 1, 5, 2 }; static const int random_init[6] = { 3, 2, 4, 1, 5, 2 };
std::vector<testvalue<VoidPointer, constant_time_size> > data (6); std::vector<testvalue<VoidPointer, constant_time_size> > data (6);
for (int i = 0; i < 6; ++i) for (int i = 0; i < 6; ++i)
data[i].value_ = random_init[i]; data[i].value_ = random_init[i];
test_unordered_multiset <typename testvalue_t::unordered_set_base_hook_t::template test_unordered_multiset < typename detail::get_base_value_traits
value_traits<testvalue_t> >::test_all(data); < value_type
, typename value_type::unordered_set_base_hook_t
>::type
>::test_all(data);
test_unordered_multiset <typename testvalue_t::unordered_set_member_hook_t::template test_unordered_multiset < typename detail::get_member_value_traits
value_traits<testvalue_t, &testvalue_t::unordered_set_node_> >::test_all(data); < value_type
, member_hook< value_type
, typename value_type::unordered_set_member_hook_t
, &value_type::unordered_set_node_
>
>::type
>::test_all(data);
return 0; return 0;
} }
@ -378,87 +394,51 @@ class test_main_template<VoidPointer, false>
public: public:
int operator()() int operator()()
{ {
typedef testvalue<VoidPointer, false> testvalue_t; typedef testvalue<VoidPointer, false> value_type;
static const int random_init[6] = { 3, 2, 4, 1, 5, 2 }; static const int random_init[6] = { 3, 2, 4, 1, 5, 2 };
std::vector<testvalue<VoidPointer, false> > data (6); std::vector<testvalue<VoidPointer, false> > data (6);
for (int i = 0; i < 6; ++i) for (int i = 0; i < 6; ++i)
data[i].value_ = random_init[i]; data[i].value_ = random_init[i];
test_unordered_multiset <typename testvalue_t::unordered_set_base_hook_t::template test_unordered_multiset < typename detail::get_base_value_traits
value_traits<testvalue_t> >::test_all(data); < value_type
, typename value_type::unordered_set_base_hook_t
>::type
>::test_all(data);
test_unordered_multiset <typename testvalue_t::unordered_set_member_hook_t::template test_unordered_multiset < typename detail::get_member_value_traits
value_traits<testvalue_t, &testvalue_t::unordered_set_node_> >::test_all(data); < value_type
, member_hook< value_type
, typename value_type::unordered_set_member_hook_t
, &value_type::unordered_set_node_
>
>::type
>::test_all(data);
test_unordered_multiset <typename testvalue_t::unordered_set_auto_base_hook_t::template test_unordered_multiset < typename detail::get_base_value_traits
value_traits<testvalue_t> >::test_all(data); < value_type
, typename value_type::unordered_set_auto_base_hook_t
>::type
>::test_all(data);
test_unordered_multiset <typename testvalue_t::unordered_set_auto_member_hook_t::template test_unordered_multiset < typename detail::get_member_value_traits
value_traits<testvalue_t, &testvalue_t::unordered_set_auto_node_> >::test_all(data); < value_type
, member_hook< value_type
, typename value_type::unordered_set_auto_member_hook_t
, &value_type::unordered_set_auto_node_
>
>::type
>::test_all(data);
return 0; return 0;
} }
}; };
/*
//Explicit instantiations of non-counted classes
template class boost::intrusive::unordered_multiset
< unordered_set_base_raw_t
, boost::hash<unordered_set_base_raw_t::value_type>
, std::equal_to<unordered_set_base_raw_t::value_type>, false>;
template class boost::intrusive::unordered_multiset
< unordered_set_member_raw_t
, boost::hash<unordered_set_member_raw_t::value_type>
, std::equal_to<unordered_set_member_raw_t::value_type>, false>;
template class boost::intrusive::unordered_multiset
< unordered_set_auto_base_raw
, boost::hash<unordered_set_auto_base_raw::value_type>
, std::equal_to<unordered_set_auto_base_raw::value_type>, false>;
template class boost::intrusive::unordered_multiset
< unordered_set_auto_member_raw
, boost::hash<unordered_set_auto_member_raw::value_type>
, std::equal_to<unordered_set_auto_member_raw::value_type>, false>;
template class boost::intrusive::unordered_multiset
< unordered_set_base_smart
, boost::hash<unordered_set_base_smart::value_type>
, std::equal_to<unordered_set_base_smart::value_type>, false>;
template class boost::intrusive::unordered_multiset
< unordered_set_member_smart
, boost::hash<unordered_set_member_smart::value_type>
, std::equal_to<unordered_set_member_smart::value_type>, false>;
template class boost::intrusive::unordered_multiset
< unordered_set_auto_base_smart
, boost::hash<unordered_set_auto_base_smart::value_type>
, std::equal_to<unordered_set_auto_base_smart::value_type>, false>;
template class boost::intrusive::unordered_multiset
< unordered_set_auto_member_smart
, boost::hash<unordered_set_auto_member_smart::value_type>
, std::equal_to<unordered_set_auto_member_smart::value_type>, false>;
//Explicit instantiation of counted classes
template class boost::intrusive::unordered_multiset
< unordered_set_base_raw_t
, boost::hash<unordered_set_base_raw_t::value_type>
, std::equal_to<unordered_set_base_raw_t::value_type>, true>;
template class boost::intrusive::unordered_multiset
< unordered_set_member_raw_t
, boost::hash<unordered_set_base_raw_t::value_type>
, std::equal_to<unordered_set_member_raw_t::value_type>, true>;
template class boost::intrusive::unordered_multiset
< unordered_set_base_smart_t
, boost::hash<unordered_set_base_smart_t::value_type>
, std::equal_to<unordered_set_base_smart_t::value_type>, true>;
template class boost::intrusive::unordered_multiset
< unordered_set_member_smart_t
, boost::hash<unordered_set_member_smart_t::value_type>
, std::equal_to<unordered_set_member_smart_t::value_type>, true>;
*/
int main( int, char* [] ) int main( int, char* [] )
{ {
test_main_template<void*, false>()(); test_main_template<void*, false>()();
test_main_template<boost::intrusive::smart_ptr<void>, false>()(); test_main_template<smart_ptr<void>, false>()();
test_main_template<void*, true>()(); test_main_template<void*, true>()();
test_main_template<boost::intrusive::smart_ptr<void>, true>()(); test_main_template<smart_ptr<void>, true>()();
return boost::report_errors(); return boost::report_errors();
} }

View File

@ -43,15 +43,16 @@ struct test_unordered_set
template<class ValueTraits> template<class ValueTraits>
void test_unordered_set<ValueTraits>::test_all(std::vector<typename ValueTraits::value_type>& values) void test_unordered_set<ValueTraits>::test_all(std::vector<typename ValueTraits::value_type>& values)
{ {
typedef boost::intrusive::unordered_set typedef typename ValueTraits::value_type value_type;
<ValueTraits typedef unordered_set
,boost::hash<typename ValueTraits::value_type> <value_type
,std::equal_to<typename ValueTraits::value_type> , value_traits<ValueTraits>
,ValueTraits::value_type::constant_time_size, std::size_t , constant_time_size<value_type::constant_time_size>
> unordered_set_type; > unordered_set_type;
typedef typename unordered_set_type::bucket_traits bucket_traits;
{ {
typename unordered_set_type::bucket_type buckets [BucketSize]; typename unordered_set_type::bucket_type buckets [BucketSize];
unordered_set_type testset(buckets, BucketSize); unordered_set_type testset(bucket_traits(buckets, BucketSize));
testset.insert(values.begin(), values.end()); testset.insert(values.begin(), values.end());
test::test_container(testset); test::test_container(testset);
testset.clear(); testset.clear();
@ -77,19 +78,20 @@ void test_unordered_set<ValueTraits>::test_all(std::vector<typename ValueTraits:
template<class ValueTraits> template<class ValueTraits>
void test_unordered_set<ValueTraits>::test_impl() void test_unordered_set<ValueTraits>::test_impl()
{ {
typedef typename ValueTraits::value_type testvalue_t; typedef typename ValueTraits::value_type value_type;
std::vector<testvalue_t> values (5); typedef unordered_set
<value_type
, value_traits<ValueTraits>
, constant_time_size<value_type::constant_time_size>
> unordered_set_type;
typedef typename unordered_set_type::bucket_traits bucket_traits;
std::vector<value_type> values (5);
for (int i = 0; i < 5; ++i) for (int i = 0; i < 5; ++i)
values[i].value_ = i; values[i].value_ = i;
typedef boost::intrusive::unordered_set
<ValueTraits
,boost::hash<typename ValueTraits::value_type>
,std::equal_to<typename ValueTraits::value_type>
,ValueTraits::value_type::constant_time_size, std::size_t
> unordered_set_type;
typename unordered_set_type::bucket_type buckets [BucketSize]; typename unordered_set_type::bucket_type buckets [BucketSize];
unordered_set_type testset(buckets, BucketSize); unordered_set_type testset(bucket_traits(buckets, BucketSize));
for (int i = 0; i < 5; ++i) for (int i = 0; i < 5; ++i)
testset.insert (values[i]); testset.insert (values[i]);
@ -104,15 +106,16 @@ void test_unordered_set<ValueTraits>::test_impl()
template<class ValueTraits> template<class ValueTraits>
void test_unordered_set<ValueTraits>::test_sort(std::vector<typename ValueTraits::value_type>& values) void test_unordered_set<ValueTraits>::test_sort(std::vector<typename ValueTraits::value_type>& values)
{ {
typedef typename ValueTraits::value_type testvalue_t; typedef typename ValueTraits::value_type value_type;
typedef boost::intrusive::unordered_set typedef unordered_set
<ValueTraits <value_type
,boost::hash<typename ValueTraits::value_type> , value_traits<ValueTraits>
,std::equal_to<typename ValueTraits::value_type> , constant_time_size<value_type::constant_time_size>
,ValueTraits::value_type::constant_time_size, std::size_t
> unordered_set_type; > unordered_set_type;
typedef typename unordered_set_type::bucket_traits bucket_traits;
typename unordered_set_type::bucket_type buckets [BucketSize]; typename unordered_set_type::bucket_type buckets [BucketSize];
unordered_set_type testset1(buckets, BucketSize, values.begin(), values.end()); unordered_set_type testset1(values.begin(), values.end(), bucket_traits(buckets, BucketSize));
BOOST_TEST (5 == std::distance(testset1.begin(), testset1.end())); BOOST_TEST (5 == std::distance(testset1.begin(), testset1.end()));
{ int init_values [] = { 1, 2, 3, 4, 5 }; { int init_values [] = { 1, 2, 3, 4, 5 };
@ -126,15 +129,16 @@ void test_unordered_set<ValueTraits>::test_sort(std::vector<typename ValueTraits
template<class ValueTraits> template<class ValueTraits>
void test_unordered_set<ValueTraits>::test_insert(std::vector<typename ValueTraits::value_type>& values) void test_unordered_set<ValueTraits>::test_insert(std::vector<typename ValueTraits::value_type>& values)
{ {
typedef typename ValueTraits::value_type testvalue_t; typedef typename ValueTraits::value_type value_type;
typedef boost::intrusive::unordered_set typedef unordered_set
<ValueTraits <value_type
,boost::hash<typename ValueTraits::value_type> , value_traits<ValueTraits>
,std::equal_to<typename ValueTraits::value_type> , constant_time_size<value_type::constant_time_size>
,ValueTraits::value_type::constant_time_size, std::size_t
> unordered_set_type; > unordered_set_type;
typedef typename unordered_set_type::bucket_traits bucket_traits;
typename unordered_set_type::bucket_type buckets [BucketSize]; typename unordered_set_type::bucket_type buckets [BucketSize];
unordered_set_type testset(buckets, BucketSize); unordered_set_type testset(bucket_traits(buckets, BucketSize));
testset.insert(&values[0] + 2, &values[0] + 5); testset.insert(&values[0] + 2, &values[0] + 5);
const unordered_set_type& const_testset = testset; const unordered_set_type& const_testset = testset;
@ -160,19 +164,18 @@ void test_unordered_set<ValueTraits>::test_insert(std::vector<typename ValueTrai
template<class ValueTraits> template<class ValueTraits>
void test_unordered_set<ValueTraits>::test_swap(std::vector<typename ValueTraits::value_type>& values) void test_unordered_set<ValueTraits>::test_swap(std::vector<typename ValueTraits::value_type>& values)
{ {
typedef typename ValueTraits::value_type testvalue_t; typedef typename ValueTraits::value_type value_type;
typedef boost::intrusive::unordered_set typedef unordered_set
<ValueTraits <value_type
,boost::hash<typename ValueTraits::value_type> , value_traits<ValueTraits>
,std::equal_to<typename ValueTraits::value_type> , constant_time_size<value_type::constant_time_size>
,ValueTraits::value_type::constant_time_size, std::size_t
> unordered_set_type; > unordered_set_type;
typedef typename unordered_set_type::bucket_traits bucket_traits;
typename unordered_set_type::bucket_type buckets1 [BucketSize]; typename unordered_set_type::bucket_type buckets1 [BucketSize];
unordered_set_type testset1(buckets1, BucketSize, &values[0], &values[0] + 2);
typename unordered_set_type::bucket_type buckets2 [BucketSize]; typename unordered_set_type::bucket_type buckets2 [BucketSize];
unordered_set_type testset2(buckets2, BucketSize); unordered_set_type testset1(&values[0], &values[0] + 2, bucket_traits(buckets1, BucketSize));
unordered_set_type testset2(bucket_traits(buckets2, BucketSize));
testset2.insert (&values[0] + 2, &values[0] + 6); testset2.insert (&values[0] + 2, &values[0] + 6);
testset1.swap (testset2); testset1.swap (testset2);
@ -192,40 +195,41 @@ void test_unordered_set<ValueTraits>::test_swap(std::vector<typename ValueTraits
template<class ValueTraits> template<class ValueTraits>
void test_unordered_set<ValueTraits>::test_rehash(std::vector<typename ValueTraits::value_type>& values) void test_unordered_set<ValueTraits>::test_rehash(std::vector<typename ValueTraits::value_type>& values)
{ {
typedef typename ValueTraits::value_type testvalue_t; typedef typename ValueTraits::value_type value_type;
typedef boost::intrusive::unordered_set typedef unordered_set
<ValueTraits <value_type
,boost::hash<typename ValueTraits::value_type> , value_traits<ValueTraits>
,std::equal_to<typename ValueTraits::value_type> , constant_time_size<value_type::constant_time_size>
,ValueTraits::value_type::constant_time_size, std::size_t
> unordered_set_type; > unordered_set_type;
typedef typename unordered_set_type::bucket_traits bucket_traits;
typename unordered_set_type::bucket_type buckets1 [BucketSize]; typename unordered_set_type::bucket_type buckets1 [BucketSize];
unordered_set_type testset1(buckets1, BucketSize, &values[0], &values[0] + 6); typename unordered_set_type::bucket_type buckets2 [2];
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() == 5);
{ int init_values [] = { 1, 2, 3, 4, 5 }; { int init_values [] = { 1, 2, 3, 4, 5 };
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); } TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
typename unordered_set_type::bucket_type buckets2 [2]; testset1.rehash(bucket_traits(buckets2, 2));
testset1.rehash(buckets2, 2);
BOOST_TEST (testset1.size() == 5); BOOST_TEST (testset1.size() == 5);
{ int init_values [] = { 4, 2, 5, 3, 1 }; { int init_values [] = { 4, 2, 5, 3, 1 };
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); } TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
typename unordered_set_type::bucket_type buckets3 [BucketSize*2]; testset1.rehash(bucket_traits(buckets3, BucketSize*2));
testset1.rehash(buckets3, BucketSize*2);
BOOST_TEST (testset1.size() == 5); BOOST_TEST (testset1.size() == 5);
{ int init_values [] = { 1, 2, 3, 4, 5 }; { int init_values [] = { 1, 2, 3, 4, 5 };
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); } TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
//Now rehash reducing the buckets //Now rehash reducing the buckets
testset1.rehash(buckets3, 2); testset1.rehash(bucket_traits(buckets3, 2));
BOOST_TEST (testset1.size() == 5); BOOST_TEST (testset1.size() == 5);
{ int init_values [] = { 4, 2, 5, 3, 1 }; { int init_values [] = { 4, 2, 5, 3, 1 };
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); } TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
//Now rehash increasing the buckets //Now rehash increasing the buckets
testset1.rehash(buckets3, BucketSize*2); testset1.rehash(bucket_traits(buckets3, BucketSize*2));
BOOST_TEST (testset1.size() == 5); BOOST_TEST (testset1.size() == 5);
{ int init_values [] = { 1, 2, 3, 4, 5 }; { int init_values [] = { 1, 2, 3, 4, 5 };
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); } TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
@ -236,18 +240,19 @@ void test_unordered_set<ValueTraits>::test_rehash(std::vector<typename ValueTrai
template<class ValueTraits> template<class ValueTraits>
void test_unordered_set<ValueTraits>::test_find(std::vector<typename ValueTraits::value_type>& values) void test_unordered_set<ValueTraits>::test_find(std::vector<typename ValueTraits::value_type>& values)
{ {
typedef typename ValueTraits::value_type testvalue_t; typedef typename ValueTraits::value_type value_type;
typedef boost::intrusive::unordered_set typedef unordered_set
<ValueTraits <value_type
,boost::hash<typename ValueTraits::value_type> , value_traits<ValueTraits>
,std::equal_to<typename ValueTraits::value_type> , constant_time_size<value_type::constant_time_size>
,ValueTraits::value_type::constant_time_size, std::size_t
> unordered_set_type; > unordered_set_type;
typedef typename unordered_set_type::bucket_traits bucket_traits;
typename unordered_set_type::bucket_type buckets [BucketSize]; typename unordered_set_type::bucket_type buckets [BucketSize];
unordered_set_type testset (buckets, BucketSize, values.begin(), values.end()); unordered_set_type testset (values.begin(), values.end(), bucket_traits(buckets, BucketSize));
typedef typename unordered_set_type::iterator iterator; typedef typename unordered_set_type::iterator iterator;
testvalue_t cmp_val; value_type cmp_val;
cmp_val.value_ = 2; cmp_val.value_ = 2;
iterator i = testset.find (cmp_val); iterator i = testset.find (cmp_val);
BOOST_TEST (i->value_ == 2); BOOST_TEST (i->value_ == 2);
@ -266,61 +271,62 @@ template<class ValueTraits>
void test_unordered_set<ValueTraits> void test_unordered_set<ValueTraits>
::test_clone(std::vector<typename ValueTraits::value_type>& values) ::test_clone(std::vector<typename ValueTraits::value_type>& values)
{ {
typedef boost::intrusive::unordered_set typedef typename ValueTraits::value_type value_type;
<ValueTraits typedef unordered_set
,boost::hash<typename ValueTraits::value_type> <value_type
,std::equal_to<typename ValueTraits::value_type> , value_traits<ValueTraits>
,ValueTraits::value_type::constant_time_size, std::size_t , constant_time_size<value_type::constant_time_size>
> unordered_set_type; > unordered_set_type;
typedef typename unordered_set_type::bucket_traits bucket_traits;
{ {
//Test with equal bucket arrays //Test with equal bucket arrays
typename unordered_set_type::bucket_type buckets1 [BucketSize]; typename unordered_set_type::bucket_type buckets1 [BucketSize];
typename unordered_set_type::bucket_type buckets2 [BucketSize]; typename unordered_set_type::bucket_type buckets2 [BucketSize];
unordered_set_type testset1 (buckets1, BucketSize, values.begin(), values.end()); unordered_set_type testset1 (values.begin(), values.end(), bucket_traits(buckets1, BucketSize));
unordered_set_type testset2 (buckets2, BucketSize); unordered_set_type testset2 (bucket_traits(buckets2, BucketSize));
testset2.clone_from(testset1, test::new_cloner(), test::delete_disposer()); 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 guarantee in the cloning so insert data in a set and test
std::set<typename ValueTraits::value_type> std::set<typename ValueTraits::value_type>
src(testset1.begin(), testset1.end()); src(testset1.begin(), testset1.end());
std::set<typename ValueTraits::value_type> std::set<typename ValueTraits::value_type>
dst(testset2.begin(), testset2.end()); dst(testset2.begin(), testset2.end());
BOOST_TEST (src == dst ); BOOST_TEST (src == dst );
testset2.clear_and_dispose(test::delete_disposer()); testset2.clear_and_dispose(test::delete_disposer<value_type>());
BOOST_TEST (testset2.empty()); BOOST_TEST (testset2.empty());
} }
{ {
//Test with bigger source bucket arrays //Test with bigger source bucket arrays
typename unordered_set_type::bucket_type buckets1 [BucketSize*2]; typename unordered_set_type::bucket_type buckets1 [BucketSize*2];
typename unordered_set_type::bucket_type buckets2 [BucketSize]; typename unordered_set_type::bucket_type buckets2 [BucketSize];
unordered_set_type testset1 (buckets1, BucketSize*2, values.begin(), values.end()); unordered_set_type testset1 (values.begin(), values.end(), bucket_traits(buckets1, BucketSize*2));
unordered_set_type testset2 (buckets2, BucketSize); unordered_set_type testset2 (bucket_traits(buckets2, BucketSize));
testset2.clone_from(testset1, test::new_cloner(), test::delete_disposer()); 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 guarantee in the cloning so insert data in a set and test
std::set<typename ValueTraits::value_type> std::set<typename ValueTraits::value_type>
src(testset1.begin(), testset1.end()); src(testset1.begin(), testset1.end());
std::set<typename ValueTraits::value_type> std::set<typename ValueTraits::value_type>
dst(testset2.begin(), testset2.end()); dst(testset2.begin(), testset2.end());
BOOST_TEST (src == dst ); BOOST_TEST (src == dst );
testset2.clear_and_dispose(test::delete_disposer()); testset2.clear_and_dispose(test::delete_disposer<value_type>());
BOOST_TEST (testset2.empty()); BOOST_TEST (testset2.empty());
} }
{ {
//Test with smaller source bucket arrays //Test with smaller source bucket arrays
typename unordered_set_type::bucket_type buckets1 [BucketSize]; typename unordered_set_type::bucket_type buckets1 [BucketSize];
typename unordered_set_type::bucket_type buckets2 [BucketSize*2]; typename unordered_set_type::bucket_type buckets2 [BucketSize*2];
unordered_set_type testset1 (buckets1, BucketSize, values.begin(), values.end()); unordered_set_type testset1 (values.begin(), values.end(), bucket_traits(buckets1, BucketSize));
unordered_set_type testset2 (buckets2, BucketSize*2); unordered_set_type testset2 (bucket_traits(buckets2, BucketSize*2));
testset2.clone_from(testset1, test::new_cloner(), test::delete_disposer()); 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 guarantee in the cloning so insert data in a set and test
std::set<typename ValueTraits::value_type> std::set<typename ValueTraits::value_type>
src(testset1.begin(), testset1.end()); src(testset1.begin(), testset1.end());
std::set<typename ValueTraits::value_type> std::set<typename ValueTraits::value_type>
dst(testset2.begin(), testset2.end()); dst(testset2.begin(), testset2.end());
BOOST_TEST (src == dst ); BOOST_TEST (src == dst );
testset2.clear_and_dispose(test::delete_disposer()); testset2.clear_and_dispose(test::delete_disposer<value_type>());
BOOST_TEST (testset2.empty()); BOOST_TEST (testset2.empty());
} }
} }
@ -331,17 +337,25 @@ class test_main_template
public: public:
int operator()() int operator()()
{ {
typedef testvalue<VoidPointer, constant_time_size> testvalue_t; typedef testvalue<VoidPointer, constant_time_size> value_type;
static const int random_init[6] = { 3, 2, 4, 1, 5, 2 }; static const int random_init[6] = { 3, 2, 4, 1, 5, 2 };
std::vector<testvalue<VoidPointer, constant_time_size> > data (6); std::vector<testvalue<VoidPointer, constant_time_size> > data (6);
for (int i = 0; i < 6; ++i) for (int i = 0; i < 6; ++i)
data[i].value_ = random_init[i]; data[i].value_ = random_init[i];
test_unordered_set <typename testvalue_t::unordered_set_base_hook_t::template test_unordered_set < typename detail::get_base_value_traits
value_traits<testvalue_t> >::test_all(data); < value_type
, typename value_type::unordered_set_base_hook_t
test_unordered_set <typename testvalue_t::unordered_set_member_hook_t::template >::type
value_traits<testvalue_t, &testvalue_t::unordered_set_node_> >::test_all(data); >::test_all(data);
test_unordered_set < typename detail::get_member_value_traits
< value_type
, member_hook< value_type
, typename value_type::unordered_set_member_hook_t
, &value_type::unordered_set_node_
>
>::type
>::test_all(data);
return 0; return 0;
} }
@ -353,84 +367,51 @@ class test_main_template<VoidPointer, false>
public: public:
int operator()() int operator()()
{ {
typedef testvalue<VoidPointer, false> testvalue_t; typedef testvalue<VoidPointer, false> value_type;
static const int random_init[6] = { 3, 2, 4, 1, 5, 2 }; static const int random_init[6] = { 3, 2, 4, 1, 5, 2 };
std::vector<testvalue<VoidPointer, false> > data (6); std::vector<testvalue<VoidPointer, false> > data (6);
for (int i = 0; i < 6; ++i) for (int i = 0; i < 6; ++i)
data[i].value_ = random_init[i]; data[i].value_ = random_init[i];
test_unordered_set <typename testvalue_t::unordered_set_base_hook_t::template test_unordered_set < typename detail::get_base_value_traits
value_traits<testvalue_t> >::test_all(data); < value_type
, typename value_type::unordered_set_base_hook_t
>::type
>::test_all(data);
test_unordered_set <typename testvalue_t::unordered_set_member_hook_t::template test_unordered_set < typename detail::get_member_value_traits
value_traits<testvalue_t, &testvalue_t::unordered_set_node_> >::test_all(data); < value_type
, member_hook< value_type
, typename value_type::unordered_set_member_hook_t
, &value_type::unordered_set_node_
>
>::type
>::test_all(data);
test_unordered_set <typename testvalue_t::unordered_set_auto_base_hook_t::template test_unordered_set < typename detail::get_base_value_traits
value_traits<testvalue_t> >::test_all(data); < value_type
, typename value_type::unordered_set_auto_base_hook_t
>::type
>::test_all(data);
test_unordered_set <typename testvalue_t::unordered_set_auto_member_hook_t::template test_unordered_set < typename detail::get_member_value_traits
value_traits<testvalue_t, &testvalue_t::unordered_set_auto_node_> >::test_all(data); < value_type
, member_hook< value_type
, typename value_type::unordered_set_auto_member_hook_t
, &value_type::unordered_set_auto_node_
>
>::type
>::test_all(data);
return 0; return 0;
} }
}; };
/*
template class boost::intrusive::unordered_set
< unordered_set_base_raw_t
, boost::hash<unordered_set_base_raw_t::value_type>
, std::equal_to<unordered_set_base_raw_t::value_type>, false>;
template class boost::intrusive::unordered_set
< unordered_set_member_raw_t
, boost::hash<unordered_set_member_raw_t::value_type>
, std::equal_to<unordered_set_member_raw_t::value_type>, false>;
template class boost::intrusive::unordered_set
< unordered_set_auto_base_raw
, boost::hash<unordered_set_auto_base_raw::value_type>
, std::equal_to<unordered_set_auto_base_raw::value_type>, false>;
template class boost::intrusive::unordered_set
< unordered_set_auto_member_raw
, boost::hash<unordered_set_auto_member_raw::value_type>
, std::equal_to<unordered_set_auto_member_raw::value_type>, false>;
template class boost::intrusive::unordered_set
< unordered_set_base_smart
, boost::hash<unordered_set_base_smart::value_type>
, std::equal_to<unordered_set_base_smart::value_type>, false>;
template class boost::intrusive::unordered_set
< unordered_set_member_smart
, boost::hash<unordered_set_member_smart::value_type>
, std::equal_to<unordered_set_member_smart::value_type>, false>;
template class boost::intrusive::unordered_set
< unordered_set_auto_base_smart
, boost::hash<unordered_set_auto_base_smart::value_type>
, std::equal_to<unordered_set_auto_base_smart::value_type>, false>;
template class boost::intrusive::unordered_set
< unordered_set_auto_member_smart
, boost::hash<unordered_set_auto_member_smart::value_type>
, std::equal_to<unordered_set_auto_member_smart::value_type>, false>;
//Explicit instantiation of counted classes
template class boost::intrusive::unordered_set
< unordered_set_base_raw_t
, boost::hash<unordered_set_base_raw_t::value_type>
, std::equal_to<unordered_set_base_raw_t::value_type>, true>;
template class boost::intrusive::unordered_set
< unordered_set_member_raw_t
, boost::hash<unordered_set_base_raw_t::value_type>
, std::equal_to<unordered_set_member_raw_t::value_type>, true>;
template class boost::intrusive::unordered_set
< unordered_set_base_smart_t
, boost::hash<unordered_set_base_smart_t::value_type>
, std::equal_to<unordered_set_base_smart_t::value_type>, true>;
template class boost::intrusive::unordered_set
< unordered_set_member_smart_t
, boost::hash<unordered_set_member_smart_t::value_type>
, std::equal_to<unordered_set_member_smart_t::value_type>, true>;
*/
int main( int, char* [] ) int main( int, char* [] )
{ {
test_main_template<void*, false>()(); test_main_template<void*, false>()();
test_main_template<boost::intrusive::smart_ptr<void>, false>()(); test_main_template<smart_ptr<void>, false>()();
test_main_template<void*, true>()(); test_main_template<void*, true>()();
test_main_template<boost::intrusive::smart_ptr<void>, true>()(); test_main_template<smart_ptr<void>, true>()();
return boost::report_errors(); return boost::report_errors();
} }
#include <boost/intrusive/detail/config_end.hpp> #include <boost/intrusive/detail/config_end.hpp>

View File

@ -0,0 +1,85 @@
/////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2007
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/intrusive for documentation.
//
/////////////////////////////////////////////////////////////////////////////
#include <boost/intrusive/list.hpp>
#include <boost/intrusive/slist.hpp>
#include <boost/intrusive/set.hpp>
#include <boost/intrusive/unordered_set.hpp>
#include <vector>
using namespace boost::intrusive;
struct VirtualBase
{
virtual ~VirtualBase(){}
};
struct VirtualBase2
{
virtual ~VirtualBase2(){}
};
struct VirtualBase3
{
};
class NonVirtualBase
: public virtual VirtualBase
, public virtual VirtualBase2
{
public:
int dummy[10];
};
class MyClass
: public NonVirtualBase
, public virtual VirtualBase3
{
int int_;
public:
list_member_hook<> list_hook_;
MyClass(int i = 0)
: int_(i)
{}
};
//Define a list that will store MyClass using the public base hook
typedef member_hook< MyClass, list_member_hook<>, &MyClass::list_hook_ > MemberHook;
typedef list<MyClass, MemberHook> List;
int main()
{
typedef std::vector<MyClass>::iterator VectIt;
typedef std::vector<MyClass>::reverse_iterator VectRit;
//Create several MyClass objects, each one with a different value
std::vector<MyClass> values;
for(int i = 0; i < 100; ++i) values.push_back(MyClass(i));
List my_list;
//Now insert them in the reverse order
//in the base hook intrusive list
for(VectIt it(values.begin()), itend(values.end()); it != itend; ++it)
my_list.push_front(*it);
//Now test lists
{
List::const_iterator list_it(my_list.cbegin());
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)
if(&*list_it != &*vect_it) return 1;
}
return 0;
}