New Intrusive version

[SVN r38273]
This commit is contained in:
Ion Gaztañaga
2007-07-22 14:19:19 +00:00
parent 1e108ff97e
commit 1ca8dabff8
22 changed files with 1061 additions and 735 deletions

View File

@@ -8,12 +8,10 @@
# See http://www.boost.org/libs/intrusive for documentation.
project boost/intrusive/doc ;
import boostbook : boostbook ;
import doxygen ;
import quickbook ;
doxygen intrusive_doxygen
doxygen autodoc
:
[ glob ../../../boost/intrusive/*.hpp ]
:
@@ -26,15 +24,15 @@ doxygen intrusive_doxygen
<doxygen:param>SEARCH_INCLUDES=YES
;
xml intrusive_xml : intrusive.qbk ;
xml intrusive : intrusive.qbk ;
boostbook intrusive
boostbook standalone
:
intrusive_xml
intrusive_doxygen
intrusive
:
<xsl:param>boost.root=../../../..
<xsl:param>boost.libraries=../../../../libs/libraries.htm
<xsl:param>generate.section.toc.level=3
<xsl:param>chunk.first.sections=1
<dependency>autodoc
;

View File

@@ -1,8 +1,16 @@
[/
/ Copyright (c) 2007 Ion Gaztanaga
/
/ 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)
/]
[library Boost.Intrusive
[quickbook 1.3]
[version 2007-06-23]
[authors [Krzikalla, Olaf], [Gazta&ntilde;aga, Ion]]
[copyright 2005 Olaf Krzikalla, 2006-2007 Ion Gazta&ntilde;aga]
[id intrusive]
[dirname intrusive]
[purpose Intrusive containers]
[license
Distributed under the Boost Software License, Version 1.0.
@@ -17,7 +25,7 @@
[*Boost.Intrusive] is a library presenting some intrusive containers to
the world of C++. Intrusive containers are special containers
that offer [link boost_intrusive.performance better performance]
that offer [link intrusive.performance better performance]
and exception safety guarantees than non-intrusive containers (like STL containers).
The performance benefits of intrusive containers makes them ideal as a building
@@ -190,7 +198,7 @@ Intrusive containers have also downsides:
swapping can be used to implement move-capabilities. To ease the implementation of
copy constructors and assignment operators of classes storing [*Boost.Intrusive]
containers, [*Boost.Intrusive] offers special cloning functions. See
[link boost_intrusive.clone_from Cloning [*Boost.Intrusive] containers] section for more information.
[link intrusive.clone_from Cloning [*Boost.Intrusive] containers] section for more information.
* Analyzing thread-safety of a program that uses containers is harder with intrusive containers, becuase
the container might be modified indirectly without an explicitly call to a container member.
@@ -214,7 +222,7 @@ Intrusive containers have also downsides:
]
For a performance comparison between Intrusive and Non-intrusive containers see
[link boost_intrusive.performance Performance] section.
[link intrusive.performance Performance] section.
[endsect]
@@ -259,11 +267,11 @@ three template arguments:
* The second template argument controls the linking policy. [*Boost.Intrusive] currently supports
3 policies: `normal_link`, `safe_link`, `auto_unlink`. More about these in the sections
[link boost_intrusive.safe_hook Safe hooks] and [link boost_intrusive.auto_unlink_hooks Auto-unlink hooks]
[link intrusive.safe_hook Safe hooks] and [link intrusive.auto_unlink_hooks Auto-unlink hooks]
* The third template argument is the pointer type to be used internally in the hook.
The default value is `void *`, which means that raw pointers will be used in the hook.
More about this in the section titled [link boost_intrusive.using_smart_pointers Using smart pointers with Boost.Intrusive containers]
More about this in the section titled [link intrusive.using_smart_pointers Using smart pointers with Boost.Intrusive containers]
Example:
@@ -591,13 +599,13 @@ the user. See [@http://www.boost.org/libs/utility/assert.html] for more
information about `BOOST_ASSERT`.
`BOOST_ASSERT` is globally configured for all the libraries, so the user might
want to redefine safe-mode assertions without modifying `BOOST_ASSERT`. This can
be achieved redefining the following macros:
want to redefine intrusive safe-mode assertions without modifying the global
`BOOST_ASSERT`. This can be achieved redefining the following macros:
* `BOOST_INTRUSIVE_SAFE_MODE_CONTAINER_INSERTION_ASSERT`: This assertion will be
* `BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT`: This assertion will be
used in insertion functions of the intrusive containers to check that
the hook of the value to be inserted is default constructed.
* `BOOST_INTRUSIVE_SAFE_MODE_HOOK_DESTRUCTOR_ASSERT`: This assertion will be
* `BOOST_INTRUSIVE_SAFE_HOOK_DESTRUCTOR_ASSERT`: This assertion will be
used in hooks' destructors to check that the hook is in a default state.
If any of these macros is not redefined, it will be defaulted to `BOOST_ASSERT`.
@@ -620,7 +628,7 @@ If any of these macros is not redefined, it will be defaulted to `BOOST_ASSERT`.
These hooks have exactly the same size overhead as their analogue non auto-unlinking
hooks, but they have a restriction: they can only be used with
[link boost_intrusive.presenting_containers non-constant time containers].
[link intrusive.presenting_containers non-constant time containers].
There is a reason for this:
* Auto-unlink hooks don't store any reference to the container where they are inserted.
@@ -1594,7 +1602,7 @@ before explaining the customization options of [*Boost.Intrusive].
[section:node_algorithms Node algorithms with custom NodeTraits]
As explained in the [link boost_intrusive.concepts Concepts] section, [*Boost.Intrusive]
As explained in the [link intrusive.concepts Concepts] section, [*Boost.Intrusive]
containers are implemented using node algorithms that work on generic nodes.
Sometimes, the use of intrusive containers is expensive for some environments
@@ -1775,7 +1783,7 @@ For a complete rbtree of functions see
[section:value_traits Containers with custom ValueTraits]
As explained in the [link boost_intrusive.concepts Concepts] section, [*Boost.Intrusive]
As explained in the [link intrusive.concepts Concepts] section, [*Boost.Intrusive]
containers are templatized using a `ValueTraits` parameter. This parameter contains
all the information to glue the `value_type` of the containers and the node to be
used in node algorithms, since these types can be different. Apart from this,
@@ -1819,7 +1827,7 @@ Let's explain each type and function:
* ['node_traits]: The node configuration that it's needed by node algorithms.
These node traits and algorithms are
described in the previous chapter: [link boost_intrusive.node_algorithms Nodes Algorithms].
described in the previous chapter: [link intrusive.node_algorithms Nodes Algorithms].
* If my_value_traits is meant to be used with [classref boost::intrusive::slist slist],
`node_traits` should follow
@@ -1912,6 +1920,21 @@ we'll define a ValueTraits class that will configure [*Boost.Intrusive] containe
[doc_value_traits_value_traits]
Defining a value traits class that just defines `value_type` as
`legacy_node_traits::node` is a common approach when defining customized
intrusive containers, so [*Boost.Intrusive] offers a templatized
[classref boost::intrusive::trivial_value_traits trivial_value_traits] class
that does exactly what we want:
[c++]
#include <boost/intrusive/trivial_value_traits.hpp>
//Now we can define legacy_value_traits just with a single line
using namespace boost::intrusive;
typedef trivial_value_traits<legacy_node_traits, normal_link> legacy_value_traits;
Now we can just define the containers that will store the legacy abi objects and write
a little test:
@@ -1955,6 +1978,40 @@ share the same list algorithms.
[endsect]
[section:simplifying_value_traits Simplifying value traits definition]
The previous example can be further simplified using
[classref boost::intrusive::derivation_value_traits derivation_value_traits]
class to define a value traits class with a value that stores the
`simple_node` as a base class:
[c++]
#include <boost/intrusive/derivation_value_traits.hpp>
//value_1, value_2, simple_node and simple_node_traits are defined
//as in the previous example...
//...
using namespace boost::intrusive;
//Now define the needed value traits using
typedef derivation_value_traits<value_1, simple_node_traits, normal_link> ValueTraits1;
typedef derivation_value_traits<value_2, simple_node_traits, normal_link> ValueTraits2;
//Now define the containers
typedef list <ValueTraits1> Value1List;
typedef list <ValueTraits2> Value2List;
We can even choose to store `simple_node` as a member of `value_1` and `value_2`
classes and use [classref boost::intrusive::member_value_traits member_value_traits]
to define the needed value traits classes:
[import ../example/doc_advanced_value_traits2.cpp]
[doc_advanced_value_traits2_value_traits]
[endsect]
[endsect]
[section:thread_safety Thread safety guarantees]
@@ -2108,7 +2165,7 @@ and also derives from `test_class`.
You can find the full test code code in the
[@../../perf/perf_list.cpp perf_list.cpp] source file.
[section:performance_results_push_back Back insertions and destruction]
[section:performance_results_push_back Back insertion and destruction]
The first test will measure the benefits we can obtain with intrusive containers
avoiding memory allocations and deallocations . All the objects to be
@@ -2171,7 +2228,7 @@ These are the times in microseconds for each case, and the normalized time:
The results are logical: intrusive lists just need one allocation. The destruction
time of the `normal_link` intrusive container is trivial (complexity: `O(1)`),
whereas `safe_link` and `auto_unlink` intrusive containers need to the hook of
whereas `safe_link` and `auto_unlink` intrusive containers need to put the hook of
erased values' in the default state (complexity: `O(NumElements)`). That's why
`normal_link` intrusive list shines in this test.
@@ -2187,7 +2244,7 @@ a good operating system memory allocator is the reason for this good results.
[section:performance_results_reversing Reversing]
The next test measures the time needed to complete calss to the member function `reverse()`.
The next test measures the time needed to complete calls to the member function `reverse()`.
Values (`test_class` and `itest_class`) and lists are created like explained in the
previous section.
@@ -2405,6 +2462,21 @@ all the objects to be inserted in intrusive containers in containers like `std::
[endsect]
[section:disabling_exceptions Disabling exceptions support]
[*Boost.Intrusive] might be useful in environments where exceptions are not available
or recommendable (like embedded or real-time systems). [*Boost.Intrusive] uses the
global Boost mechanism to disable exception handling, so that if the compiler
configuration disables exceptions, `BOOST_NO_EXCEPTIONS` is defined and exception
handling is disabled.
This mechanism is a global mechanism to disable exceptions. If for any reason,
the user wants to disable exception handling [*only] in [*Boost.Intrusive],
`BOOST_INTRUSIVE_DISABLE_EXCEPTION_HANDLING` can be defined to disable
exception handling in the library.
[endsect]
[section:tested_compilers Tested compilers]
[*Boost.Intrusive] has been tested in the following compilers/platforms:
@@ -2418,6 +2490,7 @@ all the objects to be inserted in intrusive containers in containers like `std::
* Codewarrior 9.4/WinXP
* GCC 3.4.3/Solaris 11
* GCC 4.0/Mac Os 10.4.1
* SunCC 5.8/Solaris 11
[endsect]
@@ -2448,7 +2521,7 @@ helpful discussions.
[endsect]
[xinclude intrusive_doxygen.xml]
[xinclude autodoc.xml]
[section:license_notices License notices]

View File

@@ -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/linking_policy.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 boost::intrusive::list <ValueTraits1> Value1List;
typedef boost::intrusive::list <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;
}
//]

View File

@@ -45,7 +45,7 @@ int main()
//nodes and the container itself must be created in shared memory
const int MaxElem = 100;
const int ShmSize = 50000;
const char *ShmName = "MySharedMemory";
const char *ShmName = "SharedMemoryName";
using namespace boost::interprocess;

View File

@@ -60,6 +60,7 @@ struct legacy_value_traits
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

View File

@@ -111,6 +111,9 @@
<File
RelativePath="..\..\..\..\..\boost\intrusive\circular_slist_algorithms.hpp">
</File>
<File
RelativePath="..\..\..\..\..\boost\intrusive\derivation_value_traits.hpp">
</File>
<File
RelativePath="..\..\..\..\..\boost\intrusive\hashtable.hpp">
</File>
@@ -126,6 +129,9 @@
<File
RelativePath="..\..\..\..\..\boost\intrusive\list_hook.hpp">
</File>
<File
RelativePath="..\..\..\..\..\boost\intrusive\member_value_traits.hpp">
</File>
<File
RelativePath="..\..\..\..\..\boost\intrusive\pointer_plus_bit.hpp">
</File>
@@ -150,6 +156,9 @@
<File
RelativePath="..\..\..\..\..\boost\intrusive\tag.hpp">
</File>
<File
RelativePath="..\..\..\..\..\boost\intrusive\trivial_value_traits.hpp">
</File>
<File
RelativePath="..\..\..\..\..\boost\intrusive\unordered_set.hpp">
</File>
@@ -169,7 +178,7 @@
RelativePath="..\..\..\..\..\boost\intrusive\detail\config_end.hpp">
</File>
<File
RelativePath="..\..\..\..\..\boost\intrusive\detail\ebo_holder.hpp">
RelativePath="..\..\..\..\..\boost\intrusive\detail\ebo_functor_holder.hpp">
</File>
<File
RelativePath="..\..\..\..\..\boost\intrusive\detail\hashtable_node.hpp">
@@ -186,9 +195,6 @@
<File
RelativePath="..\..\..\..\..\boost\intrusive\detail\pointer_to_other.hpp">
</File>
<File
RelativePath="..\..\..\..\..\boost\intrusive\detail\pointer_type.hpp">
</File>
<File
RelativePath="..\..\..\..\..\boost\intrusive\detail\rbtree_node.hpp">
</File>
@@ -225,6 +231,9 @@
<File
RelativePath="..\..\..\test\test_container.hpp">
</File>
<File
RelativePath="..\..\..\test\testvalue.hpp">
</File>
</Filter>
<Filter
Name="example"

View File

@@ -27,6 +27,8 @@
MinimalRebuild="TRUE"
BasicRuntimeChecks="3"
RuntimeLibrary="5"
DisableLanguageExtensions="TRUE"
ForceConformanceInForLoopScope="TRUE"
UsePrecompiledHeader="0"
WarningLevel="3"
Detect64BitPortabilityProblems="TRUE"

View File

@@ -24,6 +24,8 @@
MinimalRebuild="TRUE"
BasicRuntimeChecks="3"
RuntimeLibrary="5"
DisableLanguageExtensions="TRUE"
ForceConformanceInForLoopScope="TRUE"
UsePrecompiledHeader="0"
WarningLevel="3"
Detect64BitPortabilityProblems="TRUE"

View File

@@ -24,6 +24,8 @@
MinimalRebuild="TRUE"
BasicRuntimeChecks="3"
RuntimeLibrary="5"
DisableLanguageExtensions="TRUE"
ForceConformanceInForLoopScope="TRUE"
UsePrecompiledHeader="0"
WarningLevel="3"
Detect64BitPortabilityProblems="TRUE"

View File

@@ -24,6 +24,8 @@
MinimalRebuild="TRUE"
BasicRuntimeChecks="3"
RuntimeLibrary="5"
DisableLanguageExtensions="TRUE"
ForceConformanceInForLoopScope="TRUE"
UsePrecompiledHeader="0"
WarningLevel="3"
Detect64BitPortabilityProblems="TRUE"

View File

@@ -25,6 +25,8 @@
MinimalRebuild="TRUE"
BasicRuntimeChecks="3"
RuntimeLibrary="5"
DisableLanguageExtensions="TRUE"
ForceConformanceInForLoopScope="TRUE"
UsePrecompiledHeader="0"
WarningLevel="3"
Detect64BitPortabilityProblems="TRUE"

View File

@@ -24,6 +24,8 @@
MinimalRebuild="TRUE"
BasicRuntimeChecks="3"
RuntimeLibrary="5"
DisableLanguageExtensions="TRUE"
ForceConformanceInForLoopScope="TRUE"
UsePrecompiledHeader="0"
WarningLevel="3"
Detect64BitPortabilityProblems="TRUE"

View File

@@ -20,6 +20,7 @@
#include <vector>
#include <boost/detail/lightweight_test.hpp>
#include "test_macros.hpp"
#include "test_container.hpp"
using namespace boost::intrusive;
@@ -39,6 +40,20 @@ struct test_list
template<class ValueTraits>
void test_list<ValueTraits>::test_all(std::vector<typename ValueTraits::value_type>& values)
{
typedef boost::intrusive::list
< ValueTraits
, ValueTraits::value_type::constant_time_size
, std::size_t
> list_type;
{
list_type list(values.begin(), values.end());
test::test_container(list);
list.clear();
list.insert(list.end(), values.begin(), values.end());
test::test_sequence_container(list, values);
}
test_front_back(values);
test_sort(values);
test_insert(values);
@@ -46,11 +61,6 @@ void test_list<ValueTraits>::test_all(std::vector<typename ValueTraits::value_ty
test_swap(values);
test_clone(values);
typedef boost::intrusive::list
< ValueTraits
, ValueTraits::value_type::constant_time_size
, std::size_t
> list_type;
list_type testlist(values.begin(), values.end());
list_type testlist2;
}

View File

@@ -19,6 +19,7 @@
#include <vector>
#include <boost/detail/lightweight_test.hpp>
#include "test_macros.hpp"
#include "test_container.hpp"
using namespace boost::intrusive;
@@ -38,6 +39,24 @@ struct test_multiset
template<class ValueTraits>
void test_multiset<ValueTraits>::test_all (std::vector<typename ValueTraits::value_type>& values)
{
typedef multiset
<ValueTraits
,std::less<typename ValueTraits::value_type>
,ValueTraits::value_type::constant_time_size, std::size_t
> multiset_type;
{
multiset_type testset(values.begin(), values.end());
test::test_container(testset);
testset.clear();
testset.insert(values.begin(), values.end());
test::test_common_unordered_and_associative_container(testset, values);
testset.clear();
testset.insert(values.begin(), values.end());
test::test_associative_container(testset, values);
testset.clear();
testset.insert(values.begin(), values.end());
test::test_non_unique_container(testset, values);
}
test_sort(values);
test_insert(values);
test_swap(values);

View File

@@ -19,6 +19,7 @@
#include <vector>
#include <boost/detail/lightweight_test.hpp>
#include "test_macros.hpp"
#include "test_container.hpp"
using namespace boost::intrusive;
@@ -38,6 +39,24 @@ struct test_set
template<class ValueTraits>
void test_set<ValueTraits>::test_all(std::vector<typename ValueTraits::value_type>& values)
{
typedef boost::intrusive::set
<ValueTraits
,std::less<typename ValueTraits::value_type>
,ValueTraits::value_type::constant_time_size, std::size_t
> set_type;
{
set_type testset(values.begin(), values.end());
test::test_container(testset);
testset.clear();
testset.insert(values.begin(), values.end());
test::test_common_unordered_and_associative_container(testset, values);
testset.clear();
testset.insert(values.begin(), values.end());
test::test_associative_container(testset, values);
testset.clear();
testset.insert(values.begin(), values.end());
test::test_unique_container(testset, values);
}
test_sort(values);
test_insert(values);
test_swap(values);

View File

@@ -19,6 +19,7 @@
#include <vector>
#include <boost/detail/lightweight_test.hpp>
#include "test_macros.hpp"
#include "test_container.hpp"
using namespace boost::intrusive;
@@ -41,6 +42,17 @@ template<class ValueTraits>
void test_slist<ValueTraits>
::test_all (std::vector<typename ValueTraits::value_type>& values)
{
typedef boost::intrusive::slist
<ValueTraits
,ValueTraits::value_type::constant_time_size, std::size_t
> list_type;
{
list_type list(values.begin(), values.end());
test::test_container(list);
list.clear();
list.insert(list.end(), values.begin(), values.end());
test::test_sequence_container(list, values);
}
test_front_back (values);
test_sort(values);
test_merge (values);

View File

@@ -1,119 +1,24 @@
//////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2006 Matias Capeletto
// Copyright (c) 2007 Ion Gaztanaga
// (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.
//
/////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_INTRUSIVE_TEST_TEST_CONTAINER_HPP
#define BOOST_INTRUSIVE_TEST_TEST_CONTAINER_HPP
#ifndef BOOST_INTRUSIVE_TEST_CONTAINER_HPP
#define BOOST_INTRUSIVE_TEST_CONTAINER_HPP
// std
#include <cassert>
#include <algorithm>
#include <vector>
// Boost.Test
//#include "boost/test/included/test_exec_monitor.hpp"
#include <boost/detail/lightweight_test.hpp>
namespace boost {
namespace intrusive {
namespace test {
const int NumElem = 5;
/*
Beginning of range a.begin() iterator if a is mutable, const_iterator otherwise [4] [7]
End of range a.end() iterator if a is mutable, const_iterator otherwise [4]
Size a.size() size_type
Maximum size a.max_size() size_type
Empty container a.empty() Convertible to bool
Swap a.swap(b) void
Expression semantics
Semantics of an expression is defined only where it differs from, or is not defined in, Assignable, Equality Comparable, or LessThan Comparable Name Expression Precondition Semantics Postcondition
Move constructor X(a) X().size() == a.size(). X() contains a copy of each of a's elements.
Move constructor X b(a); b.size() == a.size(). b contains a copy of each of a's elements.
Move Assignment operator b = a b.size() == a.size(). b contains a copy of each of a's elements.
Destructor a.~X() Each of a's elements is disposed, and memory allocated for them (if any) is deallocated.
Beginning of range a.begin() Returns an iterator pointing to the first element in the container. [7] a.begin() is either dereferenceable or past-the-end. It is past-the-end if and only if a.size() == 0.
End of range a.end() Returns an iterator pointing one past the last element in the container. a.end() is past-the-end.
Size a.size() Returns the size of the container, that is, its number of elements. [8] a.size() >= 0 && a.size() <= max_size()
Maximum size a.max_size() Returns the largest size that this container can ever have. [8] a.max_size() >= 0 && a.max_size() >= a.size()
Empty container a.empty() Equivalent to a.size() == 0. (But possibly faster.)
Swap a.swap(b) Equivalent to swap(a,b) [9]
*/
/*
expression return type operational assertion/note complexity
semantics pre/post-condition
X::value_type T T is
CopyConstructible
compile time
X::reference lvalue of T compile time
X::const_-
reference
const lvalue of T compile time
X::iterator iterator type
whose value
type is T
any iterator category
except output iterator.
convertible to
X::const_iterator.
compile time
X::const_-
iterator
constant iterator
type whose
value type is T
any iterator category
except output iterator
compile time
X::difference_
type
signed integral
type
is identical to the
difference type of
X::iterator and
X::const_iterator
compile time
X::size_type unsigned
integral type
size_type can
represent any
non-negative value of
compile time
X u; post: u.size() == 0 constant
X(); X().size() == 0 constant
X(a); a == X(a). linear
X u(a); post: u == a linear
X u = a; Equivalent to: X u; u
= a;
(&a)->X(); void note: the destructor is
applied to every
element of a; all the
memory is deallocated.
linear
a.begin(); iterator;
const_-
iterator for
constant a
constant
*/
template< class Container >
void test_container( Container & c )
{
@@ -126,102 +31,231 @@ void test_container( Container & c )
typedef typename Container::const_pointer const_pointer;
typedef typename Container::difference_type difference_type;
typedef typename Container::size_type size_type;
typedef typename Container::difference_type difference_type;
typedef typename Container::size_type size_type;
typedef typename Container::value_traits value_traits;
const size_type num_elem = c.size();
BOOST_CHECK( c.empty() == (num_elem == 0) );
BOOST_TEST( c.empty() == (num_elem == 0) );
{
iterator it(c.begin()), itend(c.end());
size_type i;
for(i = 0; i < num_elem; ++i){
++it;
}
BOOST_CHECK( it == c.end() );
BOOST_CHECK( c.size() == i );
BOOST_TEST( it == c.end() );
BOOST_TEST( c.size() == i );
}
//Check iterator conversion
BOOST_CHECK( const_iterator(c.begin()) == c.cbegin() );
BOOST_TEST( const_iterator(c.begin()) == c.cbegin() );
{
const_iterator it(c.cbegin()), itend(c.cend());
size_type i;
for(i = 0; i < num_elem; ++i){
++it;
}
BOOST_CHECK( it == c.cend() );
BOOST_CHECK( c.size() == i );
BOOST_TEST( it == c.cend() );
BOOST_TEST( c.size() == i );
}
}
/*
template< class Container >
void test_container
( Container & c, typename Container::size_type num_elem
, Container & c2, typename Container::size_type num_elem2)
template< class Container, class Data >
void test_sequence_container(Container & c, Data & d)
{
assert( d.size() > 2 );
c.clear();
BOOST_TEST( c.size() == 0 );
BOOST_TEST( c.empty() );
c.insert( c.begin(), *d.begin() );
c.insert( c.end(), *(++d.begin()) );
BOOST_TEST( c.size() == 2 );
BOOST_TEST( !c.empty() );
c.erase( c.begin() );
BOOST_TEST( c.size() == 1 );
c.insert( c.begin(), *(++++d.begin()) );
c.erase( c.begin(), c.end() );
BOOST_TEST( c.empty() );
c.insert( c.begin(), *d.begin() );
BOOST_TEST( c.size() == 1 );
BOOST_TEST( c.begin() != c.end() );
c.erase( c.begin() );
c.assign(d.begin(), d.end());
BOOST_TEST( c.size() == d.size() );
c.clear();
BOOST_TEST( c.size() == 0 );
BOOST_TEST( c.empty() );
}
template< class Container, class Data >
void test_common_unordered_and_associative_container(Container & c, Data & d)
{
typedef typename Container::value_type value_type;
typedef typename Container::iterator iterator;
typedef typename Container::const_iterator const_iterator;
typedef typename Container::reference reference;
typedef typename Container::const_reference const_reference;
typedef typename Container::pointer pointer;
typedef typename Container::const_pointer const_pointer;
typedef typename Container::difference_type difference_type;
typedef typename Container::size_type size_type;
//For the future:
//
//move-copy constructor
//move-assignment
assert( d.size() > 2 );
test_container_helper(c, num_elem);
test_container_helper(c2, num_elem2);
c.clear();
c.insert(d.begin(), d.end());
//Test swap and test again
c.swap(c2);
test_container_helper(c, num_elem2);
test_container_helper(c2, num_elem);
}*/
template< class Sequence >
void test_sequence( Sequence & seq )
for( typename Data::const_iterator di = d.begin(), de = d.end();
di != de; ++di )
{
//First the container requirements
test_container(seq);
typedef Sequence::value_type value_type;
typedef Sequence::iterator iterator;
Sequence::size_type old_size(seq.size());
//Now test sequence requirements
//insert(p, t)
Sequence::value_type one(1);
iterator one_pos = seq.insert(seq.begin(), one);
BOOST_CHECK( &*seq.begin() == &one );
BOOST_CHECK( seq.size() == (old_size + 1) );
//insert(p, i, j)
value_type range[2] = { value_type(2), value_type(3) };
iterator range_it = one_pos; ++range_it;
seq.insert(range_it, &range[0], &range[2]);
BOOST_CHECK( seq.size() == (old_size + 3) );
range_it = ++seq.begin();
BOOST_CHECK( &*range_it == &range[0] );
++range_it;
BOOST_CHECK( &*range_it == &range[1] );
//erase(q)
iterator it_from_erase = seq.erase(seq.begin());
BOOST_CHECK( seq.size() == (old_size + 2) );
BOOST_CHECK( &*it_from_erase == &range[0] );
//erase(q1, q2)
iterator q1(it_from_erase), q2(it_from_erase);
++++q2;
it_from_erase = seq.erase(q1, q2);
BOOST_CHECK( seq.size() == old_size );
//clear(), assign()???
BOOST_TEST( c.find(*di) != c.end() );
}
} // namespace test{
} // namespace intrusive{
} // namespace boost{
typename Data::const_iterator da = d.begin();
typename Data::const_iterator db = ++d.begin();
#endif // BOOST_INTRUSIVE_TEST_TEST_CONTAINER_HPP
size_type old_size = c.size();
c.erase(*da);
BOOST_TEST( c.size() == old_size-1 );
BOOST_TEST( c.count(*da) == 0 );
BOOST_TEST( c.count(*db) != 0 );
BOOST_TEST( c.find(*da) == c.end() );
BOOST_TEST( c.find(*db) != c.end() );
BOOST_TEST( c.equal_range(*db).first != c.end() );
c.clear();
BOOST_TEST( c.equal_range(*da).first == c.end() );
}
template< class Container, class Data >
void test_associative_container_invariants(Container & c, Data & d)
{
typedef typename Container::const_iterator const_iterator;
for( typename Data::const_iterator di = d.begin(), de = d.end();
di != de; ++di)
{
const_iterator ci = c.find(*di);
BOOST_TEST( ci != c.end() );
BOOST_TEST( ! c.value_comp()(*ci, *di) );
const_iterator cil = c.lower_bound(*di);
const_iterator ciu = c.upper_bound(*di);
std::pair<const_iterator, const_iterator> er = c.equal_range(*di);
BOOST_TEST( cil == er.first );
BOOST_TEST( ciu == er.second );
if(ciu != c.end()){
BOOST_TEST( c.value_comp()(*cil, *ciu) );
}
if(c.count(*di) > 1){
const_iterator ci_next = cil; ++ci_next;
for( ; ci_next != ciu; ++cil, ++ci_next){
BOOST_TEST( !c.value_comp()(*ci_next, *cil) );
}
}
}
}
template< class Container, class Data >
void test_associative_container(Container & c, Data & d)
{
typedef typename Container::const_iterator const_iterator;
assert( d.size() > 2 );
c.clear();
c.insert(d.begin(),d.end());
test_associative_container_invariants(c, d);
const Container & cr = c;
test_associative_container_invariants(cr, d);
}
template< class Container, class Data >
void test_unordered_associative_container_invariants(Container & c, Data & d)
{
typedef typename Container::size_type size_type;
typedef typename Container::const_iterator const_iterator;
for( typename Data::const_iterator di = d.begin(), de = d.end() ;
di != de ; ++di ){
const_iterator i = c.find(*di);
size_type nb = c.bucket(*i);
size_type bucket_elem = std::distance(c.begin(nb), c.end(nb));
BOOST_TEST( bucket_elem == c.bucket_size(nb) );
BOOST_TEST( &*c.local_iterator_to(*c.find(*di)) == &*i );
std::pair<const_iterator, const_iterator> er = c.equal_range(*di);
size_type cnt = std::distance(er.first, er.second);
BOOST_TEST( cnt == c.count(*di));
if(cnt > 1)
for(const_iterator n = er.first, i = n++, e = er.second; n != e; ++i, ++n){
BOOST_TEST( c.key_eq()(*i, *n) );
BOOST_TEST( c.hash_function()(*i) == c.hash_function()(*n) );
}
}
size_type blen = c.bucket_count();
size_type total_objects = 0;
for(size_type i = 0; i < blen; ++i){
total_objects += c.bucket_size(i);
}
BOOST_TEST( total_objects == c.size() );
}
template< class Container, class Data >
void test_unordered_associative_container(Container & c, Data & d)
{
c.clear();
c.insert( d.begin(), d.end() );
test_unordered_associative_container_invariants(c, d);
const Container & cr = c;
test_unordered_associative_container_invariants(cr, d);
}
template< class Container, class Data >
void test_unique_container(Container & c, Data & d)
{
typedef typename Container::value_type value_type;
c.clear();
c.insert(d.begin(),d.end());
typename Container::size_type old_size = c.size();
value_type v(*d.begin());
c.insert(v);
BOOST_TEST( c.size() == old_size );
c.clear();
}
template< class Container, class Data >
void test_non_unique_container(Container & c, Data & d)
{
typedef typename Container::value_type value_type;
c.clear();
c.insert(d.begin(),d.end());
typename Container::size_type old_size = c.size();
value_type v(*d.begin());
c.insert(v);
BOOST_TEST( c.size() == (old_size+1) );
c.clear();
}
}}}
#endif //#ifndef BOOST_INTRUSIVE_TEST_CONTAINER_HPP

View File

@@ -21,6 +21,7 @@
#include <set>
#include <boost/detail/lightweight_test.hpp>
#include "test_macros.hpp"
#include "test_container.hpp"
using namespace boost::intrusive;
@@ -43,6 +44,27 @@ struct test_unordered_multiset
template<class ValueTraits>
void test_unordered_multiset<ValueTraits>::test_all (std::vector<typename ValueTraits::value_type>& values)
{
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];
unordered_multiset_type testset(buckets, BucketSize);
testset.insert(values.begin(), values.end());
test::test_container(testset);
testset.clear();
testset.insert(values.begin(), values.end());
test::test_common_unordered_and_associative_container(testset, values);
testset.clear();
testset.insert(values.begin(), values.end());
test::test_unordered_associative_container(testset, values);
testset.clear();
testset.insert(values.begin(), values.end());
test::test_non_unique_container(testset, values);
}
test_sort(values);
test_insert(values);
test_swap(values);

View File

@@ -20,6 +20,7 @@
#include <set>
#include <boost/detail/lightweight_test.hpp>
#include "test_macros.hpp"
#include "test_container.hpp"
using namespace boost::intrusive;
@@ -42,6 +43,27 @@ struct test_unordered_set
template<class ValueTraits>
void test_unordered_set<ValueTraits>::test_all(std::vector<typename ValueTraits::value_type>& values)
{
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];
unordered_set_type testset(buckets, BucketSize);
testset.insert(values.begin(), values.end());
test::test_container(testset);
testset.clear();
testset.insert(values.begin(), values.end());
test::test_common_unordered_and_associative_container(testset, values);
testset.clear();
testset.insert(values.begin(), values.end());
test::test_unordered_associative_container(testset, values);
testset.clear();
testset.insert(values.begin(), values.end());
test::test_unique_container(testset, values);
}
test_sort(values);
test_insert(values);
test_swap(values);