forked from boostorg/intrusive
Full merge from trunk at revision 41356 of entire boost-root tree.
[SVN r41370]
This commit is contained in:
@@ -0,0 +1,34 @@
|
||||
# Boost Intrusive Library Example Jamfile
|
||||
|
||||
# (C) Copyright Ion Gaztañaga 2006-2007.
|
||||
# Use, modification and distribution are subject to 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)
|
||||
|
||||
# Adapted from John Maddock's TR1 Jamfile.v2
|
||||
# Copyright John Maddock 2005.
|
||||
# Use, modification and distribution are subject to 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)
|
||||
|
||||
# this rule enumerates through all the sources and invokes
|
||||
# the run rule for each source, the result is a list of all
|
||||
# the run rules, which we can pass on to the test_suite rule:
|
||||
|
||||
rule test_all
|
||||
{
|
||||
local all_rules = ;
|
||||
|
||||
for local fileb in [ glob *.cpp ]
|
||||
{
|
||||
all_rules += [ run $(fileb) /boost/thread//boost_thread
|
||||
: # additional args
|
||||
: # test-files
|
||||
: # requirements
|
||||
] ;
|
||||
}
|
||||
|
||||
return $(all_rules) ;
|
||||
}
|
||||
|
||||
test-suite intrusive_example : [ test_all r ] : <threading>multi ;
|
||||
@@ -0,0 +1,105 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2006-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_advanced_value_traits_code
|
||||
#include <boost/intrusive/link_mode.hpp>
|
||||
#include <boost/intrusive/list.hpp>
|
||||
#include <vector>
|
||||
|
||||
//This is the node that will be used with algorithms.
|
||||
struct simple_node
|
||||
{
|
||||
simple_node *prev_;
|
||||
simple_node *next_;
|
||||
};
|
||||
//]
|
||||
|
||||
//[doc_advanced_value_traits_value_traits
|
||||
class base_1{};
|
||||
class base_2{};
|
||||
|
||||
struct value_1 : public base_1, public simple_node
|
||||
{ int id_; };
|
||||
|
||||
struct value_2 : public base_1, public base_2, public simple_node
|
||||
{ float id_; };
|
||||
|
||||
//Define the node traits. A single node_traits will be enough.
|
||||
struct simple_node_traits
|
||||
{
|
||||
typedef simple_node node;
|
||||
typedef node * node_ptr;
|
||||
typedef const node * const_node_ptr;
|
||||
static node *get_next(const node *n) { return n->next_; }
|
||||
static void set_next(node *n, node *next) { n->next_ = next; }
|
||||
static node *get_previous(const node *n) { return n->prev_; }
|
||||
static void set_previous(node *n, node *prev) { n->prev_ = prev; }
|
||||
};
|
||||
|
||||
//A templatized value traits for value_1 and value_2
|
||||
template<class ValueType>
|
||||
struct simple_value_traits
|
||||
{
|
||||
typedef simple_node_traits node_traits;
|
||||
typedef node_traits::node_ptr node_ptr;
|
||||
typedef node_traits::const_node_ptr const_node_ptr;
|
||||
typedef ValueType value_type;
|
||||
typedef ValueType * pointer;
|
||||
typedef const ValueType * const_pointer;
|
||||
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 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); }
|
||||
};
|
||||
//]
|
||||
|
||||
//[doc_advanced_value_traits_containers
|
||||
//Now define two intrusive lists. Both lists will use the same algorithms:
|
||||
// circular_list_algorithms<simple_node_traits>
|
||||
|
||||
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
|
||||
int main()
|
||||
{
|
||||
typedef std::vector<value_1> Vect1;
|
||||
typedef std::vector<value_2> Vect2;
|
||||
|
||||
//Create values, with a different internal number
|
||||
Vect1 values1;
|
||||
Vect2 values2;
|
||||
for(int i = 0; i < 100; ++i){
|
||||
value_1 v1; v1.id_ = i; values1.push_back(v1);
|
||||
value_2 v2; v2.id_ = (float)i; values2.push_back(v2);
|
||||
}
|
||||
|
||||
//Create the lists with the objects
|
||||
Value1List list1(values1.begin(), values1.end());
|
||||
Value2List list2(values2.begin(), values2.end());
|
||||
|
||||
//Now test both lists
|
||||
Value1List::const_iterator bit1(list1.begin()), bitend1(list1.end());
|
||||
Value2List::const_iterator bit2(list2.begin()), bitend2(list2.end());
|
||||
|
||||
Vect1::const_iterator it1(values1.begin()), itend1(values1.end());
|
||||
Vect2::const_iterator it2(values2.begin()), itend2(values2.end());
|
||||
|
||||
//Test the objects inserted in our lists
|
||||
for(; it1 != itend1; ++it1, ++bit1, ++it2, ++bit2){
|
||||
if(&*bit1 != &*it1 || &*bit2 != &*it2) return false;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
//]
|
||||
@@ -0,0 +1,95 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2006-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/link_mode.hpp>
|
||||
#include <boost/intrusive/list.hpp>
|
||||
#include <boost/intrusive/member_value_traits.hpp>
|
||||
#include <vector>
|
||||
|
||||
struct simple_node
|
||||
{
|
||||
simple_node *prev_;
|
||||
simple_node *next_;
|
||||
};
|
||||
|
||||
//Define the node traits. A single node_traits will be enough.
|
||||
struct simple_node_traits
|
||||
{
|
||||
typedef simple_node node;
|
||||
typedef node * node_ptr;
|
||||
typedef const node * const_node_ptr;
|
||||
static node *get_next(const node *n) { return n->next_; }
|
||||
static void set_next(node *n, node *next) { n->next_ = next; }
|
||||
static node *get_previous(const node *n) { return n->prev_; }
|
||||
static void set_previous(node *n, node *prev) { n->prev_ = prev; }
|
||||
};
|
||||
|
||||
//[doc_advanced_value_traits2_value_traits
|
||||
class base_1{};
|
||||
class base_2{};
|
||||
|
||||
struct value_1 : public base_1, public simple_node
|
||||
{
|
||||
int id_;
|
||||
simple_node node_;
|
||||
};
|
||||
|
||||
struct value_2 : public base_1, public base_2, public simple_node
|
||||
{
|
||||
simple_node node_;
|
||||
float id_;
|
||||
};
|
||||
|
||||
using namespace boost::intrusive;
|
||||
|
||||
typedef member_value_traits
|
||||
<value_1, simple_node_traits, &value_1::node_, normal_link> ValueTraits1;
|
||||
typedef member_value_traits
|
||||
<value_2, simple_node_traits, &value_2::node_, normal_link> ValueTraits2;
|
||||
|
||||
//Now define two intrusive lists. Both lists will use the same algorithms:
|
||||
// circular_list_algorithms<simple_node_traits>
|
||||
typedef list <value_1, value_traits<ValueTraits1> > Value1List;
|
||||
typedef list <value_2, value_traits<ValueTraits2> > Value2List;
|
||||
//]
|
||||
|
||||
//[doc_advanced_value_traits2_test
|
||||
int main()
|
||||
{
|
||||
typedef std::vector<value_1> Vect1;
|
||||
typedef std::vector<value_2> Vect2;
|
||||
|
||||
//Create values, with a different internal number
|
||||
Vect1 values1;
|
||||
Vect2 values2;
|
||||
for(int i = 0; i < 100; ++i){
|
||||
value_1 v1; v1.id_ = i; values1.push_back(v1);
|
||||
value_2 v2; v2.id_ = (float)i; values2.push_back(v2);
|
||||
}
|
||||
|
||||
//Create the lists with the objects
|
||||
Value1List list1(values1.begin(), values1.end());
|
||||
Value2List list2(values2.begin(), values2.end());
|
||||
|
||||
//Now test both lists
|
||||
Value1List::const_iterator bit1(list1.begin()), bitend1(list1.end());
|
||||
Value2List::const_iterator bit2(list2.begin()), bitend2(list2.end());
|
||||
|
||||
Vect1::const_iterator it1(values1.begin()), itend1(values1.end());
|
||||
Vect2::const_iterator it2(values2.begin()), itend2(values2.end());
|
||||
|
||||
//Test the objects inserted in our lists
|
||||
for(; it1 != itend1; ++it1, ++bit1, ++it2, ++bit2){
|
||||
if(&*bit1 != &*it1 || &*bit2 != &*it2) return false;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
//]
|
||||
@@ -0,0 +1,260 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2006-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_assoc_optimized_code_normal_find
|
||||
#include <boost/intrusive/set.hpp>
|
||||
#include <boost/intrusive/unordered_set.hpp>
|
||||
#include <cstring>
|
||||
|
||||
using namespace boost::intrusive;
|
||||
|
||||
// Hash function for strings
|
||||
struct StrHasher
|
||||
{
|
||||
std::size_t operator()(const char *str) const
|
||||
{
|
||||
std::size_t seed = 0;
|
||||
for(; *str; ++str) boost::hash_combine(seed, *str);
|
||||
return seed;
|
||||
}
|
||||
};
|
||||
|
||||
class Expensive : public set_base_hook<>, public unordered_set_base_hook<>
|
||||
{
|
||||
std::string key_;
|
||||
// Other members...
|
||||
|
||||
public:
|
||||
Expensive(const char *key)
|
||||
: key_(key)
|
||||
{} //other expensive initializations...
|
||||
|
||||
const std::string & get_key() const
|
||||
{ return key_; }
|
||||
|
||||
friend bool operator < (const Expensive &a, const Expensive &b)
|
||||
{ return a.key_ < b.key_; }
|
||||
|
||||
friend bool operator == (const Expensive &a, const Expensive &b)
|
||||
{ return a.key_ == b.key_; }
|
||||
|
||||
friend std::size_t hash_value(const Expensive &object)
|
||||
{ return StrHasher()(object.get_key().c_str()); }
|
||||
};
|
||||
|
||||
// A set and unordered_set that store Expensive objects
|
||||
typedef set<Expensive> Set;
|
||||
typedef unordered_set<Expensive> UnorderedSet;
|
||||
|
||||
// Search functions
|
||||
Expensive *get_from_set(const char* key, Set &set_object)
|
||||
{
|
||||
Set::iterator it = set_object.find(Expensive(key));
|
||||
if( it == set_object.end() ) return 0;
|
||||
return &*it;
|
||||
}
|
||||
|
||||
Expensive *get_from_uset(const char* key, UnorderedSet &uset_object)
|
||||
{
|
||||
UnorderedSet::iterator it = uset_object.find(Expensive (key));
|
||||
if( it == uset_object.end() ) return 0;
|
||||
return &*it;
|
||||
}
|
||||
//]
|
||||
|
||||
//[doc_assoc_optimized_code_optimized_find
|
||||
// These compare Expensive and a c-string
|
||||
struct StrExpComp
|
||||
{
|
||||
bool operator()(const char *str, const Expensive &c) const
|
||||
{ return std::strcmp(str, c.get_key().c_str()) < 0; }
|
||||
|
||||
bool operator()(const Expensive &c, const char *str) const
|
||||
{ return std::strcmp(c.get_key().c_str(), str) < 0; }
|
||||
};
|
||||
|
||||
struct StrExpEqual
|
||||
{
|
||||
bool operator()(const char *str, const Expensive &c) const
|
||||
{ return std::strcmp(str, c.get_key().c_str()) == 0; }
|
||||
|
||||
bool operator()(const Expensive &c, const char *str) const
|
||||
{ return std::strcmp(c.get_key().c_str(), str) == 0; }
|
||||
};
|
||||
|
||||
// Optimized search functions
|
||||
Expensive *get_from_set_optimized(const char* key, Set &set_object)
|
||||
{
|
||||
Set::iterator it = set_object.find(key, StrExpComp());
|
||||
if( it == set_object.end() ) return 0;
|
||||
return &*it;
|
||||
}
|
||||
|
||||
Expensive *get_from_uset_optimized(const char* key, UnorderedSet &uset_object)
|
||||
{
|
||||
UnorderedSet::iterator it = uset_object.find(key, StrHasher(), StrExpEqual());
|
||||
if( it == uset_object.end() ) return 0;
|
||||
return &*it;
|
||||
}
|
||||
//]
|
||||
|
||||
//[doc_assoc_optimized_code_normal_insert
|
||||
// Insertion functions
|
||||
bool insert_to_set(const char* key, Set &set_object)
|
||||
{
|
||||
Expensive *pobject = new Expensive(key);
|
||||
bool success = set_object.insert(*pobject).second;
|
||||
if(!success) delete pobject;
|
||||
return success;
|
||||
}
|
||||
|
||||
bool insert_to_uset(const char* key, UnorderedSet &uset_object)
|
||||
{
|
||||
Expensive *pobject = new Expensive(key);
|
||||
bool success = uset_object.insert(*pobject).second;
|
||||
if(!success) delete pobject;
|
||||
return success;
|
||||
}
|
||||
//]
|
||||
|
||||
//[doc_assoc_optimized_code_optimized_insert
|
||||
// Optimized insertion functions
|
||||
bool insert_to_set_optimized(const char* key, Set &set_object)
|
||||
{
|
||||
Set::insert_commit_data insert_data;
|
||||
bool success = set_object.insert_check(key, StrExpComp(), insert_data).second;
|
||||
if(success) set_object.insert_commit(*new Expensive(key), insert_data);
|
||||
return success;
|
||||
}
|
||||
|
||||
bool insert_to_uset_optimized(const char* key, UnorderedSet &uset_object)
|
||||
{
|
||||
UnorderedSet::insert_commit_data insert_data;
|
||||
bool success = uset_object.insert_check
|
||||
(key, StrHasher(), StrExpEqual(), insert_data).second;
|
||||
if(success) uset_object.insert_commit(*new Expensive(key), insert_data);
|
||||
return success;
|
||||
}
|
||||
//]
|
||||
|
||||
int main()
|
||||
{
|
||||
Set set;
|
||||
UnorderedSet::bucket_type buckets[10];
|
||||
UnorderedSet unordered_set(UnorderedSet::bucket_traits(buckets, 10));
|
||||
|
||||
const char * const expensive_key
|
||||
= "A long string that avoids small string optimization";
|
||||
|
||||
Expensive value(expensive_key);
|
||||
|
||||
if(get_from_set(expensive_key, set)){
|
||||
return 1;
|
||||
}
|
||||
|
||||
if(get_from_uset(expensive_key, unordered_set)){
|
||||
return 1;
|
||||
}
|
||||
|
||||
if(get_from_set_optimized(expensive_key, set)){
|
||||
return 1;
|
||||
}
|
||||
|
||||
if(get_from_uset_optimized(expensive_key, unordered_set)){
|
||||
return 1;
|
||||
}
|
||||
|
||||
Set::iterator setit = set.insert(value).first;
|
||||
UnorderedSet::iterator unordered_setit = unordered_set.insert(value).first;
|
||||
|
||||
if(!get_from_set(expensive_key, set)){
|
||||
return 1;
|
||||
}
|
||||
|
||||
if(!get_from_uset(expensive_key, unordered_set)){
|
||||
return 1;
|
||||
}
|
||||
|
||||
if(!get_from_set_optimized(expensive_key, set)){
|
||||
return 1;
|
||||
}
|
||||
|
||||
if(!get_from_uset_optimized(expensive_key, unordered_set)){
|
||||
return 1;
|
||||
}
|
||||
|
||||
set.erase(setit);
|
||||
unordered_set.erase(unordered_setit);
|
||||
|
||||
if(!insert_to_set(expensive_key, set)){
|
||||
return 1;
|
||||
}
|
||||
|
||||
if(!insert_to_uset(expensive_key, unordered_set)){
|
||||
return 1;
|
||||
}
|
||||
|
||||
{
|
||||
Expensive *ptr = &*set.begin();
|
||||
set.clear();
|
||||
delete ptr;
|
||||
}
|
||||
|
||||
{
|
||||
Expensive *ptr = &*unordered_set.begin();
|
||||
unordered_set.clear();
|
||||
delete ptr;
|
||||
}
|
||||
|
||||
if(!insert_to_set_optimized(expensive_key, set)){
|
||||
return 1;
|
||||
}
|
||||
|
||||
if(!insert_to_uset_optimized(expensive_key, unordered_set)){
|
||||
return 1;
|
||||
}
|
||||
|
||||
{
|
||||
Expensive *ptr = &*set.begin();
|
||||
set.clear();
|
||||
delete ptr;
|
||||
}
|
||||
|
||||
{
|
||||
Expensive *ptr = &*unordered_set.begin();
|
||||
unordered_set.clear();
|
||||
delete ptr;
|
||||
}
|
||||
|
||||
setit = set.insert(value).first;
|
||||
unordered_setit = unordered_set.insert(value).first;
|
||||
|
||||
if(insert_to_set(expensive_key, set)){
|
||||
return 1;
|
||||
}
|
||||
|
||||
if(insert_to_uset(expensive_key, unordered_set)){
|
||||
return 1;
|
||||
}
|
||||
|
||||
if(insert_to_set_optimized(expensive_key, set)){
|
||||
return 1;
|
||||
}
|
||||
|
||||
if(insert_to_uset_optimized(expensive_key, unordered_set)){
|
||||
return 1;
|
||||
}
|
||||
|
||||
set.erase(value);
|
||||
unordered_set.erase(value);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2006-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_auto_unlink_code
|
||||
#include <boost/intrusive/list.hpp>
|
||||
#include <cassert>
|
||||
|
||||
using namespace boost::intrusive;
|
||||
|
||||
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
|
||||
{
|
||||
int int_;
|
||||
|
||||
public:
|
||||
MyClass(int i = 0) : int_(i) {}
|
||||
void unlink() { auto_unlink_hook::unlink(); }
|
||||
bool is_linked() { return auto_unlink_hook::is_linked(); }
|
||||
};
|
||||
|
||||
//Define a list that will store values using the base hook
|
||||
//The list can't have constant-time size!
|
||||
typedef list< MyClass, constant_time_size<false> > List;
|
||||
|
||||
int main()
|
||||
{
|
||||
//Create the list
|
||||
List l;
|
||||
{
|
||||
//Create myclass and check it's linked
|
||||
MyClass myclass;
|
||||
assert(myclass.is_linked() == false);
|
||||
|
||||
//Insert the object
|
||||
l.push_back(myclass);
|
||||
|
||||
//Check that we have inserted the object
|
||||
assert(l.empty() == false);
|
||||
assert(&l.front() == &myclass);
|
||||
assert(myclass.is_linked() == true);
|
||||
|
||||
//Now myclass' destructor will unlink it
|
||||
//automatically
|
||||
}
|
||||
|
||||
//Check auto-unlink has been executed
|
||||
assert(l.empty() == true);
|
||||
|
||||
{
|
||||
//Now test the unlink() function
|
||||
|
||||
//Create myclass and check it's linked
|
||||
MyClass myclass;
|
||||
assert(myclass.is_linked() == false);
|
||||
|
||||
//Insert the object
|
||||
l.push_back(myclass);
|
||||
|
||||
//Check that we have inserted the object
|
||||
assert(l.empty() == false);
|
||||
assert(&l.front() == &myclass);
|
||||
assert(myclass.is_linked() == true);
|
||||
|
||||
//Now unlink the node
|
||||
myclass.unlink();
|
||||
|
||||
//Check auto-unlink has been executed
|
||||
assert(l.empty() == true);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
//]
|
||||
@@ -0,0 +1,86 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2006-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_avl_set_code
|
||||
#include <boost/intrusive/avl_set.hpp>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
|
||||
using namespace boost::intrusive;
|
||||
|
||||
//This is a base hook optimized for size
|
||||
class MyClass : public avl_set_base_hook<optimize_size<true> >
|
||||
{
|
||||
int int_;
|
||||
|
||||
public:
|
||||
//This is a member hook
|
||||
avl_set_member_hook<> member_hook_;
|
||||
|
||||
MyClass(int i)
|
||||
: int_(i)
|
||||
{}
|
||||
friend bool operator< (const MyClass &a, const MyClass &b)
|
||||
{ return a.int_ < b.int_; }
|
||||
friend bool operator> (const MyClass &a, const MyClass &b)
|
||||
{ return a.int_ > b.int_; }
|
||||
friend bool operator== (const MyClass &a, const MyClass &b)
|
||||
{ return a.int_ < b.int_; }
|
||||
};
|
||||
|
||||
//Define an avl_set using the base hook that will store values in reverse order
|
||||
typedef avl_set< MyClass, compare<std::greater<MyClass> > > BaseSet;
|
||||
|
||||
//Define an multiset using the member hook
|
||||
typedef member_hook<MyClass, avl_set_member_hook<>, &MyClass::member_hook_> MemberOption;
|
||||
typedef avl_multiset< MyClass, MemberOption> MemberMultiset;
|
||||
|
||||
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));
|
||||
|
||||
BaseSet baseset;
|
||||
MemberMultiset membermultiset;
|
||||
|
||||
//Check that size optimization is activated in the base hook
|
||||
assert(sizeof(avl_set_base_hook<optimize_size<true> >) == 3*sizeof(void*));
|
||||
//Check that size optimization is deactivated in the member hook
|
||||
assert(sizeof(avl_set_member_hook<>) > 3*sizeof(void*));
|
||||
|
||||
//Now insert them in the sets
|
||||
for(VectIt it(values.begin()), itend(values.end()); it != itend; ++it){
|
||||
baseset.insert(*it);
|
||||
membermultiset.insert(*it);
|
||||
}
|
||||
|
||||
//Now test avl_sets
|
||||
{
|
||||
BaseSet::reverse_iterator rbit(baseset.rbegin()), rbitend(baseset.rend());
|
||||
MemberMultiset::iterator mit(membermultiset.begin()), mitend(membermultiset.end());
|
||||
VectIt it(values.begin()), itend(values.end());
|
||||
|
||||
//Test the objects inserted in the base hook avl_set
|
||||
for(; it != itend; ++it, ++rbit)
|
||||
if(&*rbit != &*it) return 1;
|
||||
|
||||
//Test the objects inserted in the member hook avl_set
|
||||
for(it = values.begin(); it != itend; ++it, ++mit)
|
||||
if(&*mit != &*it) return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
//]
|
||||
@@ -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.
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//[doc_avltree_algorithms_code
|
||||
#include <boost/intrusive/avltree_algorithms.hpp>
|
||||
#include <cassert>
|
||||
|
||||
struct my_node
|
||||
{
|
||||
my_node(int i = 0)
|
||||
: int_(i)
|
||||
{}
|
||||
my_node *parent_, *left_, *right_;
|
||||
int balance_;
|
||||
//other members
|
||||
int int_;
|
||||
};
|
||||
|
||||
//Define our own avltree_node_traits
|
||||
struct my_avltree_node_traits
|
||||
{
|
||||
typedef my_node node;
|
||||
typedef my_node * node_ptr;
|
||||
typedef const my_node * const_node_ptr;
|
||||
typedef int balance;
|
||||
|
||||
static node_ptr get_parent(const_node_ptr n) { return n->parent_; }
|
||||
static void set_parent(node_ptr n, node_ptr parent){ n->parent_ = parent; }
|
||||
static node_ptr get_left(const_node_ptr n) { return n->left_; }
|
||||
static void set_left(node_ptr n, node_ptr left) { n->left_ = left; }
|
||||
static node_ptr get_right(const_node_ptr n) { return n->right_; }
|
||||
static void set_right(node_ptr n, node_ptr right) { n->right_ = right; }
|
||||
static balance get_balance(const_node_ptr n) { return n->balance_; }
|
||||
static void set_balance(node_ptr n, balance b) { n->balance_ = b; }
|
||||
static balance negative() { return -1; }
|
||||
static balance zero() { return 0; }
|
||||
static balance positive() { return 1; }
|
||||
};
|
||||
|
||||
struct node_ptr_compare
|
||||
{
|
||||
bool operator()(my_node *a, my_node *b)
|
||||
{ return a->int_ < b->int_; }
|
||||
};
|
||||
|
||||
int main()
|
||||
{
|
||||
typedef boost::intrusive::avltree_algorithms<my_avltree_node_traits> algo;
|
||||
my_node header, two(2), three(3);
|
||||
|
||||
//Create an empty avltree container:
|
||||
//"header" will be the header node of the tree
|
||||
algo::init_header(&header);
|
||||
|
||||
//Now insert node "two" in the tree using the sorting functor
|
||||
algo::insert_equal_upper_bound(&header, &two, node_ptr_compare());
|
||||
|
||||
//Now insert node "three" in the tree using the sorting functor
|
||||
algo::insert_equal_lower_bound(&header, &three, node_ptr_compare());
|
||||
|
||||
//Now take the first node (the left node of the header)
|
||||
my_node *n = header.left_;
|
||||
assert(n == &two);
|
||||
|
||||
//Now go to the next node
|
||||
n = algo::next_node(n);
|
||||
assert(n == &three);
|
||||
|
||||
//Erase a node just using a pointer to it
|
||||
algo::unlink(&two);
|
||||
|
||||
//Erase a node using also the header (faster)
|
||||
algo::erase(&header, &three);
|
||||
return 0;
|
||||
}
|
||||
|
||||
//]
|
||||
@@ -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;
|
||||
}
|
||||
//]
|
||||
@@ -0,0 +1,74 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2006-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_clone_from
|
||||
#include <boost/intrusive/list.hpp>
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
|
||||
using namespace boost::intrusive;
|
||||
|
||||
//A class that can be inserted in an intrusive list
|
||||
class my_class : public list_base_hook<>
|
||||
{
|
||||
public:
|
||||
friend bool operator==(const my_class &a, const my_class &b)
|
||||
{ return a.int_ == b.int_; }
|
||||
|
||||
int int_;
|
||||
|
||||
//...
|
||||
};
|
||||
|
||||
//Definition of the intrusive list
|
||||
typedef list<my_class> my_class_list;
|
||||
|
||||
//Cloner object function
|
||||
struct new_cloner
|
||||
{
|
||||
my_class *operator()(const my_class &clone_this)
|
||||
{ return new my_class(clone_this); }
|
||||
};
|
||||
|
||||
//The disposer object function
|
||||
struct delete_disposer
|
||||
{
|
||||
void operator()(my_class *delete_this)
|
||||
{ delete delete_this; }
|
||||
};
|
||||
|
||||
int main()
|
||||
{
|
||||
const int MaxElem = 100;
|
||||
std::vector<my_class> nodes(MaxElem);
|
||||
|
||||
//Fill all the nodes and insert them in the list
|
||||
my_class_list list;
|
||||
|
||||
for(int i = 0; i < MaxElem; ++i) nodes[i].int_ = i;
|
||||
|
||||
list.insert(list.end(), nodes.begin(), nodes.end());
|
||||
|
||||
//Now clone "list" using "new" and "delete" object functions
|
||||
my_class_list cloned_list;
|
||||
cloned_list.clone_from(list, new_cloner(), delete_disposer());
|
||||
|
||||
//Test that both are equal
|
||||
if(cloned_list != list)
|
||||
std::cout << "Both lists are different" << std::endl;
|
||||
else
|
||||
std::cout << "Both lists are equal" << std::endl;
|
||||
|
||||
//Don't forget to free the memory from the second list
|
||||
cloned_list.clear_and_dispose(delete_disposer());
|
||||
return 0;
|
||||
}
|
||||
//]
|
||||
@@ -0,0 +1,60 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2006-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_entity_code
|
||||
#include <boost/intrusive/list.hpp>
|
||||
|
||||
using namespace boost::intrusive;
|
||||
|
||||
//A class that can be inserted in an intrusive list
|
||||
class entity : public list_base_hook<>
|
||||
{
|
||||
public:
|
||||
virtual ~entity();
|
||||
//...
|
||||
};
|
||||
|
||||
//"some_entity" derives from "entity"
|
||||
class some_entity : public entity
|
||||
{/**/};
|
||||
|
||||
//Definition of the intrusive list
|
||||
typedef list<entity> entity_list;
|
||||
|
||||
//A global list
|
||||
entity_list global_list;
|
||||
|
||||
//The destructor removes itself from the global list
|
||||
entity::~entity()
|
||||
{ global_list.erase(entity_list::s_iterator_to(*this)); }
|
||||
|
||||
//Function to insert a new "some_entity" in the global list
|
||||
void insert_some_entity()
|
||||
{ global_list.push_back (*new some_entity(/*...*/)); }
|
||||
|
||||
//Function to clear an entity from the intrusive global list
|
||||
void clear_list ()
|
||||
{
|
||||
// entity's destructor removes itself from the global list implicitly
|
||||
while (!global_list.empty())
|
||||
delete &global_list.front();
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
//Insert some new entities
|
||||
insert_some_entity();
|
||||
insert_some_entity();
|
||||
//global_list's destructor will free objects
|
||||
return 0;
|
||||
}
|
||||
|
||||
//]
|
||||
@@ -0,0 +1,70 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2006-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_erasing_and_disposing
|
||||
#include <boost/intrusive/list.hpp>
|
||||
|
||||
using namespace boost::intrusive;
|
||||
|
||||
//A class that can be inserted in an intrusive list
|
||||
class my_class : public list_base_hook<>
|
||||
{
|
||||
public:
|
||||
my_class(int i)
|
||||
: int_(i)
|
||||
{}
|
||||
|
||||
int int_;
|
||||
//...
|
||||
};
|
||||
|
||||
//Definition of the intrusive list
|
||||
typedef list<my_class> my_class_list;
|
||||
|
||||
//The predicate function
|
||||
struct is_even
|
||||
{
|
||||
bool operator()(const my_class &c) const
|
||||
{ return 0 == (c.int_ % 2); }
|
||||
};
|
||||
|
||||
//The disposer object function
|
||||
struct delete_disposer
|
||||
{
|
||||
void operator()(my_class *delete_this)
|
||||
{ delete delete_this; }
|
||||
};
|
||||
|
||||
int main()
|
||||
{
|
||||
const int MaxElem = 100;
|
||||
|
||||
//Fill all the nodes and insert them in the list
|
||||
my_class_list list;
|
||||
|
||||
try{
|
||||
//Insert new objects in the container
|
||||
for(int i = 0; i < MaxElem; ++i) list.push_back(*new my_class(i));
|
||||
|
||||
//Now use remove_and_dispose_if to erase and delete the objects
|
||||
list.remove_and_dispose_if(is_even(), delete_disposer());
|
||||
}
|
||||
catch(...){
|
||||
//If something throws, make sure that all the memory is freed
|
||||
list.clear_and_dispose(delete_disposer());
|
||||
throw;
|
||||
}
|
||||
|
||||
//Dispose remaining elements
|
||||
list.erase_and_dispose(list.begin(), list.end(), delete_disposer());
|
||||
return 0;
|
||||
}
|
||||
//]
|
||||
@@ -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;
|
||||
}
|
||||
//]
|
||||
@@ -0,0 +1,75 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2006-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_how_to_use_code
|
||||
#include <boost/intrusive/list.hpp>
|
||||
#include <vector>
|
||||
|
||||
using namespace boost::intrusive;
|
||||
|
||||
class MyClass : public list_base_hook<>
|
||||
{
|
||||
int int_;
|
||||
|
||||
public:
|
||||
list_member_hook<> member_hook_;
|
||||
|
||||
MyClass(int i) : int_(i) {}
|
||||
};
|
||||
|
||||
//Define a list that will store MyClass using the base hook
|
||||
typedef list<MyClass> BaseList;
|
||||
|
||||
//Define a list that will store MyClass using the member hook
|
||||
typedef member_hook
|
||||
< MyClass, list_member_hook<>, &MyClass::member_hook_> MemberOption;
|
||||
typedef list<MyClass, MemberOption> MemberList;
|
||||
|
||||
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));
|
||||
|
||||
BaseList baselist;
|
||||
MemberList memberlist;
|
||||
|
||||
//Now insert them in the reverse order in the base hook list
|
||||
for(VectIt it(values.begin()), itend(values.end())
|
||||
; it != itend ; ++it){
|
||||
baselist.push_front(*it);
|
||||
}
|
||||
|
||||
//Now insert them in the same order as in vector in the member hook list
|
||||
for(VectIt it(values.begin()), itend(values.end()); it != itend; ++it)
|
||||
memberlist.push_back(*it);
|
||||
|
||||
//Now test lists
|
||||
{
|
||||
BaseList::reverse_iterator rbit(baselist.rbegin()), rbitend(baselist.rend());
|
||||
MemberList::iterator mit(memberlist.begin()), mitend(memberlist.end());
|
||||
VectIt it(values.begin()), itend(values.end());
|
||||
|
||||
//Test the objects inserted in the base hook list
|
||||
for(; it != itend; ++it, ++rbit)
|
||||
if(&*rbit != &*it) return 1;
|
||||
|
||||
//Test the objects inserted in the member hook list
|
||||
for(it = values.begin(); it != itend; ++it, ++mit)
|
||||
if(&*mit != &*it) return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
//]
|
||||
@@ -0,0 +1,97 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2006-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_iterator_from_value
|
||||
#include <boost/intrusive/list.hpp>
|
||||
#include <boost/intrusive/unordered_set.hpp>
|
||||
#include <boost/functional/hash.hpp>
|
||||
#include <vector>
|
||||
|
||||
using namespace boost::intrusive;
|
||||
|
||||
class intrusive_data
|
||||
{
|
||||
int data_id_;
|
||||
public:
|
||||
|
||||
void set(int id) { data_id_ = id; }
|
||||
|
||||
//This class can be inserted in an intrusive list
|
||||
list_member_hook<> list_hook_;
|
||||
|
||||
//This class can be inserted in an intrusive unordered_set
|
||||
unordered_set_member_hook<> unordered_set_hook_;
|
||||
|
||||
//Comparison operators
|
||||
friend bool operator==(const intrusive_data &a, const intrusive_data &b)
|
||||
{ return a.data_id_ == b.data_id_; }
|
||||
|
||||
friend bool operator!=(const intrusive_data &a, const intrusive_data &b)
|
||||
{ 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_); }
|
||||
};
|
||||
|
||||
//Definition of the intrusive list that will hold intrusive_data
|
||||
typedef member_hook<intrusive_data, list_member_hook<>
|
||||
, &intrusive_data::list_hook_> MemberListOption;
|
||||
typedef list<intrusive_data, MemberListOption> list_t;
|
||||
|
||||
//Definition of the intrusive unordered_set that will hold intrusive_data
|
||||
typedef member_hook
|
||||
< 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()
|
||||
{
|
||||
//Create MaxElem objects
|
||||
const int MaxElem = 100;
|
||||
std::vector<intrusive_data> nodes(MaxElem);
|
||||
|
||||
//Declare the intrusive containers
|
||||
list_t list;
|
||||
unordered_set_t::bucket_type buckets[MaxElem];
|
||||
unordered_set_t unordered_set
|
||||
(unordered_set_t::bucket_traits(buckets, MaxElem));
|
||||
|
||||
//Initialize all the nodes
|
||||
for(int i = 0; i < MaxElem; ++i) nodes[i].set(i);
|
||||
|
||||
//Now insert them in both intrusive containers
|
||||
list.insert(list.end(), nodes.begin(), nodes.end());
|
||||
unordered_set.insert(nodes.begin(), nodes.end());
|
||||
|
||||
//Now check the iterator_to function
|
||||
list_t::iterator list_it(list.begin());
|
||||
for(int i = 0; i < MaxElem; ++i, ++list_it)
|
||||
if(list.iterator_to(nodes[i]) != list_it ||
|
||||
list_t::s_iterator_to(nodes[i]) != list_it)
|
||||
return 1;
|
||||
|
||||
//Now check unordered_set::s_iterator_to (which is a 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());
|
||||
for(int i = 0; i < MaxElem; ++i){
|
||||
unordered_set_it = unordered_set.find(nodes[i]);
|
||||
if(unordered_set.iterator_to(nodes[i]) != unordered_set_it)
|
||||
return 1;
|
||||
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 0;
|
||||
}
|
||||
//]
|
||||
@@ -0,0 +1,76 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2006-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_list_code
|
||||
#include <boost/intrusive/list.hpp>
|
||||
#include <vector>
|
||||
|
||||
using namespace boost::intrusive;
|
||||
|
||||
class MyClass : public list_base_hook<> //This is a derivation hook
|
||||
{
|
||||
int int_;
|
||||
|
||||
public:
|
||||
//This is a member hook
|
||||
list_member_hook<> member_hook_;
|
||||
|
||||
MyClass(int i)
|
||||
: int_(i)
|
||||
{}
|
||||
};
|
||||
|
||||
//Define a list that will store MyClass using the public base hook
|
||||
typedef list<MyClass> BaseList;
|
||||
|
||||
//Define a list that will store MyClass using the public member hook
|
||||
typedef list< MyClass
|
||||
, member_hook< MyClass, list_member_hook<>, &MyClass::member_hook_>
|
||||
> MemberList;
|
||||
|
||||
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));
|
||||
|
||||
BaseList baselist;
|
||||
MemberList memberlist;
|
||||
|
||||
//Now insert them in the reverse order in the base hook list
|
||||
for(VectIt it(values.begin()), itend(values.end()); it != itend; ++it)
|
||||
baselist.push_front(*it);
|
||||
|
||||
//Now insert them in the same order as in vector in the member hook list
|
||||
for(VectIt it(values.begin()), itend(values.end()); it != itend; ++it)
|
||||
memberlist.push_back(*it);
|
||||
|
||||
//Now test lists
|
||||
{
|
||||
BaseList::reverse_iterator rbit(baselist.rbegin()), rbitend(baselist.rend());
|
||||
MemberList::iterator mit(memberlist.begin()), mitend(memberlist.end());
|
||||
VectIt it(values.begin()), itend(values.end());
|
||||
|
||||
//Test the objects inserted in the base hook list
|
||||
for(; it != itend; ++it, ++rbit)
|
||||
if(&*rbit != &*it) return 1;
|
||||
|
||||
//Test the objects inserted in the member hook list
|
||||
for(it = values.begin(); it != itend; ++it, ++mit)
|
||||
if(&*mit != &*it) return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
//]
|
||||
@@ -0,0 +1,66 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2006-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_list_algorithms_code
|
||||
#include <boost/intrusive/circular_list_algorithms.hpp>
|
||||
#include <cassert>
|
||||
|
||||
struct my_node
|
||||
{
|
||||
my_node *next_, *prev_;
|
||||
//other members...
|
||||
};
|
||||
|
||||
//Define our own list_node_traits
|
||||
struct my_list_node_traits
|
||||
{
|
||||
typedef my_node node;
|
||||
typedef my_node * node_ptr;
|
||||
typedef const my_node * const_node_ptr;
|
||||
static node_ptr get_next(const_node_ptr n) { return n->next_; }
|
||||
static void set_next(node_ptr n, node_ptr next) { n->next_ = next; }
|
||||
static node *get_previous(const_node_ptr n) { return n->prev_; }
|
||||
static void set_previous(node_ptr n, node_ptr prev){ n->prev_ = prev; }
|
||||
};
|
||||
|
||||
int main()
|
||||
{
|
||||
typedef boost::intrusive::circular_list_algorithms<my_list_node_traits> algo;
|
||||
my_node one, two, three;
|
||||
|
||||
//Create an empty doubly linked list container:
|
||||
//"one" will be the first node of the container
|
||||
algo::init(&one);
|
||||
assert(algo::count(&one) == 1);
|
||||
|
||||
//Now add a new node before "one"
|
||||
algo::link_before(&one, &two);
|
||||
assert(algo::count(&one) == 2);
|
||||
|
||||
//Now add a new node after "two"
|
||||
algo::link_after(&two, &three);
|
||||
assert(algo::count(&one) == 3);
|
||||
|
||||
//Now unlink the node after one
|
||||
algo::unlink(&three);
|
||||
assert(algo::count(&one) == 2);
|
||||
|
||||
//Now unlink two
|
||||
algo::unlink(&two);
|
||||
assert(algo::count(&one) == 1);
|
||||
|
||||
//Now unlink one
|
||||
algo::unlink(&one);
|
||||
assert(algo::count(&one) == 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
//]
|
||||
@@ -0,0 +1,100 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2006-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.
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//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
|
||||
#include <boost/intrusive/list.hpp>
|
||||
#include <boost/interprocess/offset_ptr.hpp>
|
||||
|
||||
using namespace boost::intrusive;
|
||||
namespace ip = boost::interprocess;
|
||||
|
||||
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_;
|
||||
public:
|
||||
|
||||
int get() const { return data_id_; }
|
||||
void set(int id) { data_id_ = id; }
|
||||
};
|
||||
//]
|
||||
|
||||
//[doc_offset_ptr_1
|
||||
#include <boost/interprocess/managed_shared_memory.hpp>
|
||||
#include <boost/interprocess/containers/vector.hpp>
|
||||
#include <boost/interprocess/containers/list.hpp>
|
||||
#include <boost/interprocess/allocators/allocator.hpp>
|
||||
|
||||
//Definition of the shared memory friendly intrusive list
|
||||
typedef ip::list<shared_memory_data> shm_list_t;
|
||||
|
||||
int main()
|
||||
{
|
||||
//Now create an intrusive list in shared memory:
|
||||
//nodes and the container itself must be created in shared memory
|
||||
const int MaxElem = 100;
|
||||
const int ShmSize = 50000;
|
||||
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);
|
||||
|
||||
//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);
|
||||
|
||||
//Initialize all the nodes
|
||||
for(int i = 0; i < MaxElem; ++i) (*pshm_vect)[i].set(i);
|
||||
|
||||
//Now create the shared memory intrusive list
|
||||
shm_list_t *plist = shm.construct<shm_list_t>(ip::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
|
||||
shm.destroy_ptr(plist);
|
||||
shm.destroy_ptr(pshm_vect);
|
||||
}
|
||||
ip::shared_memory_object::remove(ShmName);
|
||||
return 0;
|
||||
}
|
||||
//]
|
||||
@@ -0,0 +1,83 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2006-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_rbtree_algorithms_code
|
||||
#include <boost/intrusive/rbtree_algorithms.hpp>
|
||||
#include <cassert>
|
||||
|
||||
struct my_node
|
||||
{
|
||||
my_node(int i = 0)
|
||||
: int_(i)
|
||||
{}
|
||||
my_node *parent_, *left_, *right_;
|
||||
int color_;
|
||||
//other members
|
||||
int int_;
|
||||
};
|
||||
|
||||
//Define our own rbtree_node_traits
|
||||
struct my_rbtree_node_traits
|
||||
{
|
||||
typedef my_node node;
|
||||
typedef my_node * node_ptr;
|
||||
typedef const my_node * const_node_ptr;
|
||||
typedef int color;
|
||||
static node_ptr get_parent(const_node_ptr n) { return n->parent_; }
|
||||
static void set_parent(node_ptr n, node_ptr parent){ n->parent_ = parent; }
|
||||
static node_ptr get_left(const_node_ptr n) { return n->left_; }
|
||||
static void set_left(node_ptr n, node_ptr left) { n->left_ = left; }
|
||||
static node_ptr get_right(const_node_ptr n) { return n->right_; }
|
||||
static void set_right(node_ptr n, node_ptr right) { n->right_ = right; }
|
||||
static color get_color(const_node_ptr n) { return n->color_; }
|
||||
static void set_color(node_ptr n, color c) { n->color_ = c; }
|
||||
static color black() { return color(0); }
|
||||
static color red() { return color(1); }
|
||||
};
|
||||
|
||||
struct node_ptr_compare
|
||||
{
|
||||
bool operator()(my_node *a, my_node *b)
|
||||
{ return a->int_ < b->int_; }
|
||||
};
|
||||
|
||||
int main()
|
||||
{
|
||||
typedef boost::intrusive::rbtree_algorithms<my_rbtree_node_traits> algo;
|
||||
my_node header, two(2), three(3);
|
||||
|
||||
//Create an empty rbtree container:
|
||||
//"header" will be the header node of the tree
|
||||
algo::init_header(&header);
|
||||
|
||||
//Now insert node "two" in the tree using the sorting functor
|
||||
algo::insert_equal_upper_bound(&header, &two, node_ptr_compare());
|
||||
|
||||
//Now insert node "three" in the tree using the sorting functor
|
||||
algo::insert_equal_lower_bound(&header, &three, node_ptr_compare());
|
||||
|
||||
//Now take the first node (the left node of the header)
|
||||
my_node *n = header.left_;
|
||||
assert(n == &two);
|
||||
|
||||
//Now go to the next node
|
||||
n = algo::next_node(n);
|
||||
assert(n == &three);
|
||||
|
||||
//Erase a node just using a pointer to it
|
||||
algo::unlink(&two);
|
||||
|
||||
//Erase a node using also the header (faster)
|
||||
algo::erase(&header, &three);
|
||||
return 0;
|
||||
}
|
||||
|
||||
//]
|
||||
@@ -0,0 +1,86 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2006-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_set_code
|
||||
#include <boost/intrusive/set.hpp>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
|
||||
using namespace boost::intrusive;
|
||||
|
||||
//This is a base hook optimized for size
|
||||
class MyClass : public set_base_hook<optimize_size<true> >
|
||||
{
|
||||
int int_;
|
||||
|
||||
public:
|
||||
//This is a member hook
|
||||
set_member_hook<> member_hook_;
|
||||
|
||||
MyClass(int i)
|
||||
: int_(i)
|
||||
{}
|
||||
friend bool operator< (const MyClass &a, const MyClass &b)
|
||||
{ return a.int_ < b.int_; }
|
||||
friend bool operator> (const MyClass &a, const MyClass &b)
|
||||
{ return a.int_ > b.int_; }
|
||||
friend bool operator== (const MyClass &a, const MyClass &b)
|
||||
{ return a.int_ < b.int_; }
|
||||
};
|
||||
|
||||
//Define a set using the base hook that will store values in reverse order
|
||||
typedef set< MyClass, compare<std::greater<MyClass> > > BaseSet;
|
||||
|
||||
//Define an multiset using the member hook
|
||||
typedef member_hook<MyClass, set_member_hook<>, &MyClass::member_hook_> MemberOption;
|
||||
typedef multiset< MyClass, MemberOption> MemberMultiset;
|
||||
|
||||
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));
|
||||
|
||||
BaseSet baseset;
|
||||
MemberMultiset membermultiset;
|
||||
|
||||
//Check that size optimization is activated in the base hook
|
||||
assert(sizeof(set_base_hook<optimize_size<true> >) == 3*sizeof(void*));
|
||||
//Check that size optimization is deactivated in the member hook
|
||||
assert(sizeof(set_member_hook<>) > 3*sizeof(void*));
|
||||
|
||||
//Now insert them in the reverse order in the base hook set
|
||||
for(VectIt it(values.begin()), itend(values.end()); it != itend; ++it){
|
||||
baseset.insert(*it);
|
||||
membermultiset.insert(*it);
|
||||
}
|
||||
|
||||
//Now test sets
|
||||
{
|
||||
BaseSet::reverse_iterator rbit(baseset.rbegin()), rbitend(baseset.rend());
|
||||
MemberMultiset::iterator mit(membermultiset.begin()), mitend(membermultiset.end());
|
||||
VectIt it(values.begin()), itend(values.end());
|
||||
|
||||
//Test the objects inserted in the base hook set
|
||||
for(; it != itend; ++it, ++rbit)
|
||||
if(&*rbit != &*it) return 1;
|
||||
|
||||
//Test the objects inserted in the member hook set
|
||||
for(it = values.begin(); it != itend; ++it, ++mit)
|
||||
if(&*mit != &*it) return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
//]
|
||||
@@ -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.
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//[doc_sg_set_code
|
||||
#include <boost/intrusive/sg_set.hpp>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
|
||||
using namespace boost::intrusive;
|
||||
|
||||
class MyClass : public bs_set_base_hook<>
|
||||
{
|
||||
int int_;
|
||||
|
||||
public:
|
||||
//This is a member hook
|
||||
bs_set_member_hook<> member_hook_;
|
||||
|
||||
MyClass(int i)
|
||||
: int_(i)
|
||||
{}
|
||||
friend bool operator< (const MyClass &a, const MyClass &b)
|
||||
{ return a.int_ < b.int_; }
|
||||
friend bool operator> (const MyClass &a, const MyClass &b)
|
||||
{ return a.int_ > b.int_; }
|
||||
friend bool operator== (const MyClass &a, const MyClass &b)
|
||||
{ return a.int_ < b.int_; }
|
||||
};
|
||||
|
||||
//Define an sg_set using the base hook that will store values in reverse order
|
||||
//and won't execute floating point operations.
|
||||
typedef sg_set
|
||||
< MyClass, compare<std::greater<MyClass> >, floating_point<false> > BaseSet;
|
||||
|
||||
//Define an multiset using the member hook
|
||||
typedef member_hook<MyClass, bs_set_member_hook<>, &MyClass::member_hook_> MemberOption;
|
||||
typedef sg_multiset< MyClass, MemberOption> MemberMultiset;
|
||||
|
||||
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));
|
||||
|
||||
BaseSet baseset;
|
||||
MemberMultiset membermultiset;
|
||||
|
||||
//Now insert them in the reverse order in the base hook sg_set
|
||||
for(VectIt it(values.begin()), itend(values.end()); it != itend; ++it){
|
||||
baseset.insert(*it);
|
||||
membermultiset.insert(*it);
|
||||
}
|
||||
|
||||
//Change balance factor
|
||||
membermultiset.balance_factor(0.9f);
|
||||
|
||||
//Now test sg_sets
|
||||
{
|
||||
BaseSet::reverse_iterator rbit(baseset.rbegin()), rbitend(baseset.rend());
|
||||
MemberMultiset::iterator mit(membermultiset.begin()), mitend(membermultiset.end());
|
||||
VectIt it(values.begin()), itend(values.end());
|
||||
|
||||
//Test the objects inserted in the base hook sg_set
|
||||
for(; it != itend; ++it, ++rbit)
|
||||
if(&*rbit != &*it) return 1;
|
||||
|
||||
//Test the objects inserted in the member hook sg_set
|
||||
for(it = values.begin(); it != itend; ++it, ++mit)
|
||||
if(&*mit != &*it) return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
//]
|
||||
@@ -0,0 +1,79 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2006-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_slist_code
|
||||
#include <boost/intrusive/slist.hpp>
|
||||
#include <vector>
|
||||
|
||||
using namespace boost::intrusive;
|
||||
|
||||
//This is a base hook
|
||||
class MyClass : public slist_base_hook<>
|
||||
{
|
||||
int int_;
|
||||
|
||||
public:
|
||||
//This is a member hook
|
||||
slist_member_hook<> member_hook_;
|
||||
|
||||
MyClass(int i)
|
||||
: int_(i)
|
||||
{}
|
||||
};
|
||||
|
||||
//Define an slist that will store MyClass using the public base hook
|
||||
typedef slist<MyClass> BaseList;
|
||||
|
||||
//Define an slist that will store MyClass using the public member hook
|
||||
typedef member_hook<MyClass, slist_member_hook<>, &MyClass::member_hook_> MemberOption;
|
||||
typedef slist<MyClass, MemberOption> MemberList;
|
||||
|
||||
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));
|
||||
|
||||
BaseList baselist;
|
||||
MemberList memberlist;
|
||||
|
||||
//Now insert them in the reverse order in the base hook list
|
||||
for(VectIt it(values.begin()), itend(values.end()); it != itend; ++it)
|
||||
baselist.push_front(*it);
|
||||
|
||||
//Now insert them in the same order as in vector in the member hook list
|
||||
for(BaseList::iterator it(baselist.begin()), itend(baselist.end())
|
||||
; it != itend; ++it){
|
||||
memberlist.push_front(*it);
|
||||
}
|
||||
|
||||
//Now test lists
|
||||
{
|
||||
BaseList::iterator bit(baselist.begin()), bitend(baselist.end());
|
||||
MemberList::iterator mit(memberlist.begin()), mitend(memberlist.end());
|
||||
VectRit rit(values.rbegin()), ritend(values.rend());
|
||||
VectIt it(values.begin()), itend(values.end());
|
||||
|
||||
//Test the objects inserted in the base hook list
|
||||
for(; rit != ritend; ++rit, ++bit)
|
||||
if(&*bit != &*rit) return 1;
|
||||
|
||||
//Test the objects inserted in the member hook list
|
||||
for(; it != itend; ++it, ++mit)
|
||||
if(&*mit != &*it) return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
//]
|
||||
@@ -0,0 +1,60 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2006-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_slist_algorithms_code
|
||||
#include <boost/intrusive/circular_slist_algorithms.hpp>
|
||||
#include <cassert>
|
||||
|
||||
struct my_node
|
||||
{
|
||||
my_node *next_;
|
||||
//other members...
|
||||
};
|
||||
|
||||
//Define our own slist_node_traits
|
||||
struct my_slist_node_traits
|
||||
{
|
||||
typedef my_node node;
|
||||
typedef my_node * node_ptr;
|
||||
typedef const my_node * const_node_ptr;
|
||||
static node_ptr get_next(const_node_ptr n) { return n->next_; }
|
||||
static void set_next(node_ptr n, node_ptr next) { n->next_ = next; }
|
||||
};
|
||||
|
||||
int main()
|
||||
{
|
||||
typedef boost::intrusive::circular_slist_algorithms<my_slist_node_traits> algo;
|
||||
my_node one, two, three;
|
||||
|
||||
//Create an empty singly linked list container:
|
||||
//"one" will be the first node of the container
|
||||
algo::init(&one);
|
||||
assert(algo::count(&one) == 1);
|
||||
|
||||
//Now add a new node
|
||||
algo::link_after(&one, &two);
|
||||
assert(algo::count(&one) == 2);
|
||||
|
||||
//Now add a new node after "one"
|
||||
algo::link_after(&one, &three);
|
||||
assert(algo::count(&one) == 3);
|
||||
|
||||
//Now unlink the node after one
|
||||
algo::unlink_after(&one);
|
||||
assert(algo::count(&one) == 2);
|
||||
|
||||
//Now unlink two
|
||||
algo::unlink(&two);
|
||||
assert(algo::count(&one) == 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
//]
|
||||
@@ -0,0 +1,79 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2006-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_splaytree_algorithms_code
|
||||
#include <boost/intrusive/splaytree_algorithms.hpp>
|
||||
#include <cassert>
|
||||
|
||||
struct my_node
|
||||
{
|
||||
my_node(int i = 0)
|
||||
: int_(i)
|
||||
{}
|
||||
my_node *parent_, *left_, *right_;
|
||||
int color_;
|
||||
//other members
|
||||
int int_;
|
||||
};
|
||||
|
||||
//Define our own splaytree_node_traits
|
||||
struct my_splaytree_node_traits
|
||||
{
|
||||
typedef my_node node;
|
||||
typedef my_node * node_ptr;
|
||||
typedef const my_node * const_node_ptr;
|
||||
|
||||
static node_ptr get_parent(const_node_ptr n) { return n->parent_; }
|
||||
static void set_parent(node_ptr n, node_ptr parent){ n->parent_ = parent; }
|
||||
static node_ptr get_left(const_node_ptr n) { return n->left_; }
|
||||
static void set_left(node_ptr n, node_ptr left) { n->left_ = left; }
|
||||
static node_ptr get_right(const_node_ptr n) { return n->right_; }
|
||||
static void set_right(node_ptr n, node_ptr right) { n->right_ = right; }
|
||||
};
|
||||
|
||||
struct node_ptr_compare
|
||||
{
|
||||
bool operator()(my_node *a, my_node *b)
|
||||
{ return a->int_ < b->int_; }
|
||||
};
|
||||
|
||||
int main()
|
||||
{
|
||||
typedef boost::intrusive::splaytree_algorithms<my_splaytree_node_traits> algo;
|
||||
my_node header, two(2), three(3);
|
||||
|
||||
//Create an empty splaytree container:
|
||||
//"header" will be the header node of the tree
|
||||
algo::init_header(&header);
|
||||
|
||||
//Now insert node "two" in the tree using the sorting functor
|
||||
algo::insert_equal_upper_bound(&header, &two, node_ptr_compare());
|
||||
|
||||
//Now insert node "three" in the tree using the sorting functor
|
||||
algo::insert_equal_lower_bound(&header, &three, node_ptr_compare());
|
||||
|
||||
//Now take the first node (the left node of the header)
|
||||
my_node *n = header.left_;
|
||||
assert(n == &two);
|
||||
|
||||
//Now go to the next node
|
||||
n = algo::next_node(n);
|
||||
assert(n == &three);
|
||||
|
||||
//Erase a node just using a pointer to it
|
||||
algo::unlink(&two);
|
||||
|
||||
//Erase a node using also the header (faster)
|
||||
algo::erase(&header, &three);
|
||||
return 0;
|
||||
}
|
||||
|
||||
//]
|
||||
@@ -0,0 +1,93 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2006-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_splay_set_code
|
||||
#include <boost/intrusive/splay_set.hpp>
|
||||
#include <boost/intrusive/bs_set_hook.hpp>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
|
||||
using namespace boost::intrusive;
|
||||
|
||||
class MyClass
|
||||
: public splay_set_base_hook<> //This is an splay tree base hook
|
||||
, public bs_set_base_hook<> //This is a binary search tree base hook
|
||||
|
||||
{
|
||||
int int_;
|
||||
|
||||
public:
|
||||
//This is a member hook
|
||||
splay_set_member_hook<> member_hook_;
|
||||
|
||||
MyClass(int i)
|
||||
: int_(i)
|
||||
{}
|
||||
friend bool operator< (const MyClass &a, const MyClass &b)
|
||||
{ return a.int_ < b.int_; }
|
||||
friend bool operator> (const MyClass &a, const MyClass &b)
|
||||
{ return a.int_ > b.int_; }
|
||||
friend bool operator== (const MyClass &a, const MyClass &b)
|
||||
{ return a.int_ < b.int_; }
|
||||
};
|
||||
|
||||
//Define a set using the base hook that will store values in reverse order
|
||||
typedef splay_set< MyClass, compare<std::greater<MyClass> > > BaseSplaySet;
|
||||
|
||||
//Define a set using the binary search tree hook
|
||||
typedef splay_set< MyClass, base_hook<bs_set_base_hook<> > > BaseBsSplaySet;
|
||||
|
||||
//Define an multiset using the member hook
|
||||
typedef member_hook<MyClass, splay_set_member_hook<>, &MyClass::member_hook_> MemberOption;
|
||||
typedef splay_multiset< MyClass, MemberOption> MemberSplayMultiset;
|
||||
|
||||
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));
|
||||
|
||||
BaseSplaySet baseset;
|
||||
BaseBsSplaySet bsbaseset;
|
||||
MemberSplayMultiset membermultiset;
|
||||
|
||||
|
||||
//Insert values in the container
|
||||
for(VectIt it(values.begin()), itend(values.end()); it != itend; ++it){
|
||||
baseset.insert(*it);
|
||||
bsbaseset.insert(*it);
|
||||
membermultiset.insert(*it);
|
||||
}
|
||||
|
||||
//Now test sets
|
||||
{
|
||||
BaseSplaySet::reverse_iterator rbit(baseset.rbegin()), rbitend(baseset.rend());
|
||||
BaseBsSplaySet::iterator bsit(bsbaseset.begin()), bsitend(bsbaseset.end());
|
||||
MemberSplayMultiset::iterator mit(membermultiset.begin()), mitend(membermultiset.end());
|
||||
VectIt it(values.begin()), itend(values.end());
|
||||
|
||||
//Test the objects inserted in the base hook set
|
||||
for(; it != itend; ++it, ++rbit){
|
||||
if(&*rbit != &*it) return 1;
|
||||
}
|
||||
|
||||
//Test the objects inserted in member and binary search hook sets
|
||||
for(it = values.begin(); it != itend; ++it, ++bsit, ++mit){
|
||||
if(&*bsit != &*it) return 1;
|
||||
if(&*mit != &*it) return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
//]
|
||||
@@ -0,0 +1,78 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (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_splaytree_algorithms_code
|
||||
#include <boost/intrusive/splaytree_algorithms.hpp>
|
||||
#include <cassert>
|
||||
|
||||
struct my_node
|
||||
{
|
||||
my_node(int i = 0)
|
||||
: int_(i)
|
||||
{}
|
||||
my_node *parent_, *left_, *right_;
|
||||
//other members
|
||||
int int_;
|
||||
};
|
||||
|
||||
//Define our own splaytree_node_traits
|
||||
struct my_splaytree_node_traits
|
||||
{
|
||||
typedef my_node node;
|
||||
typedef my_node * node_ptr;
|
||||
typedef const my_node * const_node_ptr;
|
||||
|
||||
static node_ptr get_parent(const_node_ptr n) { return n->parent_; }
|
||||
static void set_parent(node_ptr n, node_ptr parent){ n->parent_ = parent; }
|
||||
static node_ptr get_left(const_node_ptr n) { return n->left_; }
|
||||
static void set_left(node_ptr n, node_ptr left) { n->left_ = left; }
|
||||
static node_ptr get_right(const_node_ptr n) { return n->right_; }
|
||||
static void set_right(node_ptr n, node_ptr right) { n->right_ = right; }
|
||||
};
|
||||
|
||||
struct node_ptr_compare
|
||||
{
|
||||
bool operator()(my_node *a, my_node *b)
|
||||
{ return a->int_ < b->int_; }
|
||||
};
|
||||
|
||||
int main()
|
||||
{
|
||||
typedef boost::intrusive::splaytree_algorithms<my_splaytree_node_traits> algo;
|
||||
my_node header, two(2), three(3);
|
||||
|
||||
//Create an empty splaytree container:
|
||||
//"header" will be the header node of the tree
|
||||
algo::init_header(&header);
|
||||
|
||||
//Now insert node "two" in the tree using the sorting functor
|
||||
algo::insert_equal_upper_bound(&header, &two, node_ptr_compare());
|
||||
|
||||
//Now insert node "three" in the tree using the sorting functor
|
||||
algo::insert_equal_lower_bound(&header, &three, node_ptr_compare());
|
||||
|
||||
//Now take the first node (the left node of the header)
|
||||
my_node *n = header.left_;
|
||||
assert(n == &two);
|
||||
|
||||
//Now go to the next node
|
||||
n = algo::next_node(n);
|
||||
assert(n == &three);
|
||||
|
||||
//Erase a node just using a pointer to it
|
||||
algo::unlink(&two);
|
||||
|
||||
//Erase a node using also the header (faster)
|
||||
algo::erase(&header, &three);
|
||||
return 0;
|
||||
}
|
||||
|
||||
//]
|
||||
@@ -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;
|
||||
}
|
||||
//]
|
||||
@@ -0,0 +1,94 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2006-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_unordered_set_code
|
||||
#include <boost/intrusive/unordered_set.hpp>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
#include <boost/functional/hash.hpp>
|
||||
|
||||
using namespace boost::intrusive;
|
||||
|
||||
class MyClass : public unordered_set_base_hook<>
|
||||
{ //This is a derivation hook
|
||||
int int_;
|
||||
|
||||
public:
|
||||
unordered_set_member_hook<> member_hook_; //This is a member hook
|
||||
|
||||
MyClass(int i)
|
||||
: int_(i)
|
||||
{}
|
||||
|
||||
friend bool operator== (const MyClass &a, const MyClass &b)
|
||||
{ return a.int_ == b.int_; }
|
||||
|
||||
friend std::size_t hash_value(const MyClass &value)
|
||||
{ return std::size_t(value.int_); }
|
||||
};
|
||||
|
||||
//Define an unordered_set that will store MyClass objects using the base hook
|
||||
typedef unordered_set<MyClass> BaseSet;
|
||||
|
||||
//Define an unordered_multiset that will store MyClass using the member hook
|
||||
typedef member_hook<MyClass, unordered_set_member_hook<>, &MyClass::member_hook_>
|
||||
MemberOption;
|
||||
typedef unordered_multiset< MyClass, MemberOption> MemberMultiSet;
|
||||
|
||||
int main()
|
||||
{
|
||||
typedef std::vector<MyClass>::iterator VectIt;
|
||||
typedef std::vector<MyClass>::reverse_iterator VectRit;
|
||||
|
||||
//Create a vector with 100 different MyClass objects
|
||||
std::vector<MyClass> values;
|
||||
for(int i = 0; i < 100; ++i) values.push_back(MyClass(i));
|
||||
|
||||
//Create a copy of the vector
|
||||
std::vector<MyClass> values2(values);
|
||||
|
||||
//Create a bucket array for base_set
|
||||
BaseSet::bucket_type base_buckets[100];
|
||||
|
||||
//Create a bucket array for member_multi_set
|
||||
MemberMultiSet::bucket_type member_buckets[200];
|
||||
|
||||
//Create unordered containers taking buckets as arguments
|
||||
BaseSet base_set(BaseSet::bucket_traits(base_buckets, 100));
|
||||
MemberMultiSet member_multi_set
|
||||
(MemberMultiSet::bucket_traits(member_buckets, 200));
|
||||
|
||||
//Now insert values's elements in the unordered_set
|
||||
for(VectIt it(values.begin()), itend(values.end()); it != itend; ++it)
|
||||
base_set.insert(*it);
|
||||
|
||||
//Now insert values's and values2's elements in the unordered_multiset
|
||||
for(VectIt it(values.begin()), itend(values.end()),
|
||||
it2(values2.begin()),itend2(values2.end())
|
||||
; it != itend; ++it, ++it2){
|
||||
member_multi_set.insert(*it);
|
||||
member_multi_set.insert(*it2);
|
||||
}
|
||||
|
||||
//Now find every element
|
||||
{
|
||||
VectIt it(values.begin()), itend(values.end());
|
||||
|
||||
for(; it != itend; ++it){
|
||||
//base_set should contain one element for each key
|
||||
if(base_set.count(*it) != 1) return 1;
|
||||
//member_multi_set should contain two elements for each key
|
||||
if(member_multi_set.count(*it) != 2) return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
//]
|
||||
@@ -0,0 +1,103 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2006-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_value_traits_code_legacy
|
||||
#include <boost/intrusive/link_mode.hpp>
|
||||
#include <boost/intrusive/list.hpp>
|
||||
#include <boost/intrusive/slist.hpp>
|
||||
#include <vector>
|
||||
|
||||
//This node is the legacy type we can't modify and we want to insert in
|
||||
//intrusive list and slist containers using only two pointers, since
|
||||
//we know the object will never be at the same time in both lists.
|
||||
struct legacy_value
|
||||
{
|
||||
legacy_value *prev_;
|
||||
legacy_value *next_;
|
||||
int id_;
|
||||
};
|
||||
//]
|
||||
|
||||
//[doc_value_traits_value_traits
|
||||
//Define our own NodeTraits that will configure singly and doubly linked
|
||||
//list algorithms. Note that this node traits is compatible with
|
||||
//circular_slist_algorithms and circular_list_algorithms.
|
||||
|
||||
namespace bi = boost::intrusive;
|
||||
|
||||
struct legacy_node_traits
|
||||
{
|
||||
typedef legacy_value node;
|
||||
typedef legacy_value * node_ptr;
|
||||
typedef const legacy_value * const_node_ptr;
|
||||
|
||||
static node *get_next(const node *n) { return n->next_; }
|
||||
static void set_next(node *n, node *next) { n->next_ = next; }
|
||||
static node *get_previous(const node *n) { return n->prev_; }
|
||||
static void set_previous(node *n, node *prev) { n->prev_ = prev; }
|
||||
};
|
||||
|
||||
//This ValueTraits will configure list and slist. In this case,
|
||||
//legacy_node_traits::node is the same as the
|
||||
//legacy_value_traits::value_type so to_node_ptr/to_value_ptr
|
||||
//functions are trivial.
|
||||
struct legacy_value_traits
|
||||
{
|
||||
typedef legacy_node_traits node_traits;
|
||||
typedef node_traits::node_ptr node_ptr;
|
||||
typedef node_traits::const_node_ptr const_node_ptr;
|
||||
typedef legacy_value value_type;
|
||||
typedef legacy_value * pointer;
|
||||
typedef const legacy_value * const_pointer;
|
||||
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 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 const_pointer to_value_ptr(const_node_ptr n) { return const_pointer(n); }
|
||||
};
|
||||
|
||||
//]
|
||||
|
||||
//[doc_value_traits_test
|
||||
//Now define an intrusive list and slist that will store legacy_value objects
|
||||
typedef bi::value_traits<legacy_value_traits> ValueTraitsOption;
|
||||
typedef bi::list<legacy_value, ValueTraitsOption> LegacyAbiList;
|
||||
typedef bi::slist<legacy_value, ValueTraitsOption> LegacyAbiSlist;
|
||||
|
||||
template<class List>
|
||||
bool test_list()
|
||||
{
|
||||
typedef std::vector<legacy_value> Vect;
|
||||
|
||||
//Create legacy_value objects, with a different internal number
|
||||
Vect legacy_vector;
|
||||
for(int i = 0; i < 100; ++i){
|
||||
legacy_value value; value.id_ = i; legacy_vector.push_back(value);
|
||||
}
|
||||
|
||||
//Create the list with the objects
|
||||
List mylist(legacy_vector.begin(), legacy_vector.end());
|
||||
|
||||
//Now test both lists
|
||||
typename List::const_iterator bit(mylist.begin()), bitend(mylist.end());
|
||||
typename Vect::const_iterator it(legacy_vector.begin()), itend(legacy_vector.end());
|
||||
|
||||
//Test the objects inserted in our list
|
||||
for(; it != itend; ++it, ++bit)
|
||||
if(&*bit != &*it) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
return test_list<LegacyAbiList>() && test_list<LegacyAbiSlist>() ? 0 : 1;
|
||||
}
|
||||
//]
|
||||
@@ -0,0 +1,83 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2006-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_window_code
|
||||
#include <boost/intrusive/list.hpp>
|
||||
|
||||
using namespace boost::intrusive;
|
||||
|
||||
//An abstract class that can be inserted in an intrusive list
|
||||
class Window : public list_base_hook<>
|
||||
{
|
||||
public:
|
||||
//This is a container those value is an abstract class: you can't do this with std::list.
|
||||
typedef list<Window> win_list;
|
||||
|
||||
//An static intrusive list declaration
|
||||
static win_list all_windows;
|
||||
|
||||
//Constructor. Includes this window in the list
|
||||
Window() { all_windows.push_back(*this); }
|
||||
//Destructor. Removes this node from the list
|
||||
virtual ~Window() { all_windows.erase(win_list::s_iterator_to(*this)); }
|
||||
//Pure virtual function to be implemented by derived classes
|
||||
virtual void Paint() = 0;
|
||||
};
|
||||
|
||||
//The static intrusive list declaration
|
||||
Window::win_list Window::all_windows;
|
||||
|
||||
//Some Window derived classes
|
||||
class FrameWindow : public Window
|
||||
{ void Paint(){/**/} };
|
||||
|
||||
class EditWindow : public Window
|
||||
{ void Paint(){/**/} };
|
||||
|
||||
class CanvasWindow : public Window
|
||||
{ void Paint(){/**/} };
|
||||
|
||||
//A function that prints all windows stored in the intrusive list
|
||||
void paint_all_windows()
|
||||
{
|
||||
for(Window::win_list::iterator i(Window::all_windows.begin())
|
||||
, e(Window::all_windows.end())
|
||||
; i != e; ++i)
|
||||
i->Paint();
|
||||
}
|
||||
|
||||
//...
|
||||
|
||||
//A class derived from Window
|
||||
class MainWindow : public Window
|
||||
{
|
||||
FrameWindow frame_; //these are derived from Window too
|
||||
EditWindow edit_;
|
||||
CanvasWindow canvas_;
|
||||
|
||||
public:
|
||||
void Paint(){/**/}
|
||||
//...
|
||||
};
|
||||
|
||||
//Main function
|
||||
int main()
|
||||
{
|
||||
//When a Window class is created, is automatically registered in the global list
|
||||
MainWindow window;
|
||||
|
||||
//Paint all the windows, sub-windows and so on
|
||||
paint_all_windows();
|
||||
|
||||
//All the windows are automatically unregistered in their destructors.
|
||||
return 0;
|
||||
}
|
||||
//]
|
||||
Reference in New Issue
Block a user