forked from boostorg/intrusive
Intrusive:
* Added `linear<>` and `cache_last<>` options to singly linked lists. * Added `optimize_multikey<>` option to unordered container hooks. * Optimized unordered containers when `store_hash` option is used in the hook. * Implementation changed to be exception agnostic so that it can be used in environments without exceptions. * Added `container_from_iterator` function to tree-based containers. Interprocess: * Added anonymous shared memory for UNIX systems. * Fixed file lock compilation errors [SVN r44819]
This commit is contained in:
@@ -528,7 +528,25 @@ chapters:
|
|||||||
small for user classes (usually the size of two pointers). Many operations have
|
small for user classes (usually the size of two pointers). Many operations have
|
||||||
constant time complexity.
|
constant time complexity.
|
||||||
|
|
||||||
* [*set/multiset]: A `std::set/std::multiset` like intrusive associative containers.
|
* [*set/multiset/rbtree]: A `std::set/std::multiset` like intrusive associative containers
|
||||||
|
based on red-black trees.
|
||||||
|
The size overhead is moderate for user classes (usually the size of three pointers).
|
||||||
|
Many operations have logarithmic time complexity.
|
||||||
|
|
||||||
|
* [*avl_set/avl_multiset/avltree]: A `std::set/std::multiset` like intrusive associative
|
||||||
|
containers based on AVL trees.
|
||||||
|
The size overhead is moderate for user classes (usually the size of three pointers).
|
||||||
|
Many operations have logarithmic time complexity.
|
||||||
|
|
||||||
|
* [*splay_set/splay_multiset/splaytree]: A `std::set/std::multiset` like intrusive associative
|
||||||
|
containers based on splay trees. Splay trees have no constant operations, but they
|
||||||
|
have some interesting caching properties.
|
||||||
|
The size overhead is moderate for user classes (usually the size of three pointers).
|
||||||
|
Many operations have logarithmic time complexity.
|
||||||
|
|
||||||
|
* [*sg_set/sg_multiset/sgtree]: A `std::set/std::multiset` like intrusive associative
|
||||||
|
containers based on scapegoat trees. Scapegoat can be configured with the desired
|
||||||
|
balance factor to achieve the desised rebalancing frequency/search time compromise.
|
||||||
The size overhead is moderate for user classes (usually the size of three pointers).
|
The size overhead is moderate for user classes (usually the size of three pointers).
|
||||||
Many operations have logarithmic time complexity.
|
Many operations have logarithmic time complexity.
|
||||||
|
|
||||||
@@ -539,7 +557,7 @@ chapters:
|
|||||||
The size overhead is moderate for user classes (an average of two pointers per element).
|
The size overhead is moderate for user classes (an average of two pointers per element).
|
||||||
Many operations have an amortized constant time complexity.
|
Many operations have an amortized constant time complexity.
|
||||||
|
|
||||||
Each of these intrusive containers can be configured with constant or linear time
|
Most of these intrusive containers can be configured with constant or linear time
|
||||||
size:
|
size:
|
||||||
|
|
||||||
* [*Linear time size]: The intrusive container doesn't hold a size member that it's
|
* [*Linear time size]: The intrusive container doesn't hold a size member that it's
|
||||||
@@ -753,7 +771,7 @@ linear time complexity, even some that usually are constant time, like
|
|||||||
only provides forward iterators.
|
only provides forward iterators.
|
||||||
|
|
||||||
For most cases, a doubly linked list is preferrable because it offers more
|
For most cases, a doubly linked list is preferrable because it offers more
|
||||||
constant-time functions with a slightly bigger overhead.
|
constant-time functions with a slightly bigger size overhead.
|
||||||
However, for some applications like
|
However, for some applications like
|
||||||
constructing more elaborated containers, singly linked lists are essential
|
constructing more elaborated containers, singly linked lists are essential
|
||||||
because of their low size overhead.
|
because of their low size overhead.
|
||||||
@@ -784,7 +802,8 @@ Like the rest of [*Boost.Intrusive] containers,
|
|||||||
it [classref boost::intrusive::slist slist]-compatible.
|
it [classref boost::intrusive::slist slist]-compatible.
|
||||||
|
|
||||||
[classref boost::intrusive::slist_base_hook slist_base_hook] and
|
[classref boost::intrusive::slist_base_hook slist_base_hook] and
|
||||||
[classref boost::intrusive::slist_member_hook slist_member_hook] receive the same options explained in
|
[classref boost::intrusive::slist_member_hook slist_member_hook]
|
||||||
|
receive the same options explained in
|
||||||
the section [link intrusive.usage How to use Boost.Intrusive]:
|
the section [link intrusive.usage How to use Boost.Intrusive]:
|
||||||
|
|
||||||
* [*`tag<class Tag>`] (for base hooks only): This argument serves as a tag,
|
* [*`tag<class Tag>`] (for base hooks only): This argument serves as a tag,
|
||||||
@@ -807,7 +826,7 @@ the section [link intrusive.usage How to use Boost.Intrusive]:
|
|||||||
template <class T, class ...Options>
|
template <class T, class ...Options>
|
||||||
class slist;
|
class slist;
|
||||||
|
|
||||||
[classref boost::intrusive::slist slist] receives the same options explained in
|
[classref boost::intrusive::slist slist] receives the options explained in
|
||||||
the section [link intrusive.usage How to use Boost.Intrusive]:
|
the section [link intrusive.usage How to use Boost.Intrusive]:
|
||||||
|
|
||||||
* [*`base_hook<class Hook>`] / [*`member_hook<class T, class Hook, Hook T::* PtrToMember>`] /
|
* [*`base_hook<class Hook>`] / [*`member_hook<class T, class Hook, Hook T::* PtrToMember>`] /
|
||||||
@@ -819,7 +838,23 @@ the section [link intrusive.usage How to use Boost.Intrusive]:
|
|||||||
Default: `constant_time_size<true>`
|
Default: `constant_time_size<true>`
|
||||||
|
|
||||||
* [*`size_type<bool Enabled>`]: To specify the type that will be used to store the size
|
* [*`size_type<bool Enabled>`]: To specify the type that will be used to store the size
|
||||||
of the container. Default: `size_type<std::size_t>`
|
of the container. Default: `size_type<std::size_t>`.
|
||||||
|
|
||||||
|
[classref boost::intrusive::slist slist] can receive additional options:
|
||||||
|
|
||||||
|
* [*`linear<bool Enable>`]: the singly linked list is implemented as a
|
||||||
|
null-terminated list instead of a circular list. This allows `O(1)` swap,
|
||||||
|
but losses some operations like `container_from_end_iterator`.
|
||||||
|
* [*`cache_last<bool Enable>`]: the singly linked also stores a pointer to the
|
||||||
|
last element of the singly linked list. This allows `O(1)` swap,
|
||||||
|
`splice_after(iterator, slist &)` and makes the list offer new functions
|
||||||
|
like `push_back(reference)` and `back()`. Logically, the size an empty list is
|
||||||
|
increased in `sizeof(void_pointer)` and the the cached last node pointer must
|
||||||
|
be updated in every operation, and that might incur in a slight performance impact.
|
||||||
|
|
||||||
|
`auto_unlink` hooks are not usable if `linear<true>` and/or `cache_last<true>` options are
|
||||||
|
used. If `auto_unlink` hooks are used and those options are specified, a static
|
||||||
|
assertion will be raised.
|
||||||
|
|
||||||
[endsect]
|
[endsect]
|
||||||
|
|
||||||
@@ -1151,6 +1186,11 @@ Apart from them, these hooks offer additional options:
|
|||||||
rehashing is frequent or hashing the value is a slow operation.
|
rehashing is frequent or hashing the value is a slow operation.
|
||||||
Default: `store_hash<false>`.
|
Default: `store_hash<false>`.
|
||||||
|
|
||||||
|
* [*`optimize_multikey<bool Enabled>`]: This option reserves additional space in
|
||||||
|
the hook that will be used to group equal elements in unordered multisets,
|
||||||
|
improving significantly the performance when many equal values are inserted
|
||||||
|
in these containers. Default: `optimize_multikey<false>`.
|
||||||
|
|
||||||
[endsect]
|
[endsect]
|
||||||
|
|
||||||
[section:unordered_set_unordered_multiset_containers unordered_set and unordered_multiset containers]
|
[section:unordered_set_unordered_multiset_containers unordered_set and unordered_multiset containers]
|
||||||
@@ -1210,7 +1250,7 @@ receive the same options explained in the section
|
|||||||
* [*`size_type<bool Enabled>`]: To specify the type that will be used to store the size
|
* [*`size_type<bool Enabled>`]: To specify the type that will be used to store the size
|
||||||
of the container. Default: `size_type<std::size_t>`
|
of the container. Default: `size_type<std::size_t>`
|
||||||
|
|
||||||
And they also can receive two additional options:
|
And they also can receive additional options:
|
||||||
|
|
||||||
* [*`equal<class Equal>`]: Equality function for the objects to be inserted
|
* [*`equal<class Equal>`]: Equality function for the objects to be inserted
|
||||||
in containers. Default: `equal< std::equal_to<T> >`
|
in containers. Default: `equal< std::equal_to<T> >`
|
||||||
@@ -1228,7 +1268,14 @@ And they also can receive two additional options:
|
|||||||
modulo operations and for some applications modulo operations can impose
|
modulo operations and for some applications modulo operations can impose
|
||||||
a considerable overhead. In debug mode an assertion will be raised if the user
|
a considerable overhead. In debug mode an assertion will be raised if the user
|
||||||
provides a bucket length that is not power of two.
|
provides a bucket length that is not power of two.
|
||||||
Default: `constant_time_size<false>`.
|
Default: `power_2_buckets<false>`.
|
||||||
|
|
||||||
|
* [*`cache_begin<bool Enabled>`]: Due to its internal structure, finding the first
|
||||||
|
element of an unordered container (`begin()` operation) is
|
||||||
|
amortized constant-time. It's possible to speed up `begin()` and other operations
|
||||||
|
related to it (like `clear()`) if the container caches internally the position
|
||||||
|
of the first element. This imposes the overhead of one pointer to the size
|
||||||
|
of the container. Default: `cache_begin<false>`.
|
||||||
|
|
||||||
[endsect]
|
[endsect]
|
||||||
|
|
||||||
@@ -1301,13 +1348,13 @@ more frequently accessed than others, splay trees perform faster searches than e
|
|||||||
balanced binary trees (such as red-black trees).
|
balanced binary trees (such as red-black trees).
|
||||||
|
|
||||||
The caching effect offered by splay trees comes with a cost: the tree must be
|
The caching effect offered by splay trees comes with a cost: the tree must be
|
||||||
rebalanced when a element is searched. This disallows const versions of search
|
rebalanced when an element is searched. This disallows const versions of search
|
||||||
functions like `find()`, `lower_bound()`, `upper_bound()`, `equal_range()`,
|
functions like `find()`, `lower_bound()`, `upper_bound()`, `equal_range()`,
|
||||||
`count()`...
|
`count()`...
|
||||||
|
|
||||||
Because of this, splay-tree based associative containers are not drop-in
|
Because of this, splay-tree based associative containers are not drop-in
|
||||||
replacements of [classref boost::intrusive::set set]/
|
replacements of [classref boost::intrusive::set set]/
|
||||||
[classref boost::intrusive::splay_set splay_set].
|
[classref boost::intrusive::multiset multiset].
|
||||||
|
|
||||||
Apart from this, if element searches are randomized, the tree will be rebalanced
|
Apart from this, if element searches are randomized, the tree will be rebalanced
|
||||||
without taking advantage of the cache effect, so splay trees can offer worse
|
without taking advantage of the cache effect, so splay trees can offer worse
|
||||||
@@ -1565,22 +1612,22 @@ time, scapegoat trees have no additional per-node overhead compared to a regular
|
|||||||
search tree.
|
search tree.
|
||||||
|
|
||||||
A binary search tree is said to be weight balanced if half the nodes are on the left
|
A binary search tree is said to be weight balanced if half the nodes are on the left
|
||||||
of the root, and half on the right. An α-height-balanced tree is defined with defined
|
of the root, and half on the right. An a-height-balanced tree is defined with defined
|
||||||
with the following equation:
|
with the following equation:
|
||||||
|
|
||||||
[*['height(tree) <= log1/α(tree.size())]]
|
[*['height(tree) <= log1/a(tree.size())]]
|
||||||
|
|
||||||
* [*['α == 1]]: A tree forming a linked list is considered balanced.
|
* [*['a == 1]]: A tree forming a linked list is considered balanced.
|
||||||
* [*['α == 0.5]]: Only a perfectly balanced binary is considered balanced.
|
* [*['a == 0.5]]: Only a perfectly balanced binary is considered balanced.
|
||||||
|
|
||||||
Scapegoat trees are loosely ['α-height-balanced] so:
|
Scapegoat trees are loosely ['a-height-balanced] so:
|
||||||
|
|
||||||
[*['height(tree) <= log1/α(tree.size()) + 1]]
|
[*['height(tree) <= log1/a(tree.size()) + 1]]
|
||||||
|
|
||||||
Scapegoat trees support any α between 0.5 and 1. If α is higher, the tree is rebalanced
|
Scapegoat trees support any a between 0.5 and 1. If a is higher, the tree is rebalanced
|
||||||
less often, obtaining quicker insertions but slower searches. Lower
|
less often, obtaining quicker insertions but slower searches. Lower
|
||||||
α values improve search times. Scapegoat-trees implemented in [*Boost.Intrusive] offer the possibility of
|
a values improve search times. Scapegoat-trees implemented in [*Boost.Intrusive] offer the possibility of
|
||||||
[*changing α at run-time] taking advantage of the flexibility of scapegoat trees.
|
[*changing a at run-time] taking advantage of the flexibility of scapegoat trees.
|
||||||
For more information on scapegoat trees see [@http://en.wikipedia.org/wiki/Scapegoat_tree Wikipedia entry].
|
For more information on scapegoat trees see [@http://en.wikipedia.org/wiki/Scapegoat_tree Wikipedia entry].
|
||||||
|
|
||||||
Scapegoat trees also have downsides:
|
Scapegoat trees also have downsides:
|
||||||
@@ -1591,7 +1638,7 @@ Scapegoat trees also have downsides:
|
|||||||
tree is also considerably increased.
|
tree is also considerably increased.
|
||||||
|
|
||||||
* The operations needed to determine if the tree is unbalanced require floating-point
|
* The operations needed to determine if the tree is unbalanced require floating-point
|
||||||
operations like ['log1/α]. If the system has no floating point operations (like some
|
operations like ['log1/a]. If the system has no floating point operations (like some
|
||||||
embedded systems), scapegoat tree operations might become slow.
|
embedded systems), scapegoat tree operations might become slow.
|
||||||
|
|
||||||
[*Boost.Intrusive] offers 3 containers based on scapegoat trees:
|
[*Boost.Intrusive] offers 3 containers based on scapegoat trees:
|
||||||
@@ -1689,9 +1736,9 @@ And they also can receive additional options:
|
|||||||
|
|
||||||
* [*`floating_point<bool Enable>`]:
|
* [*`floating_point<bool Enable>`]:
|
||||||
When this option is deactivated, the scapegoat tree loses the ability to change
|
When this option is deactivated, the scapegoat tree loses the ability to change
|
||||||
the balance factor α at run-time, but the size of an empty container is reduced
|
the balance factor a at run-time, but the size of an empty container is reduced
|
||||||
and no floating point operations are performed, normally increasing container
|
and no floating point operations are performed, normally increasing container
|
||||||
performance. The fixed α factor that is used when this option is activated
|
performance. The fixed a factor that is used when this option is activated
|
||||||
is ['1/sqrt(2) ~ 0,70711]. Default: `floating_point<true>`
|
is ['1/sqrt(2) ~ 0,70711]. Default: `floating_point<true>`
|
||||||
|
|
||||||
[endsect]
|
[endsect]
|
||||||
@@ -2523,6 +2570,63 @@ For a complete list of functions see
|
|||||||
|
|
||||||
[endsect]
|
[endsect]
|
||||||
|
|
||||||
|
[/
|
||||||
|
/
|
||||||
|
/[section:sgtree_algorithms Intrusive sg tree algorithms]
|
||||||
|
/
|
||||||
|
/
|
||||||
|
/[classref boost::intrusive::sgtree_algorithms sgtree_algorithms] have the same
|
||||||
|
/interface as [classref boost::intrusive::rbtree_algorithms rbtree_algorithms].
|
||||||
|
/
|
||||||
|
/[c++]
|
||||||
|
/
|
||||||
|
/ template<class NodeTraits>
|
||||||
|
/ struct sgtree_algorithms;
|
||||||
|
/
|
||||||
|
/[classref boost::intrusive::sgtree_algorithms sgtree_algorithms]
|
||||||
|
/is configured with a NodeTraits class, which encapsulates
|
||||||
|
/the information about the node to be manipulated. NodeTraits must support the
|
||||||
|
/following interface:
|
||||||
|
/
|
||||||
|
/[*Typedefs]:
|
||||||
|
/
|
||||||
|
/* `node`: The type of the node that forms the circular sgtree
|
||||||
|
/
|
||||||
|
/* `node_ptr`: The type of a pointer to a node (usually node*)
|
||||||
|
/
|
||||||
|
/* `const_node_ptr`: The type of a pointer to a const node (usually const node*)
|
||||||
|
/
|
||||||
|
/[*Static functions]:
|
||||||
|
/
|
||||||
|
/* `static node_ptr get_parent(const_node_ptr n);`:
|
||||||
|
/ Returns a pointer to the parent node stored in "n".
|
||||||
|
/
|
||||||
|
/* `static void set_parent(node_ptr n, node_ptr p);`:
|
||||||
|
/ Sets the pointer to the parent node stored in "n" to "p".
|
||||||
|
/
|
||||||
|
/* `static node_ptr get_left(const_node_ptr n);`:
|
||||||
|
/ Returns a pointer to the left node stored in "n".
|
||||||
|
/
|
||||||
|
/* `static void set_left(node_ptr n, node_ptr l);`:
|
||||||
|
/ Sets the pointer to the left node stored in "n" to "l".
|
||||||
|
/
|
||||||
|
/* `static node_ptr get_right(const_node_ptr n);`:
|
||||||
|
/ Returns a pointer to the right node stored in "n".
|
||||||
|
/
|
||||||
|
/* `static void set_right(node_ptr n, node_ptr r);`:
|
||||||
|
/ Sets the pointer to the right node stored in "n" to "r".
|
||||||
|
/
|
||||||
|
/Once we have a node traits configuration we can use [*Boost.Intrusive] algorithms
|
||||||
|
/with our nodes:
|
||||||
|
/
|
||||||
|
/[import ../example/doc_sgtree_algorithms.cpp]
|
||||||
|
/[doc_sgtree_algorithms_code]
|
||||||
|
/
|
||||||
|
/For a complete list of functions see
|
||||||
|
/[classref boost::intrusive::sgtree_algorithms sgtree_algorithms reference].
|
||||||
|
/
|
||||||
|
/[endsect]
|
||||||
|
/]
|
||||||
[endsect]
|
[endsect]
|
||||||
|
|
||||||
[section:value_traits Containers with custom ValueTraits]
|
[section:value_traits Containers with custom ValueTraits]
|
||||||
@@ -3104,7 +3208,7 @@ lists need to perform the same operations.
|
|||||||
These are the results:
|
These are the results:
|
||||||
|
|
||||||
[table Reverse times for Visual C++ 7.1 / Windows XP
|
[table Reverse times for Visual C++ 7.1 / Windows XP
|
||||||
[[Container] [Time in us/iteration (small object / big object)] [Normalized time (small object / big object) (small object / big object)]]
|
[[Container] [Time in us/iteration (small object / big object)] [Normalized time (small object / big object)]]
|
||||||
[[`normal_link` intrusive list] [2656 / 10625] [1 / 1.83]]
|
[[`normal_link` intrusive list] [2656 / 10625] [1 / 1.83]]
|
||||||
[[`safe_link` intrusive list] [2812 / 10937] [1.05 / 1.89]]
|
[[`safe_link` intrusive list] [2812 / 10937] [1.05 / 1.89]]
|
||||||
[[`auto_unlink` intrusive list] [2710 / 10781] [1.02 / 1.86]]
|
[[`auto_unlink` intrusive list] [2710 / 10781] [1.02 / 1.86]]
|
||||||
@@ -3310,18 +3414,18 @@ all the objects to be inserted in intrusive containers in containers like `std::
|
|||||||
|
|
||||||
[endsect]
|
[endsect]
|
||||||
|
|
||||||
[section:disabling_exceptions Disabling exceptions support]
|
[section:release_notes Release Notes]
|
||||||
|
|
||||||
[*Boost.Intrusive] might be useful in environments where exceptions are not available
|
[section:release_notes_boost_1_36_00 Boost 1.36 Release]
|
||||||
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,
|
* Added `linear<>` and `cache_last<>` options to singly linked lists.
|
||||||
the user wants to disable exception handling [*only] in [*Boost.Intrusive],
|
* Added `optimize_multikey<>` option to unordered container hooks.
|
||||||
`BOOST_INTRUSIVE_DISABLE_EXCEPTION_HANDLING` can be defined to disable
|
* Optimized unordered containers when `store_hash` option is used in the hook.
|
||||||
exception handling in the library.
|
* Implementation changed to be exception agnostic so that it can be used
|
||||||
|
in environments without exceptions.
|
||||||
|
* Added `container_from_iterator` function to tree-based containers.
|
||||||
|
|
||||||
|
[endsect]
|
||||||
|
|
||||||
[endsect]
|
[endsect]
|
||||||
|
|
||||||
@@ -3331,13 +3435,13 @@ exception handling in the library.
|
|||||||
|
|
||||||
* Visual 7.1/WinXP
|
* Visual 7.1/WinXP
|
||||||
* Visual 8.0/WinXP
|
* Visual 8.0/WinXP
|
||||||
|
* Visual 9.0/WinXP
|
||||||
* GCC 4.1.1/MinGW
|
* GCC 4.1.1/MinGW
|
||||||
* GCC 3.4.4/Cygwin
|
* GCC 3.4.4/Cygwin
|
||||||
* Intel 9.1/WinXP
|
* Intel 9.1/WinXP
|
||||||
* GCC 4.1.2/Linux
|
* GCC 4.1.2/Linux
|
||||||
* GCC 3.4.3/Solaris 11
|
* GCC 3.4.3/Solaris 11
|
||||||
* GCC 4.0/Mac Os 10.4.1
|
* GCC 4.0/Mac Os 10.4.1
|
||||||
* SunCC 5.8/Solaris 11
|
|
||||||
|
|
||||||
[endsect]
|
[endsect]
|
||||||
|
|
||||||
|
@@ -240,7 +240,7 @@ class avl_set_impl
|
|||||||
//! <b>Precondition</b>: end_iterator must be a valid end const_iterator
|
//! <b>Precondition</b>: end_iterator must be a valid end const_iterator
|
||||||
//! of avl_set.
|
//! of avl_set.
|
||||||
//!
|
//!
|
||||||
//! <b>Effects</b>: Returns a const reference to the avl_set associated to the end iterator
|
//! <b>Effects</b>: Returns a const reference to the set associated to the end iterator
|
||||||
//!
|
//!
|
||||||
//! <b>Throws</b>: Nothing.
|
//! <b>Throws</b>: Nothing.
|
||||||
//!
|
//!
|
||||||
@@ -252,6 +252,34 @@ class avl_set_impl
|
|||||||
, &avl_set_impl::tree_);
|
, &avl_set_impl::tree_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//! <b>Precondition</b>: it must be a valid iterator of set.
|
||||||
|
//!
|
||||||
|
//! <b>Effects</b>: Returns a reference to the set associated to the iterator
|
||||||
|
//!
|
||||||
|
//! <b>Throws</b>: Nothing.
|
||||||
|
//!
|
||||||
|
//! <b>Complexity</b>: Logarithmic.
|
||||||
|
static avl_set_impl &container_from_iterator(iterator it)
|
||||||
|
{
|
||||||
|
return *detail::parent_from_member<avl_set_impl, tree_type>
|
||||||
|
( &tree_type::container_from_iterator(it)
|
||||||
|
, &avl_set_impl::tree_);
|
||||||
|
}
|
||||||
|
|
||||||
|
//! <b>Precondition</b>: it must be a valid const_iterator of set.
|
||||||
|
//!
|
||||||
|
//! <b>Effects</b>: Returns a const reference to the set associated to the iterator
|
||||||
|
//!
|
||||||
|
//! <b>Throws</b>: Nothing.
|
||||||
|
//!
|
||||||
|
//! <b>Complexity</b>: Logarithmic.
|
||||||
|
static const avl_set_impl &container_from_iterator(const_iterator it)
|
||||||
|
{
|
||||||
|
return *detail::parent_from_member<avl_set_impl, tree_type>
|
||||||
|
( &tree_type::container_from_iterator(it)
|
||||||
|
, &avl_set_impl::tree_);
|
||||||
|
}
|
||||||
|
|
||||||
//! <b>Effects</b>: Returns the key_compare object used by the avl_set.
|
//! <b>Effects</b>: Returns the key_compare object used by the avl_set.
|
||||||
//!
|
//!
|
||||||
//! <b>Complexity</b>: Constant.
|
//! <b>Complexity</b>: Constant.
|
||||||
@@ -1085,6 +1113,12 @@ class avl_set
|
|||||||
|
|
||||||
static const avl_set &container_from_end_iterator(const_iterator end_iterator)
|
static const avl_set &container_from_end_iterator(const_iterator end_iterator)
|
||||||
{ return static_cast<const avl_set &>(Base::container_from_end_iterator(end_iterator)); }
|
{ return static_cast<const avl_set &>(Base::container_from_end_iterator(end_iterator)); }
|
||||||
|
|
||||||
|
static avl_set &container_from_iterator(iterator end_iterator)
|
||||||
|
{ return static_cast<avl_set &>(Base::container_from_iterator(end_iterator)); }
|
||||||
|
|
||||||
|
static const avl_set &container_from_iterator(const_iterator end_iterator)
|
||||||
|
{ return static_cast<const avl_set &>(Base::container_from_iterator(end_iterator)); }
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -1317,6 +1351,34 @@ class avl_multiset_impl
|
|||||||
, &avl_multiset_impl::tree_);
|
, &avl_multiset_impl::tree_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//! <b>Precondition</b>: it must be a valid iterator of multiset.
|
||||||
|
//!
|
||||||
|
//! <b>Effects</b>: Returns a const reference to the multiset associated to the iterator
|
||||||
|
//!
|
||||||
|
//! <b>Throws</b>: Nothing.
|
||||||
|
//!
|
||||||
|
//! <b>Complexity</b>: Logarithmic.
|
||||||
|
static avl_multiset_impl &container_from_iterator(iterator it)
|
||||||
|
{
|
||||||
|
return *detail::parent_from_member<avl_multiset_impl, tree_type>
|
||||||
|
( &tree_type::container_from_iterator(it)
|
||||||
|
, &avl_multiset_impl::tree_);
|
||||||
|
}
|
||||||
|
|
||||||
|
//! <b>Precondition</b>: it must be a valid const_iterator of multiset.
|
||||||
|
//!
|
||||||
|
//! <b>Effects</b>: Returns a const reference to the multiset associated to the iterator
|
||||||
|
//!
|
||||||
|
//! <b>Throws</b>: Nothing.
|
||||||
|
//!
|
||||||
|
//! <b>Complexity</b>: Logarithmic.
|
||||||
|
static const avl_multiset_impl &container_from_iterator(const_iterator it)
|
||||||
|
{
|
||||||
|
return *detail::parent_from_member<avl_multiset_impl, tree_type>
|
||||||
|
( &tree_type::container_from_iterator(it)
|
||||||
|
, &avl_multiset_impl::tree_);
|
||||||
|
}
|
||||||
|
|
||||||
//! <b>Effects</b>: Returns the key_compare object used by the avl_multiset.
|
//! <b>Effects</b>: Returns the key_compare object used by the avl_multiset.
|
||||||
//!
|
//!
|
||||||
//! <b>Complexity</b>: Constant.
|
//! <b>Complexity</b>: Constant.
|
||||||
@@ -2057,6 +2119,12 @@ class avl_multiset
|
|||||||
|
|
||||||
static const avl_multiset &container_from_end_iterator(const_iterator end_iterator)
|
static const avl_multiset &container_from_end_iterator(const_iterator end_iterator)
|
||||||
{ return static_cast<const avl_multiset &>(Base::container_from_end_iterator(end_iterator)); }
|
{ return static_cast<const avl_multiset &>(Base::container_from_end_iterator(end_iterator)); }
|
||||||
|
|
||||||
|
static avl_multiset &container_from_iterator(iterator end_iterator)
|
||||||
|
{ return static_cast<avl_multiset &>(Base::container_from_iterator(end_iterator)); }
|
||||||
|
|
||||||
|
static const avl_multiset &container_from_iterator(const_iterator end_iterator)
|
||||||
|
{ return static_cast<const avl_multiset &>(Base::container_from_iterator(end_iterator)); }
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@@ -387,6 +387,28 @@ class avltree_impl
|
|||||||
static const avltree_impl &container_from_end_iterator(const_iterator end_iterator)
|
static const avltree_impl &container_from_end_iterator(const_iterator end_iterator)
|
||||||
{ return priv_container_from_end_iterator(end_iterator); }
|
{ return priv_container_from_end_iterator(end_iterator); }
|
||||||
|
|
||||||
|
//! <b>Precondition</b>: it must be a valid iterator
|
||||||
|
//! of rbtree.
|
||||||
|
//!
|
||||||
|
//! <b>Effects</b>: Returns a const reference to the tree associated to the iterator
|
||||||
|
//!
|
||||||
|
//! <b>Throws</b>: Nothing.
|
||||||
|
//!
|
||||||
|
//! <b>Complexity</b>: Logarithmic.
|
||||||
|
static avltree_impl &container_from_iterator(iterator it)
|
||||||
|
{ return priv_container_from_iterator(it); }
|
||||||
|
|
||||||
|
//! <b>Precondition</b>: it must be a valid end const_iterator
|
||||||
|
//! of rbtree.
|
||||||
|
//!
|
||||||
|
//! <b>Effects</b>: Returns a const reference to the tree associated to the iterator
|
||||||
|
//!
|
||||||
|
//! <b>Throws</b>: Nothing.
|
||||||
|
//!
|
||||||
|
//! <b>Complexity</b>: Logarithmic.
|
||||||
|
static const avltree_impl &container_from_iterator(const_iterator it)
|
||||||
|
{ return priv_container_from_iterator(it); }
|
||||||
|
|
||||||
//! <b>Effects</b>: Returns the value_compare object used by the tree.
|
//! <b>Effects</b>: Returns the value_compare object used by the tree.
|
||||||
//!
|
//!
|
||||||
//! <b>Complexity</b>: Constant.
|
//! <b>Complexity</b>: Constant.
|
||||||
@@ -1233,6 +1255,9 @@ class avltree_impl
|
|||||||
avltree_impl *avl = detail::parent_from_member<avltree_impl, data_t>(d, &avltree_impl::data_);
|
avltree_impl *avl = detail::parent_from_member<avltree_impl, data_t>(d, &avltree_impl::data_);
|
||||||
return *avl;
|
return *avl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static avltree_impl &priv_container_from_iterator(const const_iterator &it)
|
||||||
|
{ return priv_container_from_end_iterator(it.end_iterator_from_it()); }
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
|
#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
|
||||||
@@ -1426,6 +1451,12 @@ class avltree
|
|||||||
|
|
||||||
static const avltree &container_from_end_iterator(const_iterator end_iterator)
|
static const avltree &container_from_end_iterator(const_iterator end_iterator)
|
||||||
{ return static_cast<const avltree &>(Base::container_from_end_iterator(end_iterator)); }
|
{ return static_cast<const avltree &>(Base::container_from_end_iterator(end_iterator)); }
|
||||||
|
|
||||||
|
static avltree &container_from_iterator(iterator it)
|
||||||
|
{ return static_cast<avltree &>(Base::container_from_iterator(it)); }
|
||||||
|
|
||||||
|
static const avltree &container_from_iterator(const_iterator it)
|
||||||
|
{ return static_cast<const avltree &>(Base::container_from_iterator(it)); }
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@@ -20,7 +20,6 @@
|
|||||||
#include <boost/intrusive/intrusive_fwd.hpp>
|
#include <boost/intrusive/intrusive_fwd.hpp>
|
||||||
|
|
||||||
#include <boost/intrusive/detail/assert.hpp>
|
#include <boost/intrusive/detail/assert.hpp>
|
||||||
#include <boost/intrusive/detail/no_exceptions_support.hpp>
|
|
||||||
#include <boost/intrusive/detail/utilities.hpp>
|
#include <boost/intrusive/detail/utilities.hpp>
|
||||||
#include <boost/intrusive/detail/tree_algorithms.hpp>
|
#include <boost/intrusive/detail/tree_algorithms.hpp>
|
||||||
|
|
||||||
@@ -641,6 +640,16 @@ class avltree_algorithms
|
|||||||
rebalance_after_insertion(header, new_value);
|
rebalance_after_insertion(header, new_value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//! <b>Requires</b>: "n" must be a node inserted in a tree.
|
||||||
|
//!
|
||||||
|
//! <b>Effects</b>: Returns a pointer to the header node of the tree.
|
||||||
|
//!
|
||||||
|
//! <b>Complexity</b>: Logarithmic.
|
||||||
|
//!
|
||||||
|
//! <b>Throws</b>: Nothing.
|
||||||
|
static node_ptr get_header(node_ptr n)
|
||||||
|
{ return tree_algorithms::get_header(n); }
|
||||||
|
|
||||||
/// @cond
|
/// @cond
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
@@ -62,8 +62,8 @@ class circular_list_algorithms
|
|||||||
//! <b>Throws</b>: Nothing.
|
//! <b>Throws</b>: Nothing.
|
||||||
static void init(node_ptr this_node)
|
static void init(node_ptr this_node)
|
||||||
{
|
{
|
||||||
NodeTraits::set_next(this_node, 0);
|
NodeTraits::set_next(this_node, node_ptr(0));
|
||||||
NodeTraits::set_previous(this_node, 0);
|
NodeTraits::set_previous(this_node, node_ptr(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
//! <b>Effects</b>: Returns true is "this_node" is in a non-used state
|
//! <b>Effects</b>: Returns true is "this_node" is in a non-used state
|
||||||
|
@@ -305,12 +305,12 @@ class circular_slist_algorithms
|
|||||||
static node_ptr move_backwards(node_ptr p, std::size_t n)
|
static node_ptr move_backwards(node_ptr p, std::size_t n)
|
||||||
{
|
{
|
||||||
//Null shift, nothing to do
|
//Null shift, nothing to do
|
||||||
if(!n) return 0;
|
if(!n) return node_ptr(0);
|
||||||
node_ptr first = NodeTraits::get_next(p);
|
node_ptr first = NodeTraits::get_next(p);
|
||||||
|
|
||||||
//count() == 1 or 2, nothing to do
|
//count() == 1 or 2, nothing to do
|
||||||
if(NodeTraits::get_next(first) == p)
|
if(NodeTraits::get_next(first) == p)
|
||||||
return 0;
|
return node_ptr(0);
|
||||||
|
|
||||||
bool end_found = false;
|
bool end_found = false;
|
||||||
node_ptr new_last(0);
|
node_ptr new_last(0);
|
||||||
@@ -326,7 +326,7 @@ class circular_slist_algorithms
|
|||||||
//Shortcut the shift with the modulo of the size of the list
|
//Shortcut the shift with the modulo of the size of the list
|
||||||
n %= i;
|
n %= i;
|
||||||
if(!n)
|
if(!n)
|
||||||
return 0;
|
return node_ptr(0);
|
||||||
i = 0;
|
i = 0;
|
||||||
//Unlink p and continue the new first node search
|
//Unlink p and continue the new first node search
|
||||||
first = NodeTraits::get_next(p);
|
first = NodeTraits::get_next(p);
|
||||||
@@ -357,11 +357,11 @@ class circular_slist_algorithms
|
|||||||
static node_ptr move_forward(node_ptr p, std::size_t n)
|
static node_ptr move_forward(node_ptr p, std::size_t n)
|
||||||
{
|
{
|
||||||
//Null shift, nothing to do
|
//Null shift, nothing to do
|
||||||
if(!n) return 0;
|
if(!n) return node_ptr(0);
|
||||||
node_ptr first = node_traits::get_next(p);
|
node_ptr first = node_traits::get_next(p);
|
||||||
|
|
||||||
//count() == 1 or 2, nothing to do
|
//count() == 1 or 2, nothing to do
|
||||||
if(node_traits::get_next(first) == p) return 0;
|
if(node_traits::get_next(first) == p) return node_ptr(0);
|
||||||
|
|
||||||
//Iterate until p is found to know where the current last node is.
|
//Iterate until p is found to know where the current last node is.
|
||||||
//If the shift count is less than the size of the list, we can also obtain
|
//If the shift count is less than the size of the list, we can also obtain
|
||||||
@@ -380,7 +380,7 @@ class circular_slist_algorithms
|
|||||||
//Shortcut the shift with the modulo of the size of the list
|
//Shortcut the shift with the modulo of the size of the list
|
||||||
std::size_t new_before_last_pos = (distance - (n % distance))% distance;
|
std::size_t new_before_last_pos = (distance - (n % distance))% distance;
|
||||||
//If the shift is a multiple of the size there is nothing to do
|
//If the shift is a multiple of the size there is nothing to do
|
||||||
if(!new_before_last_pos) return 0;
|
if(!new_before_last_pos) return node_ptr(0);
|
||||||
|
|
||||||
for( new_last = p
|
for( new_last = p
|
||||||
; new_before_last_pos--
|
; new_before_last_pos--
|
||||||
|
@@ -17,7 +17,7 @@
|
|||||||
#include <iterator>
|
#include <iterator>
|
||||||
#include <boost/intrusive/detail/pointer_to_other.hpp>
|
#include <boost/intrusive/detail/pointer_to_other.hpp>
|
||||||
#include <boost/intrusive/avltree_algorithms.hpp>
|
#include <boost/intrusive/avltree_algorithms.hpp>
|
||||||
#include <boost/intrusive/pointer_plus_2_bits.hpp>
|
#include <boost/intrusive/pointer_plus_bits.hpp>
|
||||||
#include <boost/intrusive/detail/mpl.hpp>
|
#include <boost/intrusive/detail/mpl.hpp>
|
||||||
|
|
||||||
namespace boost {
|
namespace boost {
|
||||||
@@ -111,7 +111,7 @@ struct compact_avltree_node_traits_impl
|
|||||||
<VoidPointer, const node>::type const_node_ptr;
|
<VoidPointer, const node>::type const_node_ptr;
|
||||||
typedef typename node::balance balance;
|
typedef typename node::balance balance;
|
||||||
|
|
||||||
typedef pointer_plus_2_bits<node_ptr> ptr_bit;
|
typedef pointer_plus_bits<node_ptr, 2> ptr_bit;
|
||||||
|
|
||||||
static node_ptr get_parent(const_node_ptr n)
|
static node_ptr get_parent(const_node_ptr n)
|
||||||
{ return ptr_bit::get_pointer(n->parent_); }
|
{ return ptr_bit::get_pointer(n->parent_); }
|
||||||
@@ -148,7 +148,7 @@ struct compact_avltree_node_traits_impl
|
|||||||
};
|
};
|
||||||
|
|
||||||
//Dispatches the implementation based on the boolean
|
//Dispatches the implementation based on the boolean
|
||||||
template<class VoidPointer, bool compact>
|
template<class VoidPointer, bool Compact>
|
||||||
struct avltree_node_traits_dispatch
|
struct avltree_node_traits_dispatch
|
||||||
: public default_avltree_node_traits_impl<VoidPointer>
|
: public default_avltree_node_traits_impl<VoidPointer>
|
||||||
{};
|
{};
|
||||||
@@ -164,10 +164,10 @@ struct avltree_node_traits
|
|||||||
: public avltree_node_traits_dispatch
|
: public avltree_node_traits_dispatch
|
||||||
< VoidPointer
|
< VoidPointer
|
||||||
, OptimizeSize &&
|
, OptimizeSize &&
|
||||||
has_pointer_plus_2_bits
|
max_pointer_plus_bits
|
||||||
< VoidPointer
|
< VoidPointer
|
||||||
, detail::alignment_of<compact_avltree_node<VoidPointer> >::value
|
, detail::alignment_of<compact_avltree_node<VoidPointer> >::value
|
||||||
>::value
|
>::value >= 2u
|
||||||
>
|
>
|
||||||
{};
|
{};
|
||||||
|
|
||||||
|
@@ -47,7 +47,7 @@ class common_slist_algorithms
|
|||||||
{ NodeTraits::set_next(this_node, this_node); }
|
{ NodeTraits::set_next(this_node, this_node); }
|
||||||
|
|
||||||
static void init(node_ptr this_node)
|
static void init(node_ptr this_node)
|
||||||
{ NodeTraits::set_next(this_node, 0); }
|
{ NodeTraits::set_next(this_node, node_ptr(0)); }
|
||||||
|
|
||||||
static bool unique(const_node_ptr this_node)
|
static bool unique(const_node_ptr this_node)
|
||||||
{
|
{
|
||||||
|
@@ -23,8 +23,15 @@ template<typename T, bool IsEmpty = true>
|
|||||||
class ebo_functor_holder_impl
|
class ebo_functor_holder_impl
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ebo_functor_holder_impl(){}
|
ebo_functor_holder_impl()
|
||||||
ebo_functor_holder_impl(const T& t):t(t){}
|
{}
|
||||||
|
ebo_functor_holder_impl(const T& t)
|
||||||
|
: t(t)
|
||||||
|
{}
|
||||||
|
template<class Arg1, class Arg2>
|
||||||
|
ebo_functor_holder_impl(const Arg1& arg1, const Arg2& arg2)
|
||||||
|
: t(arg1, arg2)
|
||||||
|
{}
|
||||||
|
|
||||||
T& get(){return t;}
|
T& get(){return t;}
|
||||||
const T& get()const{return t;}
|
const T& get()const{return t;}
|
||||||
@@ -38,8 +45,15 @@ class ebo_functor_holder_impl<T, false>
|
|||||||
: public T
|
: public T
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ebo_functor_holder_impl(){}
|
ebo_functor_holder_impl()
|
||||||
ebo_functor_holder_impl(const T& t):T(t){}
|
{}
|
||||||
|
ebo_functor_holder_impl(const T& t)
|
||||||
|
: T(t)
|
||||||
|
{}
|
||||||
|
template<class Arg1, class Arg2>
|
||||||
|
ebo_functor_holder_impl(const Arg1& arg1, const Arg2& arg2)
|
||||||
|
: T(arg1, arg2)
|
||||||
|
{}
|
||||||
|
|
||||||
T& get(){return *this;}
|
T& get(){return *this;}
|
||||||
const T& get()const{return *this;}
|
const T& get()const{return *this;}
|
||||||
@@ -54,7 +68,14 @@ class ebo_functor_holder
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
ebo_functor_holder(){}
|
ebo_functor_holder(){}
|
||||||
ebo_functor_holder(const T& t):super(t){}
|
ebo_functor_holder(const T& t)
|
||||||
|
: super(t)
|
||||||
|
{}
|
||||||
|
|
||||||
|
template<class Arg1, class Arg2>
|
||||||
|
ebo_functor_holder(const Arg1& arg1, const Arg2& arg2)
|
||||||
|
: super(arg1, arg2)
|
||||||
|
{}
|
||||||
|
|
||||||
ebo_functor_holder& operator=(const ebo_functor_holder& x)
|
ebo_functor_holder& operator=(const ebo_functor_holder& x)
|
||||||
{
|
{
|
||||||
|
@@ -50,6 +50,7 @@ const std::size_t prime_list_holder<Dummy>::prime_list_size
|
|||||||
template <class Slist>
|
template <class Slist>
|
||||||
struct bucket_impl : public Slist
|
struct bucket_impl : public Slist
|
||||||
{
|
{
|
||||||
|
typedef Slist slist_type;
|
||||||
bucket_impl()
|
bucket_impl()
|
||||||
{}
|
{}
|
||||||
|
|
||||||
@@ -69,28 +70,6 @@ struct bucket_impl : public Slist
|
|||||||
//Slist::clear();
|
//Slist::clear();
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
static typename Slist::difference_type get_bucket_num
|
|
||||||
( typename Slist::const_iterator it
|
|
||||||
, const bucket_impl<Slist> &first_bucket
|
|
||||||
, const bucket_impl<Slist> &last_bucket)
|
|
||||||
{
|
|
||||||
typename Slist::const_iterator
|
|
||||||
first(first_bucket.cend()), last(last_bucket.cend());
|
|
||||||
|
|
||||||
//The end node is embedded in the singly linked list:
|
|
||||||
//iterate until we reach it.
|
|
||||||
while(!(first.pointed_node() <= it.pointed_node() &&
|
|
||||||
it.pointed_node() <= last.pointed_node())){
|
|
||||||
++it;
|
|
||||||
}
|
|
||||||
//Now get the bucket_impl from the iterator
|
|
||||||
const bucket_impl &b = static_cast<const bucket_impl&>
|
|
||||||
(Slist::container_from_end_iterator(it));
|
|
||||||
|
|
||||||
//Now just calculate the index b has in the bucket array
|
|
||||||
return &b - &first_bucket;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
template<class Slist>
|
template<class Slist>
|
||||||
@@ -133,6 +112,9 @@ class hashtable_iterator
|
|||||||
< typename Container::pointer, const Container>::type const_cont_ptr;
|
< typename Container::pointer, const Container>::type const_cont_ptr;
|
||||||
typedef typename Container::size_type size_type;
|
typedef typename Container::size_type size_type;
|
||||||
|
|
||||||
|
static typename Container::node_ptr downcast_bucket(typename bucket_type::node_ptr p)
|
||||||
|
{ return typename Container::node_ptr(&static_cast<typename Container::node&>(*p)); }
|
||||||
|
|
||||||
public:
|
public:
|
||||||
typedef typename detail::add_const_if_c
|
typedef typename detail::add_const_if_c
|
||||||
<typename Container::value_type, IsConst>::type value_type;
|
<typename Container::value_type, IsConst>::type value_type;
|
||||||
@@ -172,7 +154,7 @@ class hashtable_iterator
|
|||||||
{ return *this->operator ->(); }
|
{ return *this->operator ->(); }
|
||||||
|
|
||||||
value_type* operator->() const
|
value_type* operator->() const
|
||||||
{ return detail::get_pointer(this->get_real_value_traits()->to_value_ptr(slist_it_.pointed_node())); }
|
{ return detail::get_pointer(this->get_real_value_traits()->to_value_ptr(downcast_bucket(slist_it_.pointed_node()))); }
|
||||||
|
|
||||||
const Container *get_container() const
|
const Container *get_container() const
|
||||||
{ return detail::get_pointer(cont_); }
|
{ return detail::get_pointer(cont_); }
|
||||||
@@ -186,17 +168,19 @@ class hashtable_iterator
|
|||||||
const Container *cont = detail::get_pointer(cont_);
|
const Container *cont = detail::get_pointer(cont_);
|
||||||
bucket_type* buckets = detail::get_pointer(cont->bucket_pointer());
|
bucket_type* buckets = detail::get_pointer(cont->bucket_pointer());
|
||||||
size_type buckets_len = cont->bucket_count();
|
size_type buckets_len = cont->bucket_count();
|
||||||
const_siterator first(buckets[0].cend());
|
|
||||||
const_siterator last (buckets[buckets_len].cend());
|
|
||||||
|
|
||||||
++slist_it_;
|
++slist_it_;
|
||||||
if(first.pointed_node() <= slist_it_.pointed_node() &&
|
if(buckets[0].cend().pointed_node() <= slist_it_.pointed_node() &&
|
||||||
slist_it_.pointed_node()<= last.pointed_node() ){
|
slist_it_.pointed_node()<= buckets[buckets_len].cend().pointed_node() ){
|
||||||
size_type n_bucket = (size_type)
|
//Now get the bucket_impl from the iterator
|
||||||
bucket_type::get_bucket_num(slist_it_, buckets[0], buckets[buckets_len]);
|
const bucket_type &b = static_cast<const bucket_type&>
|
||||||
|
(bucket_type::slist_type::container_from_end_iterator(slist_it_));
|
||||||
|
|
||||||
|
//Now just calculate the index b has in the bucket array
|
||||||
|
size_type n_bucket = static_cast<size_type>(&b - &buckets[0]);
|
||||||
do{
|
do{
|
||||||
if (++n_bucket == buckets_len){
|
if (++n_bucket == buckets_len){
|
||||||
slist_it_ = buckets->end();
|
slist_it_ = (&buckets[0] + buckets_len)->end();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
slist_it_ = buckets[n_bucket].begin();
|
slist_it_ = buckets[n_bucket].begin();
|
||||||
|
@@ -32,7 +32,8 @@ struct list_node
|
|||||||
{
|
{
|
||||||
typedef typename boost::pointer_to_other
|
typedef typename boost::pointer_to_other
|
||||||
<VoidPointer, list_node>::type node_ptr;
|
<VoidPointer, list_node>::type node_ptr;
|
||||||
node_ptr prev_, next_;
|
node_ptr next_;
|
||||||
|
node_ptr prev_;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<class VoidPointer>
|
template<class VoidPointer>
|
||||||
@@ -85,7 +86,7 @@ class list_iterator
|
|||||||
typedef value_type * pointer;
|
typedef value_type * pointer;
|
||||||
|
|
||||||
list_iterator()
|
list_iterator()
|
||||||
: members_ (0, 0)
|
: members_ (node_ptr(0), 0)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
explicit list_iterator(node_ptr node, const Container *cont_ptr)
|
explicit list_iterator(node_ptr node, const Container *cont_ptr)
|
||||||
|
@@ -13,6 +13,8 @@
|
|||||||
#ifndef BOOST_INTRUSIVE_DETAIL_MPL_HPP
|
#ifndef BOOST_INTRUSIVE_DETAIL_MPL_HPP
|
||||||
#define BOOST_INTRUSIVE_DETAIL_MPL_HPP
|
#define BOOST_INTRUSIVE_DETAIL_MPL_HPP
|
||||||
|
|
||||||
|
#include <cstddef>
|
||||||
|
|
||||||
namespace boost {
|
namespace boost {
|
||||||
namespace intrusive {
|
namespace intrusive {
|
||||||
namespace detail {
|
namespace detail {
|
||||||
@@ -290,6 +292,24 @@ class is_empty_class
|
|||||||
static const bool value = sizeof(empty_helper_t1<Class>) == sizeof(empty_helper_t2);
|
static const bool value = sizeof(empty_helper_t1<Class>) == sizeof(empty_helper_t2);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<std::size_t S>
|
||||||
|
struct ls_zeros
|
||||||
|
{
|
||||||
|
static const std::size_t value = (S & std::size_t(1)) ? 0 : (1 + ls_zeros<(S>>1u)>::value);
|
||||||
|
};
|
||||||
|
|
||||||
|
template<>
|
||||||
|
struct ls_zeros<0>
|
||||||
|
{
|
||||||
|
static const std::size_t value = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<>
|
||||||
|
struct ls_zeros<1>
|
||||||
|
{
|
||||||
|
static const std::size_t value = 0;
|
||||||
|
};
|
||||||
|
|
||||||
} //namespace detail
|
} //namespace detail
|
||||||
} //namespace intrusive
|
} //namespace intrusive
|
||||||
} //namespace boost
|
} //namespace boost
|
||||||
|
@@ -1,28 +0,0 @@
|
|||||||
/////////////////////////////////////////////////////////////////////////////
|
|
||||||
//
|
|
||||||
// (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_NO_EXCEPTION_SUPPORT_HPP
|
|
||||||
|
|
||||||
#if !(defined BOOST_INTRUSIVE_DISABLE_EXCEPTION_HANDLING)
|
|
||||||
# include <boost/detail/no_exceptions_support.hpp>
|
|
||||||
# define BOOST_INTRUSIVE_TRY BOOST_TRY
|
|
||||||
# define BOOST_INTRUSIVE_CATCH(x) BOOST_CATCH(x)
|
|
||||||
# define BOOST_INTRUSIVE_RETHROW BOOST_RETHROW
|
|
||||||
# define BOOST_INTRUSIVE_CATCH_END BOOST_CATCH_END
|
|
||||||
#else
|
|
||||||
# define BOOST_INTRUSIVE_TRY { if (true)
|
|
||||||
# define BOOST_INTRUSIVE_CATCH(x) else if (false)
|
|
||||||
# define BOOST_INTRUSIVE_RETHROW
|
|
||||||
# define BOOST_INTRUSIVE_CATCH_END }
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif //#ifndef BOOST_INTRUSIVE_NO_EXCEPTION_SUPPORT_HPP
|
|
@@ -18,7 +18,7 @@
|
|||||||
#include <iterator>
|
#include <iterator>
|
||||||
#include <boost/intrusive/detail/pointer_to_other.hpp>
|
#include <boost/intrusive/detail/pointer_to_other.hpp>
|
||||||
#include <boost/intrusive/rbtree_algorithms.hpp>
|
#include <boost/intrusive/rbtree_algorithms.hpp>
|
||||||
#include <boost/intrusive/pointer_plus_bit.hpp>
|
#include <boost/intrusive/pointer_plus_bits.hpp>
|
||||||
#include <boost/intrusive/detail/mpl.hpp>
|
#include <boost/intrusive/detail/mpl.hpp>
|
||||||
|
|
||||||
namespace boost {
|
namespace boost {
|
||||||
@@ -110,7 +110,7 @@ struct compact_rbtree_node_traits_impl
|
|||||||
typedef typename boost::pointer_to_other
|
typedef typename boost::pointer_to_other
|
||||||
<VoidPointer, const node>::type const_node_ptr;
|
<VoidPointer, const node>::type const_node_ptr;
|
||||||
|
|
||||||
typedef pointer_plus_bit<node_ptr> ptr_bit;
|
typedef pointer_plus_bits<node_ptr, 1> ptr_bit;
|
||||||
|
|
||||||
typedef typename node::color color;
|
typedef typename node::color color;
|
||||||
|
|
||||||
@@ -133,10 +133,10 @@ struct compact_rbtree_node_traits_impl
|
|||||||
{ n->right_ = r; }
|
{ n->right_ = r; }
|
||||||
|
|
||||||
static color get_color(const_node_ptr n)
|
static color get_color(const_node_ptr n)
|
||||||
{ return (color)ptr_bit::get_bit(n->parent_); }
|
{ return (color)ptr_bit::get_bits(n->parent_); }
|
||||||
|
|
||||||
static void set_color(node_ptr n, color c)
|
static void set_color(node_ptr n, color c)
|
||||||
{ ptr_bit::set_bit(n->parent_, c != 0); }
|
{ ptr_bit::set_bits(n->parent_, c != 0); }
|
||||||
|
|
||||||
static color black()
|
static color black()
|
||||||
{ return node::black_t; }
|
{ return node::black_t; }
|
||||||
@@ -146,7 +146,7 @@ struct compact_rbtree_node_traits_impl
|
|||||||
};
|
};
|
||||||
|
|
||||||
//Dispatches the implementation based on the boolean
|
//Dispatches the implementation based on the boolean
|
||||||
template<class VoidPointer, bool compact>
|
template<class VoidPointer, bool Compact>
|
||||||
struct rbtree_node_traits_dispatch
|
struct rbtree_node_traits_dispatch
|
||||||
: public default_rbtree_node_traits_impl<VoidPointer>
|
: public default_rbtree_node_traits_impl<VoidPointer>
|
||||||
{};
|
{};
|
||||||
@@ -161,11 +161,11 @@ template<class VoidPointer, bool OptimizeSize = false>
|
|||||||
struct rbtree_node_traits
|
struct rbtree_node_traits
|
||||||
: public rbtree_node_traits_dispatch
|
: public rbtree_node_traits_dispatch
|
||||||
< VoidPointer
|
< VoidPointer
|
||||||
, OptimizeSize &&
|
, OptimizeSize &&
|
||||||
has_pointer_plus_bit
|
(max_pointer_plus_bits
|
||||||
< VoidPointer
|
< VoidPointer
|
||||||
, detail::alignment_of<compact_rbtree_node<VoidPointer> >::value
|
, detail::alignment_of<compact_rbtree_node<VoidPointer> >::value
|
||||||
>::value
|
>::value >= 1)
|
||||||
>
|
>
|
||||||
{};
|
{};
|
||||||
|
|
||||||
|
@@ -78,7 +78,7 @@ class slist_iterator
|
|||||||
typedef value_type * pointer;
|
typedef value_type * pointer;
|
||||||
|
|
||||||
slist_iterator()
|
slist_iterator()
|
||||||
: members_ (0, 0)
|
: members_ (node_ptr(0), 0)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
explicit slist_iterator(node_ptr node, const Container *cont_ptr)
|
explicit slist_iterator(node_ptr node, const Container *cont_ptr)
|
||||||
|
@@ -17,7 +17,6 @@
|
|||||||
#include <boost/intrusive/detail/assert.hpp>
|
#include <boost/intrusive/detail/assert.hpp>
|
||||||
#include <boost/intrusive/intrusive_fwd.hpp>
|
#include <boost/intrusive/intrusive_fwd.hpp>
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
#include <boost/intrusive/detail/no_exceptions_support.hpp>
|
|
||||||
#include <boost/intrusive/detail/utilities.hpp>
|
#include <boost/intrusive/detail/utilities.hpp>
|
||||||
|
|
||||||
namespace boost {
|
namespace boost {
|
||||||
@@ -97,6 +96,7 @@ class tree_algorithms
|
|||||||
{
|
{
|
||||||
/// @cond
|
/// @cond
|
||||||
private:
|
private:
|
||||||
|
|
||||||
typedef typename NodeTraits::node node;
|
typedef typename NodeTraits::node node;
|
||||||
/// @endcond
|
/// @endcond
|
||||||
|
|
||||||
@@ -123,6 +123,26 @@ class tree_algorithms
|
|||||||
|
|
||||||
/// @cond
|
/// @cond
|
||||||
private:
|
private:
|
||||||
|
template<class Disposer>
|
||||||
|
struct dispose_subtree_disposer
|
||||||
|
{
|
||||||
|
dispose_subtree_disposer(Disposer &disp, node_ptr subtree)
|
||||||
|
: disposer_(&disp), subtree_(subtree)
|
||||||
|
{}
|
||||||
|
|
||||||
|
void release()
|
||||||
|
{ disposer_ = 0; }
|
||||||
|
|
||||||
|
~dispose_subtree_disposer()
|
||||||
|
{
|
||||||
|
if(disposer_){
|
||||||
|
dispose_subtree(subtree_, *disposer_);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Disposer *disposer_;
|
||||||
|
node_ptr subtree_;
|
||||||
|
};
|
||||||
|
|
||||||
static node_ptr uncast(const_node_ptr ptr)
|
static node_ptr uncast(const_node_ptr ptr)
|
||||||
{
|
{
|
||||||
return node_ptr(const_cast<node*>(::boost::intrusive::detail::get_pointer(ptr)));
|
return node_ptr(const_cast<node*>(::boost::intrusive::detail::get_pointer(ptr)));
|
||||||
@@ -505,9 +525,21 @@ class tree_algorithms
|
|||||||
//! <b>Nodes</b>: If node is inserted in a tree, this function corrupts the tree.
|
//! <b>Nodes</b>: If node is inserted in a tree, this function corrupts the tree.
|
||||||
static void init(node_ptr node)
|
static void init(node_ptr node)
|
||||||
{
|
{
|
||||||
NodeTraits::set_parent(node, 0);
|
NodeTraits::set_parent(node, node_ptr(0));
|
||||||
NodeTraits::set_left(node, 0);
|
NodeTraits::set_left(node, node_ptr(0));
|
||||||
NodeTraits::set_right(node, 0);
|
NodeTraits::set_right(node, node_ptr(0));
|
||||||
|
};
|
||||||
|
|
||||||
|
//! <b>Effects</b>: Returns true if node is in the same state as if called init(node)
|
||||||
|
//!
|
||||||
|
//! <b>Complexity</b>: Constant.
|
||||||
|
//!
|
||||||
|
//! <b>Throws</b>: Nothing.
|
||||||
|
static bool inited(const_node_ptr node)
|
||||||
|
{
|
||||||
|
return !NodeTraits::get_parent(node) &&
|
||||||
|
!NodeTraits::get_left(node) &&
|
||||||
|
!NodeTraits::get_right(node) ;
|
||||||
};
|
};
|
||||||
|
|
||||||
//! <b>Requires</b>: node must not be part of any tree.
|
//! <b>Requires</b>: node must not be part of any tree.
|
||||||
@@ -522,7 +554,7 @@ class tree_algorithms
|
|||||||
//! <b>Nodes</b>: If node is inserted in a tree, this function corrupts the tree.
|
//! <b>Nodes</b>: If node is inserted in a tree, this function corrupts the tree.
|
||||||
static void init_header(node_ptr header)
|
static void init_header(node_ptr header)
|
||||||
{
|
{
|
||||||
NodeTraits::set_parent(header, 0);
|
NodeTraits::set_parent(header, node_ptr(0));
|
||||||
NodeTraits::set_left(header, header);
|
NodeTraits::set_left(header, header);
|
||||||
NodeTraits::set_right(header, header);
|
NodeTraits::set_right(header, header);
|
||||||
}
|
}
|
||||||
@@ -565,7 +597,7 @@ class tree_algorithms
|
|||||||
{
|
{
|
||||||
node_ptr leftmost = NodeTraits::get_left(header);
|
node_ptr leftmost = NodeTraits::get_left(header);
|
||||||
if (leftmost == header)
|
if (leftmost == header)
|
||||||
return 0;
|
return node_ptr(0);
|
||||||
node_ptr leftmost_parent(NodeTraits::get_parent(leftmost));
|
node_ptr leftmost_parent(NodeTraits::get_parent(leftmost));
|
||||||
node_ptr leftmost_right (NodeTraits::get_right(leftmost));
|
node_ptr leftmost_right (NodeTraits::get_right(leftmost));
|
||||||
bool is_root = leftmost_parent == header;
|
bool is_root = leftmost_parent == header;
|
||||||
@@ -580,12 +612,12 @@ class tree_algorithms
|
|||||||
NodeTraits::set_left(NodeTraits::get_parent(header), leftmost_right);
|
NodeTraits::set_left(NodeTraits::get_parent(header), leftmost_right);
|
||||||
}
|
}
|
||||||
else if (is_root){
|
else if (is_root){
|
||||||
NodeTraits::set_parent(header, 0);
|
NodeTraits::set_parent(header, node_ptr(0));
|
||||||
NodeTraits::set_left(header, header);
|
NodeTraits::set_left(header, header);
|
||||||
NodeTraits::set_right(header, header);
|
NodeTraits::set_right(header, header);
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
NodeTraits::set_left(leftmost_parent, 0);
|
NodeTraits::set_left(leftmost_parent, node_ptr(0));
|
||||||
NodeTraits::set_left(header, leftmost_parent);
|
NodeTraits::set_left(header, leftmost_parent);
|
||||||
}
|
}
|
||||||
return leftmost;
|
return leftmost;
|
||||||
@@ -1143,58 +1175,54 @@ class tree_algorithms
|
|||||||
node_ptr rightmost = target_sub_root;
|
node_ptr rightmost = target_sub_root;
|
||||||
|
|
||||||
//First set the subroot
|
//First set the subroot
|
||||||
NodeTraits::set_left(target_sub_root, 0);
|
NodeTraits::set_left(target_sub_root, node_ptr(0));
|
||||||
NodeTraits::set_right(target_sub_root, 0);
|
NodeTraits::set_right(target_sub_root, node_ptr(0));
|
||||||
NodeTraits::set_parent(target_sub_root, target_parent);
|
NodeTraits::set_parent(target_sub_root, target_parent);
|
||||||
|
|
||||||
try {
|
dispose_subtree_disposer<Disposer> rollback(disposer, target_sub_root);
|
||||||
while(true) {
|
while(true) {
|
||||||
//First clone left nodes
|
//First clone left nodes
|
||||||
if( NodeTraits::get_left(current) &&
|
if( NodeTraits::get_left(current) &&
|
||||||
!NodeTraits::get_left(insertion_point)) {
|
!NodeTraits::get_left(insertion_point)) {
|
||||||
current = NodeTraits::get_left(current);
|
current = NodeTraits::get_left(current);
|
||||||
node_ptr temp = insertion_point;
|
node_ptr temp = insertion_point;
|
||||||
//Clone and mark as leaf
|
//Clone and mark as leaf
|
||||||
insertion_point = cloner(current);
|
insertion_point = cloner(current);
|
||||||
NodeTraits::set_left (insertion_point, 0);
|
NodeTraits::set_left (insertion_point, node_ptr(0));
|
||||||
NodeTraits::set_right (insertion_point, 0);
|
NodeTraits::set_right (insertion_point, node_ptr(0));
|
||||||
//Insert left
|
//Insert left
|
||||||
NodeTraits::set_parent(insertion_point, temp);
|
NodeTraits::set_parent(insertion_point, temp);
|
||||||
NodeTraits::set_left (temp, insertion_point);
|
NodeTraits::set_left (temp, insertion_point);
|
||||||
//Update leftmost
|
//Update leftmost
|
||||||
if(rightmost == target_sub_root)
|
if(rightmost == target_sub_root)
|
||||||
leftmost = insertion_point;
|
leftmost = insertion_point;
|
||||||
}
|
}
|
||||||
//Then clone right nodes
|
//Then clone right nodes
|
||||||
else if( NodeTraits::get_right(current) &&
|
else if( NodeTraits::get_right(current) &&
|
||||||
!NodeTraits::get_right(insertion_point)){
|
!NodeTraits::get_right(insertion_point)){
|
||||||
current = NodeTraits::get_right(current);
|
current = NodeTraits::get_right(current);
|
||||||
node_ptr temp = insertion_point;
|
node_ptr temp = insertion_point;
|
||||||
//Clone and mark as leaf
|
//Clone and mark as leaf
|
||||||
insertion_point = cloner(current);
|
insertion_point = cloner(current);
|
||||||
NodeTraits::set_left (insertion_point, 0);
|
NodeTraits::set_left (insertion_point, node_ptr(0));
|
||||||
NodeTraits::set_right (insertion_point, 0);
|
NodeTraits::set_right (insertion_point, node_ptr(0));
|
||||||
//Insert right
|
//Insert right
|
||||||
NodeTraits::set_parent(insertion_point, temp);
|
NodeTraits::set_parent(insertion_point, temp);
|
||||||
NodeTraits::set_right (temp, insertion_point);
|
NodeTraits::set_right (temp, insertion_point);
|
||||||
//Update rightmost
|
//Update rightmost
|
||||||
rightmost = insertion_point;
|
rightmost = insertion_point;
|
||||||
}
|
}
|
||||||
//If not, go up
|
//If not, go up
|
||||||
else if(current == source_root){
|
else if(current == source_root){
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
//Branch completed, go up searching more nodes to clone
|
//Branch completed, go up searching more nodes to clone
|
||||||
current = NodeTraits::get_parent(current);
|
current = NodeTraits::get_parent(current);
|
||||||
insertion_point = NodeTraits::get_parent(insertion_point);
|
insertion_point = NodeTraits::get_parent(insertion_point);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch(...) {
|
rollback.release();
|
||||||
dispose_subtree(target_sub_root, disposer);
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
leftmost_out = leftmost;
|
leftmost_out = leftmost;
|
||||||
rightmost_out = rightmost;
|
rightmost_out = rightmost;
|
||||||
}
|
}
|
||||||
@@ -1321,8 +1349,8 @@ class tree_algorithms
|
|||||||
NodeTraits::set_right(header, z);
|
NodeTraits::set_right(header, z);
|
||||||
}
|
}
|
||||||
NodeTraits::set_parent(z, par);
|
NodeTraits::set_parent(z, par);
|
||||||
NodeTraits::set_right(z, 0);
|
NodeTraits::set_right(z, node_ptr(0));
|
||||||
NodeTraits::set_left(z, 0);
|
NodeTraits::set_left(z, node_ptr(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void erase(node_ptr header, node_ptr z)
|
static void erase(node_ptr header, node_ptr z)
|
||||||
@@ -1384,7 +1412,7 @@ class tree_algorithms
|
|||||||
{
|
{
|
||||||
std::size_t len;
|
std::size_t len;
|
||||||
len = 0;
|
len = 0;
|
||||||
if(!old_root) return 0;
|
if(!old_root) return node_ptr(0);
|
||||||
|
|
||||||
//To avoid irregularities in the algorithm (old_root can be a
|
//To avoid irregularities in the algorithm (old_root can be a
|
||||||
//left or right child or even the root of the tree) just put the
|
//left or right child or even the root of the tree) just put the
|
||||||
@@ -1392,8 +1420,8 @@ class tree_algorithms
|
|||||||
//information to restore the original relationship after
|
//information to restore the original relationship after
|
||||||
//the algorithm is applied.
|
//the algorithm is applied.
|
||||||
node_ptr super_root = NodeTraits::get_parent(old_root);
|
node_ptr super_root = NodeTraits::get_parent(old_root);
|
||||||
assert(super_root);
|
BOOST_INTRUSIVE_INVARIANT_ASSERT(super_root);
|
||||||
|
|
||||||
//Get info
|
//Get info
|
||||||
node_ptr super_root_right_backup = NodeTraits::get_right(super_root);
|
node_ptr super_root_right_backup = NodeTraits::get_right(super_root);
|
||||||
bool super_root_is_header = is_header(super_root);
|
bool super_root_is_header = is_header(super_root);
|
||||||
@@ -1464,7 +1492,7 @@ class tree_algorithms
|
|||||||
//information to restore the original relationship after
|
//information to restore the original relationship after
|
||||||
//the algorithm is applied.
|
//the algorithm is applied.
|
||||||
node_ptr super_root = NodeTraits::get_parent(old_root);
|
node_ptr super_root = NodeTraits::get_parent(old_root);
|
||||||
assert(super_root);
|
BOOST_INTRUSIVE_INVARIANT_ASSERT(super_root);
|
||||||
|
|
||||||
//Get info
|
//Get info
|
||||||
node_ptr super_root_right_backup = NodeTraits::get_right(super_root);
|
node_ptr super_root_right_backup = NodeTraits::get_right(super_root);
|
||||||
@@ -1511,6 +1539,28 @@ class tree_algorithms
|
|||||||
return new_root;
|
return new_root;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//! <b>Requires</b>: "n" must be a node inserted in a tree.
|
||||||
|
//!
|
||||||
|
//! <b>Effects</b>: Returns a pointer to the header node of the tree.
|
||||||
|
//!
|
||||||
|
//! <b>Complexity</b>: Logarithmic.
|
||||||
|
//!
|
||||||
|
//! <b>Throws</b>: Nothing.
|
||||||
|
static node_ptr get_root(node_ptr node)
|
||||||
|
{
|
||||||
|
BOOST_INTRUSIVE_INVARIANT_ASSERT((!inited(node)));
|
||||||
|
node_ptr x = NodeTraits::get_parent(node);
|
||||||
|
if(x){
|
||||||
|
while(!is_header(x)){
|
||||||
|
x = NodeTraits::get_parent(x);
|
||||||
|
}
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static void erase_impl(node_ptr header, node_ptr z, data_for_rebalance &info)
|
static void erase_impl(node_ptr header, node_ptr z, data_for_rebalance &info)
|
||||||
{
|
{
|
||||||
@@ -1569,7 +1619,6 @@ class tree_algorithms
|
|||||||
info.x_parent = x_parent;
|
info.x_parent = x_parent;
|
||||||
info.y = y;
|
info.y = y;
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} //namespace detail {
|
} //namespace detail {
|
||||||
|
@@ -168,6 +168,11 @@ class tree_iterator
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tree_iterator end_iterator_from_it() const
|
||||||
|
{
|
||||||
|
return tree_iterator(node_algorithms::get_header(this->pointed_node()), this->get_container());
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct members
|
struct members
|
||||||
: public detail::select_constptr
|
: public detail::select_constptr
|
||||||
|
@@ -235,16 +235,9 @@ struct node_cloner
|
|||||||
node_cloner(F f, const Container *cont)
|
node_cloner(F f, const Container *cont)
|
||||||
: base_t(f), cont_(cont)
|
: base_t(f), cont_(cont)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
node_ptr operator()(node_ptr p)
|
node_ptr operator()(node_ptr p)
|
||||||
{
|
{ return this->operator()(*p); }
|
||||||
node_ptr n = cont_->get_real_value_traits().to_node_ptr
|
|
||||||
(*base_t::get()(*cont_->get_real_value_traits().to_value_ptr(p)));
|
|
||||||
//Cloned node must be in default mode if the linking mode requires it
|
|
||||||
if(safemode_or_autounlink)
|
|
||||||
BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::unique(n));
|
|
||||||
return n;
|
|
||||||
}
|
|
||||||
|
|
||||||
node_ptr operator()(const node &to_clone)
|
node_ptr operator()(const node &to_clone)
|
||||||
{
|
{
|
||||||
@@ -396,16 +389,16 @@ template <link_mode_type LinkMode>
|
|||||||
struct link_dispatch
|
struct link_dispatch
|
||||||
{};
|
{};
|
||||||
|
|
||||||
template<class Container>
|
template<class Hook>
|
||||||
void destructor_impl(Container &cont, detail::link_dispatch<safe_link>)
|
void destructor_impl(Hook &hook, detail::link_dispatch<safe_link>)
|
||||||
{ (void)cont; BOOST_INTRUSIVE_SAFE_HOOK_DESTRUCTOR_ASSERT(!cont.is_linked()); }
|
{ (void)hook; BOOST_INTRUSIVE_SAFE_HOOK_DESTRUCTOR_ASSERT(!hook.is_linked()); }
|
||||||
|
|
||||||
template<class Container>
|
template<class Hook>
|
||||||
void destructor_impl(Container &cont, detail::link_dispatch<auto_unlink>)
|
void destructor_impl(Hook &hook, detail::link_dispatch<auto_unlink>)
|
||||||
{ cont.unlink(); }
|
{ hook.unlink(); }
|
||||||
|
|
||||||
template<class Container>
|
template<class Hook>
|
||||||
void destructor_impl(Container &, detail::link_dispatch<normal_link>)
|
void destructor_impl(Hook &, detail::link_dispatch<normal_link>)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
template<class T, class NodeTraits, link_mode_type LinkMode, class Tag, int HookType>
|
template<class T, class NodeTraits, link_mode_type LinkMode, class Tag, int HookType>
|
||||||
@@ -548,6 +541,62 @@ inline std::size_t sqrt2_pow_2xplus1 (std::size_t x)
|
|||||||
return (value >> (pow - x)) + 1;
|
return (value >> (pow - x)) + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<class Container, class Disposer>
|
||||||
|
class exception_disposer
|
||||||
|
{
|
||||||
|
Container *cont_;
|
||||||
|
Disposer &disp_;
|
||||||
|
|
||||||
|
exception_disposer(const exception_disposer&);
|
||||||
|
exception_disposer &operator=(const exception_disposer&);
|
||||||
|
|
||||||
|
public:
|
||||||
|
exception_disposer(Container &cont, Disposer &disp)
|
||||||
|
: cont_(&cont), disp_(disp)
|
||||||
|
{}
|
||||||
|
|
||||||
|
void release()
|
||||||
|
{ cont_ = 0; }
|
||||||
|
|
||||||
|
~exception_disposer()
|
||||||
|
{
|
||||||
|
if(cont_){
|
||||||
|
cont_->clear_and_dispose(disp_);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<class Container, class Disposer>
|
||||||
|
class exception_array_disposer
|
||||||
|
{
|
||||||
|
Container *cont_;
|
||||||
|
Disposer &disp_;
|
||||||
|
typename Container::size_type &constructed_;
|
||||||
|
|
||||||
|
exception_array_disposer(const exception_array_disposer&);
|
||||||
|
exception_array_disposer &operator=(const exception_array_disposer&);
|
||||||
|
|
||||||
|
public:
|
||||||
|
typedef typename Container::size_type size_type;
|
||||||
|
exception_array_disposer
|
||||||
|
(Container &cont, Disposer &disp, size_type &constructed)
|
||||||
|
: cont_(&cont), disp_(disp), constructed_(constructed)
|
||||||
|
{}
|
||||||
|
|
||||||
|
void release()
|
||||||
|
{ cont_ = 0; }
|
||||||
|
|
||||||
|
~exception_array_disposer()
|
||||||
|
{
|
||||||
|
size_type n = constructed_;
|
||||||
|
if(cont_){
|
||||||
|
while(n--){
|
||||||
|
cont_[n].clear_and_dispose(disp_);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
} //namespace detail
|
} //namespace detail
|
||||||
} //namespace intrusive
|
} //namespace intrusive
|
||||||
} //namespace boost
|
} //namespace boost
|
||||||
|
File diff suppressed because it is too large
Load Diff
@@ -283,8 +283,7 @@ template
|
|||||||
>
|
>
|
||||||
class bs_set_member_hook;
|
class bs_set_member_hook;
|
||||||
|
|
||||||
//hash/unordered
|
//hashtable/unordered_set/unordered_multiset
|
||||||
//rbtree/set/multiset
|
|
||||||
template
|
template
|
||||||
< class T
|
< class T
|
||||||
, class O1 = none
|
, class O1 = none
|
||||||
@@ -294,6 +293,7 @@ template
|
|||||||
, class O5 = none
|
, class O5 = none
|
||||||
, class O6 = none
|
, class O6 = none
|
||||||
, class O7 = none
|
, class O7 = none
|
||||||
|
, class O8 = none
|
||||||
>
|
>
|
||||||
class hashtable;
|
class hashtable;
|
||||||
|
|
||||||
@@ -306,6 +306,7 @@ template
|
|||||||
, class O5 = none
|
, class O5 = none
|
||||||
, class O6 = none
|
, class O6 = none
|
||||||
, class O7 = none
|
, class O7 = none
|
||||||
|
, class O8 = none
|
||||||
>
|
>
|
||||||
class unordered_set;
|
class unordered_set;
|
||||||
|
|
||||||
@@ -318,6 +319,7 @@ template
|
|||||||
, class O5 = none
|
, class O5 = none
|
||||||
, class O6 = none
|
, class O6 = none
|
||||||
, class O7 = none
|
, class O7 = none
|
||||||
|
, class O8 = none
|
||||||
>
|
>
|
||||||
class unordered_multiset;
|
class unordered_multiset;
|
||||||
|
|
||||||
|
@@ -136,7 +136,7 @@ class linear_slist_algorithms
|
|||||||
//!
|
//!
|
||||||
//! <b>Throws</b>: Nothing.
|
//! <b>Throws</b>: Nothing.
|
||||||
static void init_header(node_ptr this_node)
|
static void init_header(node_ptr this_node)
|
||||||
{ NodeTraits::set_next(this_node, 0); }
|
{ NodeTraits::set_next(this_node, node_ptr(0)); }
|
||||||
|
|
||||||
//! <b>Requires</b>: this_node and prev_init_node must be in the same linear list.
|
//! <b>Requires</b>: this_node and prev_init_node must be in the same linear list.
|
||||||
//!
|
//!
|
||||||
@@ -195,7 +195,7 @@ class linear_slist_algorithms
|
|||||||
//! <b>Complexity</b>: This function is linear to the contained elements.
|
//! <b>Complexity</b>: This function is linear to the contained elements.
|
||||||
static node_ptr reverse(node_ptr p)
|
static node_ptr reverse(node_ptr p)
|
||||||
{
|
{
|
||||||
if(!p) return 0;
|
if(!p) return node_ptr(0);
|
||||||
node_ptr i = NodeTraits::get_next(p);
|
node_ptr i = NodeTraits::get_next(p);
|
||||||
node_ptr first(p);
|
node_ptr first(p);
|
||||||
while(i){
|
while(i){
|
||||||
@@ -218,7 +218,7 @@ class linear_slist_algorithms
|
|||||||
//! <b>Complexity</b>: Linear to the number of elements plus the number moved positions.
|
//! <b>Complexity</b>: Linear to the number of elements plus the number moved positions.
|
||||||
static std::pair<node_ptr, node_ptr> move_first_n_backwards(node_ptr p, std::size_t n)
|
static std::pair<node_ptr, node_ptr> move_first_n_backwards(node_ptr p, std::size_t n)
|
||||||
{
|
{
|
||||||
std::pair<node_ptr, node_ptr> ret(0, 0);
|
std::pair<node_ptr, node_ptr> ret(node_ptr(0), node_ptr(0));
|
||||||
//Null shift, or count() == 0 or 1, nothing to do
|
//Null shift, or count() == 0 or 1, nothing to do
|
||||||
if(!n || !p || !NodeTraits::get_next(p)){
|
if(!n || !p || !NodeTraits::get_next(p)){
|
||||||
return ret;
|
return ret;
|
||||||
@@ -252,12 +252,12 @@ class linear_slist_algorithms
|
|||||||
//If the p has not been found in the previous loop, find it
|
//If the p has not been found in the previous loop, find it
|
||||||
//starting in the new first node and unlink it
|
//starting in the new first node and unlink it
|
||||||
if(!end_found){
|
if(!end_found){
|
||||||
old_last = base_t::get_previous_node(first, 0);
|
old_last = base_t::get_previous_node(first, node_ptr(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
//Now link p after the new last node
|
//Now link p after the new last node
|
||||||
NodeTraits::set_next(old_last, p);
|
NodeTraits::set_next(old_last, p);
|
||||||
NodeTraits::set_next(new_last, 0);
|
NodeTraits::set_next(new_last, node_ptr(0));
|
||||||
ret.first = first;
|
ret.first = first;
|
||||||
ret.second = new_last;
|
ret.second = new_last;
|
||||||
return ret;
|
return ret;
|
||||||
@@ -273,7 +273,7 @@ class linear_slist_algorithms
|
|||||||
//! <b>Complexity</b>: Linear to the number of elements plus the number moved positions.
|
//! <b>Complexity</b>: Linear to the number of elements plus the number moved positions.
|
||||||
static std::pair<node_ptr, node_ptr> move_first_n_forward(node_ptr p, std::size_t n)
|
static std::pair<node_ptr, node_ptr> move_first_n_forward(node_ptr p, std::size_t n)
|
||||||
{
|
{
|
||||||
std::pair<node_ptr, node_ptr> ret(0, 0);
|
std::pair<node_ptr, node_ptr> ret(node_ptr(0), node_ptr(0));
|
||||||
//Null shift, or count() == 0 or 1, nothing to do
|
//Null shift, or count() == 0 or 1, nothing to do
|
||||||
if(!n || !p || !NodeTraits::get_next(p))
|
if(!n || !p || !NodeTraits::get_next(p))
|
||||||
return ret;
|
return ret;
|
||||||
@@ -311,7 +311,7 @@ class linear_slist_algorithms
|
|||||||
node_ptr new_first(node_traits::get_next(new_last));
|
node_ptr new_first(node_traits::get_next(new_last));
|
||||||
//Now put the old beginning after the old end
|
//Now put the old beginning after the old end
|
||||||
NodeTraits::set_next(old_last, p);
|
NodeTraits::set_next(old_last, p);
|
||||||
NodeTraits::set_next(new_last, 0);
|
NodeTraits::set_next(new_last, node_ptr(0));
|
||||||
ret.first = new_first;
|
ret.first = new_first;
|
||||||
ret.second = new_last;
|
ret.second = new_last;
|
||||||
return ret;
|
return ret;
|
||||||
|
@@ -24,7 +24,7 @@
|
|||||||
#include <boost/intrusive/link_mode.hpp>
|
#include <boost/intrusive/link_mode.hpp>
|
||||||
#include <boost/static_assert.hpp>
|
#include <boost/static_assert.hpp>
|
||||||
#include <boost/intrusive/options.hpp>
|
#include <boost/intrusive/options.hpp>
|
||||||
#include <boost/intrusive/detail/no_exceptions_support.hpp>
|
#include <boost/intrusive/detail/utilities.hpp>
|
||||||
#include <iterator>
|
#include <iterator>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
@@ -732,17 +732,13 @@ class list_impl
|
|||||||
void clone_from(const list_impl &src, Cloner cloner, Disposer disposer)
|
void clone_from(const list_impl &src, Cloner cloner, Disposer disposer)
|
||||||
{
|
{
|
||||||
this->clear_and_dispose(disposer);
|
this->clear_and_dispose(disposer);
|
||||||
BOOST_INTRUSIVE_TRY{
|
detail::exception_disposer<list_impl, Disposer>
|
||||||
const_iterator b(src.begin()), e(src.end());
|
rollback(*this, disposer);
|
||||||
for(; b != e; ++b){
|
const_iterator b(src.begin()), e(src.end());
|
||||||
this->push_back(*cloner(*b));
|
for(; b != e; ++b){
|
||||||
}
|
this->push_back(*cloner(*b));
|
||||||
}
|
}
|
||||||
BOOST_INTRUSIVE_CATCH(...){
|
rollback.release();
|
||||||
this->clear_and_dispose(disposer);
|
|
||||||
BOOST_INTRUSIVE_RETHROW;
|
|
||||||
}
|
|
||||||
BOOST_INTRUSIVE_CATCH_END
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//! <b>Requires</b>: value must be an lvalue and p must be a valid iterator of *this.
|
//! <b>Requires</b>: value must be an lvalue and p must be a valid iterator of *this.
|
||||||
|
@@ -406,6 +406,24 @@ struct store_hash
|
|||||||
/// @endcond
|
/// @endcond
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//!This option setter specifies if the unordered hook
|
||||||
|
//!should offer room to store another link to another node
|
||||||
|
//!with the same key.
|
||||||
|
//!Storing this link will speed up lookups and insertions on
|
||||||
|
//!unordered_multiset containers with a great number of elements
|
||||||
|
//!with the same key.
|
||||||
|
template<bool Enabled>
|
||||||
|
struct optimize_multikey
|
||||||
|
{
|
||||||
|
/// @cond
|
||||||
|
template<class Base>
|
||||||
|
struct pack : Base
|
||||||
|
{
|
||||||
|
static const bool optimize_multikey = Enabled;
|
||||||
|
};
|
||||||
|
/// @endcond
|
||||||
|
};
|
||||||
|
|
||||||
//!This option setter specifies if the bucket array will be always power of two.
|
//!This option setter specifies if the bucket array will be always power of two.
|
||||||
//!This allows using masks instead of the default modulo operation to determine
|
//!This allows using masks instead of the default modulo operation to determine
|
||||||
//!the bucket number from the hash value, leading to better performance.
|
//!the bucket number from the hash value, leading to better performance.
|
||||||
@@ -423,6 +441,22 @@ struct power_2_buckets
|
|||||||
/// @endcond
|
/// @endcond
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//!This option setter specifies if the container will cache a pointer to the first
|
||||||
|
//!non-empty bucket so that begin() is always constant-time.
|
||||||
|
//!This is specially helpful when we can have containers with a few elements
|
||||||
|
//!but with big bucket arrays (that is, hashtables with low load factors).
|
||||||
|
template<bool Enabled>
|
||||||
|
struct cache_begin
|
||||||
|
{
|
||||||
|
/// @cond
|
||||||
|
template<class Base>
|
||||||
|
struct pack : Base
|
||||||
|
{
|
||||||
|
static const bool cache_begin = Enabled;
|
||||||
|
};
|
||||||
|
/// @endcond
|
||||||
|
};
|
||||||
|
|
||||||
/// @cond
|
/// @cond
|
||||||
|
|
||||||
template<class Prev, class Next>
|
template<class Prev, class Next>
|
||||||
@@ -500,6 +534,7 @@ struct hook_defaults
|
|||||||
, optimize_size<false>
|
, optimize_size<false>
|
||||||
, store_hash<false>
|
, store_hash<false>
|
||||||
, linear<false>
|
, linear<false>
|
||||||
|
, optimize_multikey<false>
|
||||||
>::type
|
>::type
|
||||||
{};
|
{};
|
||||||
|
|
||||||
|
@@ -1,82 +0,0 @@
|
|||||||
/////////////////////////////////////////////////////////////////////////////
|
|
||||||
//
|
|
||||||
// (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_POINTER_PLUS_2_BIT_HPP
|
|
||||||
#define BOOST_INTRUSIVE_POINTER_PLUS_2_BIT_HPP
|
|
||||||
|
|
||||||
namespace boost {
|
|
||||||
namespace intrusive {
|
|
||||||
|
|
||||||
//!This trait class is used to know if a pointer
|
|
||||||
//!can embed 2 extra bits of information if
|
|
||||||
//!it's going to be used to point to objects
|
|
||||||
//!with an alignment of "Alignment" bytes.
|
|
||||||
template<class VoidPointer, std::size_t Alignment>
|
|
||||||
struct has_pointer_plus_2_bits
|
|
||||||
{
|
|
||||||
static const bool value = false;
|
|
||||||
};
|
|
||||||
|
|
||||||
//!This is an specialization for raw pointers.
|
|
||||||
//!Raw pointers can embed two extra bits in the lower bits
|
|
||||||
//!if the alignment is multiple of 4.
|
|
||||||
template<std::size_t N>
|
|
||||||
struct has_pointer_plus_2_bits<void*, N>
|
|
||||||
{
|
|
||||||
static const bool value = (N % 4u == 0);
|
|
||||||
};
|
|
||||||
|
|
||||||
//!This is class that is supposed to have static methods
|
|
||||||
//!to embed 2 extra bits of information in a pointer.
|
|
||||||
//!
|
|
||||||
//!This is a declaration and there is no default implementation,
|
|
||||||
//!because operations to embed bits change with every pointer type.
|
|
||||||
//!
|
|
||||||
//!An implementation that detects that a pointer type whose
|
|
||||||
//!has_pointer_plus_2_bits<>::value is non-zero can make use of these
|
|
||||||
//!operations to embed bits in the pointer.
|
|
||||||
template<class Pointer>
|
|
||||||
struct pointer_plus_2_bits
|
|
||||||
{
|
|
||||||
static const bool value = false;
|
|
||||||
};
|
|
||||||
|
|
||||||
//!This is the specialization to embed 2 extra bits of information
|
|
||||||
//!in a raw pointer. Extra bits are stored in the lower bits of the pointer.
|
|
||||||
template<class T>
|
|
||||||
struct pointer_plus_2_bits<T*>
|
|
||||||
{
|
|
||||||
typedef T* pointer;
|
|
||||||
|
|
||||||
static pointer get_pointer(pointer n)
|
|
||||||
{ return pointer(std::size_t(n) & ~std::size_t(3u)); }
|
|
||||||
|
|
||||||
static void set_pointer(pointer &n, pointer p)
|
|
||||||
{
|
|
||||||
assert(0 == (std::size_t(p) & std::size_t(3u)));
|
|
||||||
n = pointer(std::size_t(p) | (std::size_t(n) & std::size_t(3u)));
|
|
||||||
}
|
|
||||||
|
|
||||||
static std::size_t get_bits(pointer n)
|
|
||||||
{ return (std::size_t(n) & std::size_t(3u)); }
|
|
||||||
|
|
||||||
static void set_bits(pointer &n, std::size_t c)
|
|
||||||
{
|
|
||||||
assert(c < 4);
|
|
||||||
n = pointer(std::size_t(get_pointer(n)) | c);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
} //namespace intrusive
|
|
||||||
} //namespace boost
|
|
||||||
|
|
||||||
#endif //BOOST_INTRUSIVE_POINTER_PLUS_2_BIT_HPP
|
|
@@ -1,78 +0,0 @@
|
|||||||
/////////////////////////////////////////////////////////////////////////////
|
|
||||||
//
|
|
||||||
// (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_POINTER_PLUS_BIT_HPP
|
|
||||||
#define BOOST_INTRUSIVE_POINTER_PLUS_BIT_HPP
|
|
||||||
|
|
||||||
namespace boost {
|
|
||||||
namespace intrusive {
|
|
||||||
|
|
||||||
//!This trait class is used to know if a pointer
|
|
||||||
//!can embed an extra bit of information if
|
|
||||||
//!it's going to be used to point to objects
|
|
||||||
//!with an alignment of "Alignment" bytes.
|
|
||||||
template<class VoidPointer, std::size_t Alignment>
|
|
||||||
struct has_pointer_plus_bit
|
|
||||||
{
|
|
||||||
static const bool value = false;
|
|
||||||
};
|
|
||||||
|
|
||||||
//!This is an specialization for raw pointers.
|
|
||||||
//!Raw pointers can embed an extra bit in the lower bit
|
|
||||||
//!if the alignment is multiple of 2.
|
|
||||||
template<std::size_t N>
|
|
||||||
struct has_pointer_plus_bit<void*, N>
|
|
||||||
{
|
|
||||||
static const bool value = (N % 2u == 0);
|
|
||||||
};
|
|
||||||
|
|
||||||
//!This is class that is supposed to have static methods
|
|
||||||
//!to embed an extra bit of information in a pointer.
|
|
||||||
//!This is a declaration and there is no default implementation,
|
|
||||||
//!because operations to embed the bit change with every pointer type.
|
|
||||||
//!
|
|
||||||
//!An implementation that detects that a pointer type whose
|
|
||||||
//!has_pointer_plus_bit<>::value is non-zero can make use of these
|
|
||||||
//!operations to embed the bit in the pointer.
|
|
||||||
template<class Pointer>
|
|
||||||
struct pointer_plus_bit
|
|
||||||
{
|
|
||||||
static const bool value = false;
|
|
||||||
};
|
|
||||||
|
|
||||||
//!This is the specialization to embed an extra bit of information
|
|
||||||
//!in a raw pointer. The extra bit is stored in the lower bit of the pointer.
|
|
||||||
template<class T>
|
|
||||||
struct pointer_plus_bit<T*>
|
|
||||||
{
|
|
||||||
typedef T* pointer;
|
|
||||||
|
|
||||||
static pointer get_pointer(pointer n)
|
|
||||||
{ return pointer(std::size_t(n) & ~std::size_t(1u)); }
|
|
||||||
|
|
||||||
static void set_pointer(pointer &n, pointer p)
|
|
||||||
{
|
|
||||||
assert(0 == (std::size_t(p) & std::size_t(1u)));
|
|
||||||
n = pointer(std::size_t(p) | (std::size_t(n) & std::size_t(1u)));
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool get_bit(pointer n)
|
|
||||||
{ return (std::size_t(n) & std::size_t(1u)) != 0; }
|
|
||||||
|
|
||||||
static void set_bit(pointer &n, bool c)
|
|
||||||
{ n = pointer(std::size_t(get_pointer(n)) | std::size_t(c)); }
|
|
||||||
};
|
|
||||||
|
|
||||||
} //namespace intrusive
|
|
||||||
} //namespace boost
|
|
||||||
|
|
||||||
#endif //BOOST_INTRUSIVE_POINTER_PLUS_BIT_HPP
|
|
81
include/boost/intrusive/pointer_plus_bits.hpp
Normal file
81
include/boost/intrusive/pointer_plus_bits.hpp
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// (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_POINTER_PLUS_BITS_HPP
|
||||||
|
#define BOOST_INTRUSIVE_POINTER_PLUS_BITS_HPP
|
||||||
|
|
||||||
|
#include <boost/intrusive/detail/mpl.hpp> //ls_zeros
|
||||||
|
|
||||||
|
namespace boost {
|
||||||
|
namespace intrusive {
|
||||||
|
|
||||||
|
//!This trait class is used to know if a pointer
|
||||||
|
//!can embed extra bits of information if
|
||||||
|
//!it's going to be used to point to objects
|
||||||
|
//!with an alignment of "Alignment" bytes.
|
||||||
|
template<class VoidPointer, std::size_t Alignment>
|
||||||
|
struct max_pointer_plus_bits
|
||||||
|
{
|
||||||
|
static const std::size_t value = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
//!This is an specialization for raw pointers.
|
||||||
|
//!Raw pointers can embed extra bits in the lower bits
|
||||||
|
//!if the alignment is multiple of 2pow(NumBits).
|
||||||
|
template<std::size_t Alignment>
|
||||||
|
struct max_pointer_plus_bits<void*, Alignment>
|
||||||
|
{
|
||||||
|
static const std::size_t value = detail::ls_zeros<Alignment>::value;
|
||||||
|
};
|
||||||
|
|
||||||
|
//!This is class that is supposed to have static methods
|
||||||
|
//!to embed extra bits of information in a pointer.
|
||||||
|
//!This is a declaration and there is no default implementation,
|
||||||
|
//!because operations to embed the bits change with every pointer type.
|
||||||
|
//!
|
||||||
|
//!An implementation that detects that a pointer type whose
|
||||||
|
//!has_pointer_plus_bits<>::value is non-zero can make use of these
|
||||||
|
//!operations to embed the bits in the pointer.
|
||||||
|
template<class Pointer, std::size_t NumBits>
|
||||||
|
struct pointer_plus_bits;
|
||||||
|
|
||||||
|
//!This is the specialization to embed extra bits of information
|
||||||
|
//!in a raw pointer. The extra bits are stored in the lower bit of the pointer.
|
||||||
|
template<class T, std::size_t NumBits>
|
||||||
|
struct pointer_plus_bits<T*, NumBits>
|
||||||
|
{
|
||||||
|
static const std::size_t Mask = ((std::size_t(1u) << NumBits) - 1);
|
||||||
|
typedef T* pointer;
|
||||||
|
|
||||||
|
static pointer get_pointer(pointer n)
|
||||||
|
{ return pointer(std::size_t(n) & ~Mask); }
|
||||||
|
|
||||||
|
static void set_pointer(pointer &n, pointer p)
|
||||||
|
{
|
||||||
|
assert(0 == (std::size_t(p) & Mask));
|
||||||
|
n = pointer(std::size_t(p) | (std::size_t(n) & Mask));
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::size_t get_bits(pointer n)
|
||||||
|
{ return (std::size_t(n) & Mask); }
|
||||||
|
|
||||||
|
static void set_bits(pointer &n, std::size_t c)
|
||||||
|
{
|
||||||
|
assert(c <= Mask);
|
||||||
|
n = pointer(std::size_t(get_pointer(n)) | c);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} //namespace intrusive
|
||||||
|
} //namespace boost
|
||||||
|
|
||||||
|
#endif //BOOST_INTRUSIVE_POINTER_PLUS_BITS_HPP
|
@@ -379,7 +379,7 @@ class rbtree_impl
|
|||||||
//! <b>Precondition</b>: end_iterator must be a valid end const_iterator
|
//! <b>Precondition</b>: end_iterator must be a valid end const_iterator
|
||||||
//! of rbtree.
|
//! of rbtree.
|
||||||
//!
|
//!
|
||||||
//! <b>Effects</b>: Returns a const reference to the rbtree associated to the end iterator
|
//! <b>Effects</b>: Returns a const reference to the rbtree associated to the iterator
|
||||||
//!
|
//!
|
||||||
//! <b>Throws</b>: Nothing.
|
//! <b>Throws</b>: Nothing.
|
||||||
//!
|
//!
|
||||||
@@ -387,6 +387,28 @@ class rbtree_impl
|
|||||||
static const rbtree_impl &container_from_end_iterator(const_iterator end_iterator)
|
static const rbtree_impl &container_from_end_iterator(const_iterator end_iterator)
|
||||||
{ return priv_container_from_end_iterator(end_iterator); }
|
{ return priv_container_from_end_iterator(end_iterator); }
|
||||||
|
|
||||||
|
//! <b>Precondition</b>: it must be a valid iterator
|
||||||
|
//! of rbtree.
|
||||||
|
//!
|
||||||
|
//! <b>Effects</b>: Returns a const reference to the tree associated to the iterator
|
||||||
|
//!
|
||||||
|
//! <b>Throws</b>: Nothing.
|
||||||
|
//!
|
||||||
|
//! <b>Complexity</b>: Logarithmic.
|
||||||
|
static rbtree_impl &container_from_iterator(iterator it)
|
||||||
|
{ return priv_container_from_iterator(it); }
|
||||||
|
|
||||||
|
//! <b>Precondition</b>: it must be a valid end const_iterator
|
||||||
|
//! of rbtree.
|
||||||
|
//!
|
||||||
|
//! <b>Effects</b>: Returns a const reference to the tree associated to the end iterator
|
||||||
|
//!
|
||||||
|
//! <b>Throws</b>: Nothing.
|
||||||
|
//!
|
||||||
|
//! <b>Complexity</b>: Logarithmic.
|
||||||
|
static const rbtree_impl &container_from_iterator(const_iterator it)
|
||||||
|
{ return priv_container_from_iterator(it); }
|
||||||
|
|
||||||
//! <b>Effects</b>: Returns the value_compare object used by the tree.
|
//! <b>Effects</b>: Returns the value_compare object used by the tree.
|
||||||
//!
|
//!
|
||||||
//! <b>Complexity</b>: Constant.
|
//! <b>Complexity</b>: Constant.
|
||||||
@@ -1176,33 +1198,26 @@ class rbtree_impl
|
|||||||
static void init_node(reference value)
|
static void init_node(reference value)
|
||||||
{ node_algorithms::init(value_traits::to_node_ptr(value)); }
|
{ node_algorithms::init(value_traits::to_node_ptr(value)); }
|
||||||
|
|
||||||
/*
|
//! <b>Effects</b>: removes "value" from the container.
|
||||||
//! <b>Effects</b>: removes x from a tree of the appropriate type. It has no effect,
|
|
||||||
//! if x is not in such a tree.
|
|
||||||
//!
|
//!
|
||||||
//! <b>Throws</b>: Nothing.
|
//! <b>Throws</b>: Nothing.
|
||||||
//!
|
//!
|
||||||
//! <b>Complexity</b>: Constant time.
|
//! <b>Complexity</b>: Logarithmic time.
|
||||||
//!
|
//!
|
||||||
//! <b>Note</b>: This static function is only usable with the "safe mode"
|
//! <b>Note</b>: This static function is only usable with non-constant
|
||||||
//! hook and non-constant time size lists. Otherwise, the user must use
|
//! time size containers that have stateless comparison functors.
|
||||||
//! the non-static "erase(reference )" member. If the user calls
|
//!
|
||||||
//! this function with a non "safe mode" or constant time size list
|
//! If the user calls
|
||||||
//! a compilation error will be issued.
|
//! this function with a constant time size container or stateful comparison
|
||||||
template<class T>
|
//! functor a compilation error will be issued.
|
||||||
static void remove_node(T& value)
|
static void remove_node(reference value)
|
||||||
{
|
{
|
||||||
//This function is only usable for safe mode hooks and non-constant
|
|
||||||
//time lists.
|
|
||||||
//BOOST_STATIC_ASSERT((!(safemode_or_autounlink && constant_time_size)));
|
|
||||||
BOOST_STATIC_ASSERT((!constant_time_size));
|
BOOST_STATIC_ASSERT((!constant_time_size));
|
||||||
BOOST_STATIC_ASSERT((boost::is_convertible<T, value_type>::value));
|
|
||||||
node_ptr to_remove(value_traits::to_node_ptr(value));
|
node_ptr to_remove(value_traits::to_node_ptr(value));
|
||||||
node_algorithms::unlink_and_rebalance(to_remove);
|
node_algorithms::unlink(to_remove);
|
||||||
if(safemode_or_autounlink)
|
if(safemode_or_autounlink)
|
||||||
node_algorithms::init(to_remove);
|
node_algorithms::init(to_remove);
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
|
||||||
/// @cond
|
/// @cond
|
||||||
private:
|
private:
|
||||||
@@ -1233,6 +1248,9 @@ class rbtree_impl
|
|||||||
rbtree_impl *rb = detail::parent_from_member<rbtree_impl, data_t>(d, &rbtree_impl::data_);
|
rbtree_impl *rb = detail::parent_from_member<rbtree_impl, data_t>(d, &rbtree_impl::data_);
|
||||||
return *rb;
|
return *rb;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static rbtree_impl &priv_container_from_iterator(const const_iterator &it)
|
||||||
|
{ return priv_container_from_end_iterator(it.end_iterator_from_it()); }
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
|
#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
|
||||||
@@ -1426,6 +1444,12 @@ class rbtree
|
|||||||
|
|
||||||
static const rbtree &container_from_end_iterator(const_iterator end_iterator)
|
static const rbtree &container_from_end_iterator(const_iterator end_iterator)
|
||||||
{ return static_cast<const rbtree &>(Base::container_from_end_iterator(end_iterator)); }
|
{ return static_cast<const rbtree &>(Base::container_from_end_iterator(end_iterator)); }
|
||||||
|
|
||||||
|
static rbtree &container_from_it(iterator it)
|
||||||
|
{ return static_cast<rbtree &>(Base::container_from_iterator(it)); }
|
||||||
|
|
||||||
|
static const rbtree &container_from_it(const_iterator it)
|
||||||
|
{ return static_cast<const rbtree &>(Base::container_from_iterator(it)); }
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@@ -54,7 +54,6 @@
|
|||||||
#include <boost/intrusive/intrusive_fwd.hpp>
|
#include <boost/intrusive/intrusive_fwd.hpp>
|
||||||
|
|
||||||
#include <boost/intrusive/detail/assert.hpp>
|
#include <boost/intrusive/detail/assert.hpp>
|
||||||
#include <boost/intrusive/detail/no_exceptions_support.hpp>
|
|
||||||
#include <boost/intrusive/detail/utilities.hpp>
|
#include <boost/intrusive/detail/utilities.hpp>
|
||||||
#include <boost/intrusive/detail/tree_algorithms.hpp>
|
#include <boost/intrusive/detail/tree_algorithms.hpp>
|
||||||
|
|
||||||
@@ -695,6 +694,16 @@ class rbtree_algorithms
|
|||||||
rebalance_after_insertion(header, new_value);
|
rebalance_after_insertion(header, new_value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//! <b>Requires</b>: "n" must be a node inserted in a tree.
|
||||||
|
//!
|
||||||
|
//! <b>Effects</b>: Returns a pointer to the header node of the tree.
|
||||||
|
//!
|
||||||
|
//! <b>Complexity</b>: Logarithmic.
|
||||||
|
//!
|
||||||
|
//! <b>Throws</b>: Nothing.
|
||||||
|
static node_ptr get_header(node_ptr n)
|
||||||
|
{ return tree_algorithms::get_header(n); }
|
||||||
|
|
||||||
/// @cond
|
/// @cond
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
@@ -226,7 +226,7 @@ class set_impl
|
|||||||
//! <b>Precondition</b>: end_iterator must be a valid end iterator
|
//! <b>Precondition</b>: end_iterator must be a valid end iterator
|
||||||
//! of set.
|
//! of set.
|
||||||
//!
|
//!
|
||||||
//! <b>Effects</b>: Returns a const reference to the set associated to the end iterator
|
//! <b>Effects</b>: Returns a reference to the set associated to the end iterator
|
||||||
//!
|
//!
|
||||||
//! <b>Throws</b>: Nothing.
|
//! <b>Throws</b>: Nothing.
|
||||||
//!
|
//!
|
||||||
@@ -253,6 +253,34 @@ class set_impl
|
|||||||
, &set_impl::tree_);
|
, &set_impl::tree_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//! <b>Precondition</b>: it must be a valid iterator of set.
|
||||||
|
//!
|
||||||
|
//! <b>Effects</b>: Returns a reference to the set associated to the iterator
|
||||||
|
//!
|
||||||
|
//! <b>Throws</b>: Nothing.
|
||||||
|
//!
|
||||||
|
//! <b>Complexity</b>: Logarithmic.
|
||||||
|
static set_impl &container_from_iterator(iterator it)
|
||||||
|
{
|
||||||
|
return *detail::parent_from_member<set_impl, tree_type>
|
||||||
|
( &tree_type::container_from_iterator(it)
|
||||||
|
, &set_impl::tree_);
|
||||||
|
}
|
||||||
|
|
||||||
|
//! <b>Precondition</b>: it must be a valid const_iterator of set.
|
||||||
|
//!
|
||||||
|
//! <b>Effects</b>: Returns a const reference to the set associated to the iterator
|
||||||
|
//!
|
||||||
|
//! <b>Throws</b>: Nothing.
|
||||||
|
//!
|
||||||
|
//! <b>Complexity</b>: Logarithmic.
|
||||||
|
static const set_impl &container_from_iterator(const_iterator it)
|
||||||
|
{
|
||||||
|
return *detail::parent_from_member<set_impl, tree_type>
|
||||||
|
( &tree_type::container_from_iterator(it)
|
||||||
|
, &set_impl::tree_);
|
||||||
|
}
|
||||||
|
|
||||||
//! <b>Effects</b>: Returns the key_compare object used by the set.
|
//! <b>Effects</b>: Returns the key_compare object used by the set.
|
||||||
//!
|
//!
|
||||||
//! <b>Complexity</b>: Constant.
|
//! <b>Complexity</b>: Constant.
|
||||||
@@ -1086,6 +1114,12 @@ class set
|
|||||||
|
|
||||||
static const set &container_from_end_iterator(const_iterator end_iterator)
|
static const set &container_from_end_iterator(const_iterator end_iterator)
|
||||||
{ return static_cast<const set &>(Base::container_from_end_iterator(end_iterator)); }
|
{ return static_cast<const set &>(Base::container_from_end_iterator(end_iterator)); }
|
||||||
|
|
||||||
|
static set &container_from_iterator(iterator it)
|
||||||
|
{ return static_cast<set &>(Base::container_from_iterator(it)); }
|
||||||
|
|
||||||
|
static const set &container_from_iterator(const_iterator it)
|
||||||
|
{ return static_cast<const set &>(Base::container_from_iterator(it)); }
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -1318,6 +1352,34 @@ class multiset_impl
|
|||||||
, &multiset_impl::tree_);
|
, &multiset_impl::tree_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//! <b>Precondition</b>: it must be a valid iterator of multiset.
|
||||||
|
//!
|
||||||
|
//! <b>Effects</b>: Returns a const reference to the multiset associated to the iterator
|
||||||
|
//!
|
||||||
|
//! <b>Throws</b>: Nothing.
|
||||||
|
//!
|
||||||
|
//! <b>Complexity</b>: Constant.
|
||||||
|
static multiset_impl &container_from_iterator(iterator it)
|
||||||
|
{
|
||||||
|
return *detail::parent_from_member<multiset_impl, tree_type>
|
||||||
|
( &tree_type::container_from_iterator(it)
|
||||||
|
, &multiset_impl::tree_);
|
||||||
|
}
|
||||||
|
|
||||||
|
//! <b>Precondition</b>: it must be a valid const_iterator of multiset.
|
||||||
|
//!
|
||||||
|
//! <b>Effects</b>: Returns a const reference to the multiset associated to the iterator
|
||||||
|
//!
|
||||||
|
//! <b>Throws</b>: Nothing.
|
||||||
|
//!
|
||||||
|
//! <b>Complexity</b>: Constant.
|
||||||
|
static const multiset_impl &container_from_iterator(const_iterator it)
|
||||||
|
{
|
||||||
|
return *detail::parent_from_member<multiset_impl, tree_type>
|
||||||
|
( &tree_type::container_from_iterator(it)
|
||||||
|
, &multiset_impl::tree_);
|
||||||
|
}
|
||||||
|
|
||||||
//! <b>Effects</b>: Returns the key_compare object used by the multiset.
|
//! <b>Effects</b>: Returns the key_compare object used by the multiset.
|
||||||
//!
|
//!
|
||||||
//! <b>Complexity</b>: Constant.
|
//! <b>Complexity</b>: Constant.
|
||||||
@@ -1932,6 +1994,21 @@ class multiset_impl
|
|||||||
void replace_node(iterator replace_this, reference with_this)
|
void replace_node(iterator replace_this, reference with_this)
|
||||||
{ tree_.replace_node(replace_this, with_this); }
|
{ tree_.replace_node(replace_this, with_this); }
|
||||||
|
|
||||||
|
//! <b>Effects</b>: removes "value" from the container.
|
||||||
|
//!
|
||||||
|
//! <b>Throws</b>: Nothing.
|
||||||
|
//!
|
||||||
|
//! <b>Complexity</b>: Logarithmic time.
|
||||||
|
//!
|
||||||
|
//! <b>Note</b>: This static function is only usable with non-constant
|
||||||
|
//! time size containers that have stateless comparison functors.
|
||||||
|
//!
|
||||||
|
//! If the user calls
|
||||||
|
//! this function with a constant time size container or stateful comparison
|
||||||
|
//! functor a compilation error will be issued.
|
||||||
|
static void remove_node(reference value)
|
||||||
|
{ tree_type::remove_node(value); }
|
||||||
|
|
||||||
/// @cond
|
/// @cond
|
||||||
friend bool operator==(const multiset_impl &x, const multiset_impl &y)
|
friend bool operator==(const multiset_impl &x, const multiset_impl &y)
|
||||||
{ return x.tree_ == y.tree_; }
|
{ return x.tree_ == y.tree_; }
|
||||||
@@ -2058,6 +2135,12 @@ class multiset
|
|||||||
|
|
||||||
static const multiset &container_from_end_iterator(const_iterator end_iterator)
|
static const multiset &container_from_end_iterator(const_iterator end_iterator)
|
||||||
{ return static_cast<const multiset &>(Base::container_from_end_iterator(end_iterator)); }
|
{ return static_cast<const multiset &>(Base::container_from_end_iterator(end_iterator)); }
|
||||||
|
|
||||||
|
static multiset &container_from_iterator(iterator it)
|
||||||
|
{ return static_cast<multiset &>(Base::container_from_iterator(it)); }
|
||||||
|
|
||||||
|
static const multiset &container_from_iterator(const_iterator it)
|
||||||
|
{ return static_cast<const multiset &>(Base::container_from_iterator(it)); }
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@@ -252,6 +252,34 @@ class sg_set_impl
|
|||||||
, &sg_set_impl::tree_);
|
, &sg_set_impl::tree_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//! <b>Precondition</b>: it must be a valid iterator of set.
|
||||||
|
//!
|
||||||
|
//! <b>Effects</b>: Returns a reference to the set associated to the iterator
|
||||||
|
//!
|
||||||
|
//! <b>Throws</b>: Nothing.
|
||||||
|
//!
|
||||||
|
//! <b>Complexity</b>: Logarithmic.
|
||||||
|
static sg_set_impl &container_from_iterator(iterator it)
|
||||||
|
{
|
||||||
|
return *detail::parent_from_member<sg_set_impl, tree_type>
|
||||||
|
( &tree_type::container_from_iterator(it)
|
||||||
|
, &sg_set_impl::tree_);
|
||||||
|
}
|
||||||
|
|
||||||
|
//! <b>Precondition</b>: it must be a valid const_iterator of set.
|
||||||
|
//!
|
||||||
|
//! <b>Effects</b>: Returns a const reference to the set associated to the iterator
|
||||||
|
//!
|
||||||
|
//! <b>Throws</b>: Nothing.
|
||||||
|
//!
|
||||||
|
//! <b>Complexity</b>: Logarithmic.
|
||||||
|
static const sg_set_impl &container_from_iterator(const_iterator it)
|
||||||
|
{
|
||||||
|
return *detail::parent_from_member<sg_set_impl, tree_type>
|
||||||
|
( &tree_type::container_from_iterator(it)
|
||||||
|
, &sg_set_impl::tree_);
|
||||||
|
}
|
||||||
|
|
||||||
//! <b>Effects</b>: Returns the key_compare object used by the sg_set.
|
//! <b>Effects</b>: Returns the key_compare object used by the sg_set.
|
||||||
//!
|
//!
|
||||||
//! <b>Complexity</b>: Constant.
|
//! <b>Complexity</b>: Constant.
|
||||||
@@ -1124,6 +1152,12 @@ class sg_set
|
|||||||
|
|
||||||
static const sg_set &container_from_end_iterator(const_iterator end_iterator)
|
static const sg_set &container_from_end_iterator(const_iterator end_iterator)
|
||||||
{ return static_cast<const sg_set &>(Base::container_from_end_iterator(end_iterator)); }
|
{ return static_cast<const sg_set &>(Base::container_from_end_iterator(end_iterator)); }
|
||||||
|
|
||||||
|
static sg_set &container_from_iterator(iterator it)
|
||||||
|
{ return static_cast<sg_set &>(Base::container_from_iterator(it)); }
|
||||||
|
|
||||||
|
static const sg_set &container_from_iterator(const_iterator it)
|
||||||
|
{ return static_cast<const sg_set &>(Base::container_from_iterator(it)); }
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -1356,6 +1390,34 @@ class sg_multiset_impl
|
|||||||
, &sg_multiset_impl::tree_);
|
, &sg_multiset_impl::tree_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//! <b>Precondition</b>: it must be a valid iterator of multiset.
|
||||||
|
//!
|
||||||
|
//! <b>Effects</b>: Returns a const reference to the multiset associated to the iterator
|
||||||
|
//!
|
||||||
|
//! <b>Throws</b>: Nothing.
|
||||||
|
//!
|
||||||
|
//! <b>Complexity</b>: Constant.
|
||||||
|
static sg_multiset_impl &container_from_iterator(iterator it)
|
||||||
|
{
|
||||||
|
return *detail::parent_from_member<sg_multiset_impl, tree_type>
|
||||||
|
( &tree_type::container_from_iterator(it)
|
||||||
|
, &sg_multiset_impl::tree_);
|
||||||
|
}
|
||||||
|
|
||||||
|
//! <b>Precondition</b>: it must be a valid const_iterator of multiset.
|
||||||
|
//!
|
||||||
|
//! <b>Effects</b>: Returns a const reference to the multiset associated to the iterator
|
||||||
|
//!
|
||||||
|
//! <b>Throws</b>: Nothing.
|
||||||
|
//!
|
||||||
|
//! <b>Complexity</b>: Constant.
|
||||||
|
static const sg_multiset_impl &container_from_iterator(const_iterator it)
|
||||||
|
{
|
||||||
|
return *detail::parent_from_member<sg_multiset_impl, tree_type>
|
||||||
|
( &tree_type::container_from_iterator(it)
|
||||||
|
, &sg_multiset_impl::tree_);
|
||||||
|
}
|
||||||
|
|
||||||
//! <b>Effects</b>: Returns the key_compare object used by the sg_multiset.
|
//! <b>Effects</b>: Returns the key_compare object used by the sg_multiset.
|
||||||
//!
|
//!
|
||||||
//! <b>Complexity</b>: Constant.
|
//! <b>Complexity</b>: Constant.
|
||||||
@@ -2135,6 +2197,12 @@ class sg_multiset
|
|||||||
|
|
||||||
static const sg_multiset &container_from_end_iterator(const_iterator end_iterator)
|
static const sg_multiset &container_from_end_iterator(const_iterator end_iterator)
|
||||||
{ return static_cast<const sg_multiset &>(Base::container_from_end_iterator(end_iterator)); }
|
{ return static_cast<const sg_multiset &>(Base::container_from_end_iterator(end_iterator)); }
|
||||||
|
|
||||||
|
static sg_multiset &container_from_iterator(iterator it)
|
||||||
|
{ return static_cast<sg_multiset &>(Base::container_from_iterator(it)); }
|
||||||
|
|
||||||
|
static const sg_multiset &container_from_iterator(const_iterator it)
|
||||||
|
{ return static_cast<const sg_multiset &>(Base::container_from_iterator(it)); }
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@@ -527,6 +527,28 @@ class sgtree_impl
|
|||||||
static const sgtree_impl &container_from_end_iterator(const_iterator end_iterator)
|
static const sgtree_impl &container_from_end_iterator(const_iterator end_iterator)
|
||||||
{ return priv_container_from_end_iterator(end_iterator); }
|
{ return priv_container_from_end_iterator(end_iterator); }
|
||||||
|
|
||||||
|
//! <b>Precondition</b>: it must be a valid iterator
|
||||||
|
//! of rbtree.
|
||||||
|
//!
|
||||||
|
//! <b>Effects</b>: Returns a const reference to the tree associated to the iterator
|
||||||
|
//!
|
||||||
|
//! <b>Throws</b>: Nothing.
|
||||||
|
//!
|
||||||
|
//! <b>Complexity</b>: Logarithmic.
|
||||||
|
static sgtree_impl &container_from_iterator(iterator it)
|
||||||
|
{ return priv_container_from_iterator(it); }
|
||||||
|
|
||||||
|
//! <b>Precondition</b>: it must be a valid end const_iterator
|
||||||
|
//! of rbtree.
|
||||||
|
//!
|
||||||
|
//! <b>Effects</b>: Returns a const reference to the tree associated to the iterator
|
||||||
|
//!
|
||||||
|
//! <b>Throws</b>: Nothing.
|
||||||
|
//!
|
||||||
|
//! <b>Complexity</b>: Logarithmic.
|
||||||
|
static const sgtree_impl &container_from_iterator(const_iterator it)
|
||||||
|
{ return priv_container_from_iterator(it); }
|
||||||
|
|
||||||
//! <b>Effects</b>: Returns the value_compare object used by the tree.
|
//! <b>Effects</b>: Returns the value_compare object used by the tree.
|
||||||
//!
|
//!
|
||||||
//! <b>Complexity</b>: Constant.
|
//! <b>Complexity</b>: Constant.
|
||||||
@@ -1442,6 +1464,9 @@ class sgtree_impl
|
|||||||
sgtree_impl *scapegoat = detail::parent_from_member<sgtree_impl, data_t>(d, &sgtree_impl::data_);
|
sgtree_impl *scapegoat = detail::parent_from_member<sgtree_impl, data_t>(d, &sgtree_impl::data_);
|
||||||
return *scapegoat;
|
return *scapegoat;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static sgtree_impl &priv_container_from_iterator(const const_iterator &it)
|
||||||
|
{ return priv_container_from_end_iterator(it.end_iterator_from_it()); }
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
|
#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
|
||||||
|
@@ -22,7 +22,6 @@
|
|||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
#include <boost/intrusive/intrusive_fwd.hpp>
|
#include <boost/intrusive/intrusive_fwd.hpp>
|
||||||
#include <boost/intrusive/detail/assert.hpp>
|
#include <boost/intrusive/detail/assert.hpp>
|
||||||
#include <boost/intrusive/detail/no_exceptions_support.hpp>
|
|
||||||
#include <boost/intrusive/detail/utilities.hpp>
|
#include <boost/intrusive/detail/utilities.hpp>
|
||||||
#include <boost/intrusive/detail/tree_algorithms.hpp>
|
#include <boost/intrusive/detail/tree_algorithms.hpp>
|
||||||
|
|
||||||
@@ -640,6 +639,16 @@ class sgtree_algorithms
|
|||||||
static node_ptr rebalance_subtree(node_ptr old_root)
|
static node_ptr rebalance_subtree(node_ptr old_root)
|
||||||
{ return tree_algorithms::rebalance_subtree(old_root); }
|
{ return tree_algorithms::rebalance_subtree(old_root); }
|
||||||
|
|
||||||
|
//! <b>Requires</b>: "n" must be a node inserted in a tree.
|
||||||
|
//!
|
||||||
|
//! <b>Effects</b>: Returns a pointer to the header node of the tree.
|
||||||
|
//!
|
||||||
|
//! <b>Complexity</b>: Logarithmic.
|
||||||
|
//!
|
||||||
|
//! <b>Throws</b>: Nothing.
|
||||||
|
static node_ptr get_header(node_ptr n)
|
||||||
|
{ return tree_algorithms::get_header(n); }
|
||||||
|
|
||||||
/// @cond
|
/// @cond
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
@@ -16,7 +16,6 @@
|
|||||||
|
|
||||||
#include <boost/intrusive/detail/config_begin.hpp>
|
#include <boost/intrusive/detail/config_begin.hpp>
|
||||||
#include <boost/static_assert.hpp>
|
#include <boost/static_assert.hpp>
|
||||||
#include <boost/intrusive/detail/no_exceptions_support.hpp>
|
|
||||||
#include <boost/intrusive/detail/assert.hpp>
|
#include <boost/intrusive/detail/assert.hpp>
|
||||||
#include <boost/intrusive/intrusive_fwd.hpp>
|
#include <boost/intrusive/intrusive_fwd.hpp>
|
||||||
#include <boost/intrusive/slist_hook.hpp>
|
#include <boost/intrusive/slist_hook.hpp>
|
||||||
@@ -25,6 +24,7 @@
|
|||||||
#include <boost/intrusive/detail/pointer_to_other.hpp>
|
#include <boost/intrusive/detail/pointer_to_other.hpp>
|
||||||
#include <boost/intrusive/link_mode.hpp>
|
#include <boost/intrusive/link_mode.hpp>
|
||||||
#include <boost/intrusive/options.hpp>
|
#include <boost/intrusive/options.hpp>
|
||||||
|
#include <boost/intrusive/detail/utilities.hpp>
|
||||||
#include <iterator>
|
#include <iterator>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
@@ -183,10 +183,12 @@ class slist_impl
|
|||||||
BOOST_STATIC_ASSERT(!(cache_last && ((int)real_value_traits::link_mode == (int)auto_unlink)));
|
BOOST_STATIC_ASSERT(!(cache_last && ((int)real_value_traits::link_mode == (int)auto_unlink)));
|
||||||
|
|
||||||
node_ptr get_end_node()
|
node_ptr get_end_node()
|
||||||
{ return node_ptr(linear ? 0 : this->get_root_node()); }
|
{ return node_ptr(linear ? node_ptr(0) : this->get_root_node()); }
|
||||||
|
|
||||||
const_node_ptr get_end_node() const
|
const_node_ptr get_end_node() const
|
||||||
{ return const_node_ptr(linear ? 0 : this->get_root_node()); }
|
{
|
||||||
|
return const_node_ptr
|
||||||
|
(linear ? const_node_ptr(0) : this->get_root_node()); }
|
||||||
|
|
||||||
node_ptr get_root_node()
|
node_ptr get_root_node()
|
||||||
{ return node_ptr(&data_.root_plus_size_.root_); }
|
{ return node_ptr(&data_.root_plus_size_.root_); }
|
||||||
@@ -203,13 +205,10 @@ class slist_impl
|
|||||||
void set_last_node(node_ptr n)
|
void set_last_node(node_ptr n)
|
||||||
{ return this->set_last_node(n, detail::bool_<cache_last>()); }
|
{ return this->set_last_node(n, detail::bool_<cache_last>()); }
|
||||||
|
|
||||||
node_ptr get_last_node(detail::bool_<false>)
|
static node_ptr get_last_node(detail::bool_<false>)
|
||||||
{ return node_ptr(0); }
|
{ return node_ptr(0); }
|
||||||
|
|
||||||
const_node_ptr get_last_node(detail::bool_<false>) const
|
static void set_last_node(node_ptr, detail::bool_<false>)
|
||||||
{ return const_node_ptr(0); }
|
|
||||||
|
|
||||||
void set_last_node(node_ptr, detail::bool_<false>)
|
|
||||||
{}
|
{}
|
||||||
|
|
||||||
node_ptr get_last_node(detail::bool_<true>)
|
node_ptr get_last_node(detail::bool_<true>)
|
||||||
@@ -667,18 +666,14 @@ class slist_impl
|
|||||||
void clone_from(const slist_impl &src, Cloner cloner, Disposer disposer)
|
void clone_from(const slist_impl &src, Cloner cloner, Disposer disposer)
|
||||||
{
|
{
|
||||||
this->clear_and_dispose(disposer);
|
this->clear_and_dispose(disposer);
|
||||||
BOOST_INTRUSIVE_TRY{
|
detail::exception_disposer<slist_impl, Disposer>
|
||||||
iterator prev(this->before_begin());
|
rollback(*this, disposer);
|
||||||
const_iterator b(src.begin()), e(src.end());
|
iterator prev(this->before_begin());
|
||||||
for(; b != e; ++b){
|
const_iterator b(src.begin()), e(src.end());
|
||||||
prev = this->insert_after(prev, *cloner(*b));
|
for(; b != e; ++b){
|
||||||
}
|
prev = this->insert_after(prev, *cloner(*b));
|
||||||
}
|
}
|
||||||
BOOST_INTRUSIVE_CATCH(...){
|
rollback.release();
|
||||||
this->clear_and_dispose(disposer);
|
|
||||||
BOOST_INTRUSIVE_RETHROW;
|
|
||||||
}
|
|
||||||
BOOST_INTRUSIVE_CATCH_END
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//! <b>Requires</b>: value must be an lvalue and prev_p must point to an element
|
//! <b>Requires</b>: value must be an lvalue and prev_p must point to an element
|
||||||
@@ -849,13 +844,36 @@ class slist_impl
|
|||||||
if(cache_last && (to_erase == this->get_last_node())){
|
if(cache_last && (to_erase == this->get_last_node())){
|
||||||
this->set_last_node(prev_n);
|
this->set_last_node(prev_n);
|
||||||
}
|
}
|
||||||
this->priv_size_traits().decrement();
|
|
||||||
if(safemode_or_autounlink)
|
if(safemode_or_autounlink)
|
||||||
node_algorithms::init(to_erase);
|
node_algorithms::init(to_erase);
|
||||||
disposer(get_real_value_traits().to_value_ptr(to_erase));
|
disposer(get_real_value_traits().to_value_ptr(to_erase));
|
||||||
|
this->priv_size_traits().decrement();
|
||||||
return it;
|
return it;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// @cond
|
||||||
|
|
||||||
|
template<class Disposer>
|
||||||
|
static iterator s_erase_after_and_dispose(iterator prev, Disposer disposer)
|
||||||
|
{
|
||||||
|
BOOST_STATIC_ASSERT(((!cache_last)&&(!constant_time_size)&&(!stateful_value_traits)));
|
||||||
|
iterator it(prev);
|
||||||
|
++it;
|
||||||
|
node_ptr to_erase(it.pointed_node());
|
||||||
|
++it;
|
||||||
|
node_ptr prev_n(prev.pointed_node());
|
||||||
|
node_algorithms::unlink_after(prev_n);
|
||||||
|
if(safemode_or_autounlink)
|
||||||
|
node_algorithms::init(to_erase);
|
||||||
|
disposer(real_value_traits::to_value_ptr(to_erase));
|
||||||
|
return it;
|
||||||
|
}
|
||||||
|
|
||||||
|
static iterator s_erase_after(iterator prev)
|
||||||
|
{ return s_erase_after_and_dispose(prev, detail::null_disposer()); }
|
||||||
|
|
||||||
|
/// @endcond
|
||||||
|
|
||||||
//! <b>Requires</b>: Disposer::operator()(pointer) shouldn't throw.
|
//! <b>Requires</b>: Disposer::operator()(pointer) shouldn't throw.
|
||||||
//!
|
//!
|
||||||
//! <b>Effects</b>: Erases the range (before_first, last) from
|
//! <b>Effects</b>: Erases the range (before_first, last) from
|
||||||
|
@@ -252,6 +252,34 @@ class splay_set_impl
|
|||||||
, &splay_set_impl::tree_);
|
, &splay_set_impl::tree_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//! <b>Precondition</b>: it must be a valid iterator of set.
|
||||||
|
//!
|
||||||
|
//! <b>Effects</b>: Returns a reference to the set associated to the iterator
|
||||||
|
//!
|
||||||
|
//! <b>Throws</b>: Nothing.
|
||||||
|
//!
|
||||||
|
//! <b>Complexity</b>: Constant.
|
||||||
|
static splay_set_impl &container_from_iterator(iterator it)
|
||||||
|
{
|
||||||
|
return *detail::parent_from_member<splay_set_impl, tree_type>
|
||||||
|
( &tree_type::container_from_iterator(it)
|
||||||
|
, &splay_set_impl::tree_);
|
||||||
|
}
|
||||||
|
|
||||||
|
//! <b>Precondition</b>: it must be a valid const_iterator of set.
|
||||||
|
//!
|
||||||
|
//! <b>Effects</b>: Returns a const reference to the set associated to the iterator
|
||||||
|
//!
|
||||||
|
//! <b>Throws</b>: Nothing.
|
||||||
|
//!
|
||||||
|
//! <b>Complexity</b>: Logarithmic.
|
||||||
|
static const splay_set_impl &container_from_iterator(const_iterator it)
|
||||||
|
{
|
||||||
|
return *detail::parent_from_member<splay_set_impl, tree_type>
|
||||||
|
( &tree_type::container_from_iterator(it)
|
||||||
|
, &splay_set_impl::tree_);
|
||||||
|
}
|
||||||
|
|
||||||
//! <b>Effects</b>: Returns the key_compare object used by the splay_set.
|
//! <b>Effects</b>: Returns the key_compare object used by the splay_set.
|
||||||
//!
|
//!
|
||||||
//! <b>Complexity</b>: Constant.
|
//! <b>Complexity</b>: Constant.
|
||||||
@@ -1161,6 +1189,12 @@ class splay_set
|
|||||||
|
|
||||||
static const splay_set &container_from_end_iterator(const_iterator end_iterator)
|
static const splay_set &container_from_end_iterator(const_iterator end_iterator)
|
||||||
{ return static_cast<const splay_set &>(Base::container_from_end_iterator(end_iterator)); }
|
{ return static_cast<const splay_set &>(Base::container_from_end_iterator(end_iterator)); }
|
||||||
|
|
||||||
|
static splay_set &container_from_iterator(iterator it)
|
||||||
|
{ return static_cast<splay_set &>(Base::container_from_iterator(it)); }
|
||||||
|
|
||||||
|
static const splay_set &container_from_iterator(const_iterator it)
|
||||||
|
{ return static_cast<const splay_set &>(Base::container_from_iterator(it)); }
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -1393,6 +1427,34 @@ class splay_multiset_impl
|
|||||||
, &splay_multiset_impl::tree_);
|
, &splay_multiset_impl::tree_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//! <b>Precondition</b>: it must be a valid iterator of multiset.
|
||||||
|
//!
|
||||||
|
//! <b>Effects</b>: Returns a const reference to the multiset associated to the iterator
|
||||||
|
//!
|
||||||
|
//! <b>Throws</b>: Nothing.
|
||||||
|
//!
|
||||||
|
//! <b>Complexity</b>: Logarithmic.
|
||||||
|
static splay_multiset_impl &container_from_iterator(iterator it)
|
||||||
|
{
|
||||||
|
return *detail::parent_from_member<splay_multiset_impl, tree_type>
|
||||||
|
( &tree_type::container_from_iterator(it)
|
||||||
|
, &splay_multiset_impl::tree_);
|
||||||
|
}
|
||||||
|
|
||||||
|
//! <b>Precondition</b>: it must be a valid const_iterator of multiset.
|
||||||
|
//!
|
||||||
|
//! <b>Effects</b>: Returns a const reference to the multiset associated to the iterator
|
||||||
|
//!
|
||||||
|
//! <b>Throws</b>: Nothing.
|
||||||
|
//!
|
||||||
|
//! <b>Complexity</b>: Constant.
|
||||||
|
static const splay_multiset_impl &container_from_iterator(const_iterator it)
|
||||||
|
{
|
||||||
|
return *detail::parent_from_member<splay_multiset_impl, tree_type>
|
||||||
|
( &tree_type::container_from_iterator(it)
|
||||||
|
, &splay_multiset_impl::tree_);
|
||||||
|
}
|
||||||
|
|
||||||
//! <b>Effects</b>: Returns the key_compare object used by the splay_multiset.
|
//! <b>Effects</b>: Returns the key_compare object used by the splay_multiset.
|
||||||
//!
|
//!
|
||||||
//! <b>Complexity</b>: Constant.
|
//! <b>Complexity</b>: Constant.
|
||||||
@@ -2209,6 +2271,12 @@ class splay_multiset
|
|||||||
|
|
||||||
static const splay_multiset &container_from_end_iterator(const_iterator end_iterator)
|
static const splay_multiset &container_from_end_iterator(const_iterator end_iterator)
|
||||||
{ return static_cast<const splay_multiset &>(Base::container_from_end_iterator(end_iterator)); }
|
{ return static_cast<const splay_multiset &>(Base::container_from_end_iterator(end_iterator)); }
|
||||||
|
|
||||||
|
static splay_multiset &container_from_iterator(iterator it)
|
||||||
|
{ return static_cast<splay_multiset &>(Base::container_from_iterator(it)); }
|
||||||
|
|
||||||
|
static const splay_multiset &container_from_iterator(const_iterator it)
|
||||||
|
{ return static_cast<const splay_multiset &>(Base::container_from_iterator(it)); }
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@@ -387,6 +387,28 @@ class splaytree_impl
|
|||||||
static const splaytree_impl &container_from_end_iterator(const_iterator end_iterator)
|
static const splaytree_impl &container_from_end_iterator(const_iterator end_iterator)
|
||||||
{ return priv_container_from_end_iterator(end_iterator); }
|
{ return priv_container_from_end_iterator(end_iterator); }
|
||||||
|
|
||||||
|
//! <b>Precondition</b>: it must be a valid iterator
|
||||||
|
//! of rbtree.
|
||||||
|
//!
|
||||||
|
//! <b>Effects</b>: Returns a const reference to the tree associated to the iterator
|
||||||
|
//!
|
||||||
|
//! <b>Throws</b>: Nothing.
|
||||||
|
//!
|
||||||
|
//! <b>Complexity</b>: Logarithmic.
|
||||||
|
static splaytree_impl &container_from_iterator(iterator it)
|
||||||
|
{ return priv_container_from_iterator(it); }
|
||||||
|
|
||||||
|
//! <b>Precondition</b>: it must be a valid end const_iterator
|
||||||
|
//! of rbtree.
|
||||||
|
//!
|
||||||
|
//! <b>Effects</b>: Returns a const reference to the tree associated to the iterator
|
||||||
|
//!
|
||||||
|
//! <b>Throws</b>: Nothing.
|
||||||
|
//!
|
||||||
|
//! <b>Complexity</b>: Logarithmic.
|
||||||
|
static const splaytree_impl &container_from_iterator(const_iterator it)
|
||||||
|
{ return priv_container_from_iterator(it); }
|
||||||
|
|
||||||
//! <b>Effects</b>: Returns the value_compare object used by the tree.
|
//! <b>Effects</b>: Returns the value_compare object used by the tree.
|
||||||
//!
|
//!
|
||||||
//! <b>Complexity</b>: Constant.
|
//! <b>Complexity</b>: Constant.
|
||||||
@@ -1312,6 +1334,9 @@ class splaytree_impl
|
|||||||
splaytree_impl *rb = detail::parent_from_member<splaytree_impl, data_t>(d, &splaytree_impl::data_);
|
splaytree_impl *rb = detail::parent_from_member<splaytree_impl, data_t>(d, &splaytree_impl::data_);
|
||||||
return *rb;
|
return *rb;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static splaytree_impl &priv_container_from_iterator(const const_iterator &it)
|
||||||
|
{ return priv_container_from_end_iterator(it.end_iterator_from_it()); }
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
|
#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
|
||||||
|
@@ -50,13 +50,48 @@
|
|||||||
#include <boost/intrusive/detail/assert.hpp>
|
#include <boost/intrusive/detail/assert.hpp>
|
||||||
#include <boost/intrusive/intrusive_fwd.hpp>
|
#include <boost/intrusive/intrusive_fwd.hpp>
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
#include <boost/intrusive/detail/no_exceptions_support.hpp>
|
|
||||||
#include <boost/intrusive/detail/utilities.hpp>
|
#include <boost/intrusive/detail/utilities.hpp>
|
||||||
#include <boost/intrusive/detail/tree_algorithms.hpp>
|
#include <boost/intrusive/detail/tree_algorithms.hpp>
|
||||||
|
|
||||||
namespace boost {
|
namespace boost {
|
||||||
namespace intrusive {
|
namespace intrusive {
|
||||||
|
|
||||||
|
/// @cond
|
||||||
|
namespace detail {
|
||||||
|
|
||||||
|
template<class NodeTraits>
|
||||||
|
struct splaydown_rollback
|
||||||
|
{
|
||||||
|
typedef typename NodeTraits::node_ptr node_ptr;
|
||||||
|
splaydown_rollback( const node_ptr *pcur_subtree, node_ptr header
|
||||||
|
, node_ptr leftmost , node_ptr rightmost)
|
||||||
|
: pcur_subtree_(pcur_subtree) , header_(header)
|
||||||
|
, leftmost_(leftmost) , rightmost_(rightmost)
|
||||||
|
{}
|
||||||
|
|
||||||
|
void release()
|
||||||
|
{ pcur_subtree_ = 0; }
|
||||||
|
|
||||||
|
~splaydown_rollback()
|
||||||
|
{
|
||||||
|
if(pcur_subtree_){
|
||||||
|
//Exception can only be thrown by comp, but
|
||||||
|
//tree invariants still hold. *pcur_subtree is the current root
|
||||||
|
//so link it to the header.
|
||||||
|
NodeTraits::set_parent(*pcur_subtree_, header_);
|
||||||
|
NodeTraits::set_parent(header_, *pcur_subtree_);
|
||||||
|
//Recover leftmost/rightmost pointers
|
||||||
|
NodeTraits::set_left (header_, leftmost_);
|
||||||
|
NodeTraits::set_right(header_, rightmost_);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const node_ptr *pcur_subtree_;
|
||||||
|
node_ptr header_, leftmost_, rightmost_;
|
||||||
|
};
|
||||||
|
|
||||||
|
} //namespace detail {
|
||||||
|
/// @endcond
|
||||||
|
|
||||||
//! A splay tree is an implementation of a binary search tree. The tree is
|
//! A splay tree is an implementation of a binary search tree. The tree is
|
||||||
//! self balancing using the splay algorithm as described in
|
//! self balancing using the splay algorithm as described in
|
||||||
//!
|
//!
|
||||||
@@ -656,7 +691,8 @@ class splaytree_algorithms
|
|||||||
node_ptr leftmost = NodeTraits::get_left(header);
|
node_ptr leftmost = NodeTraits::get_left(header);
|
||||||
node_ptr rightmost = NodeTraits::get_right(header);
|
node_ptr rightmost = NodeTraits::get_right(header);
|
||||||
|
|
||||||
try{
|
{
|
||||||
|
detail::splaydown_rollback<NodeTraits> rollback(&t, header, leftmost, rightmost);
|
||||||
node_ptr null = header;
|
node_ptr null = header;
|
||||||
node_ptr l = null;
|
node_ptr l = null;
|
||||||
node_ptr r = null;
|
node_ptr r = null;
|
||||||
@@ -712,18 +748,9 @@ class splaytree_algorithms
|
|||||||
}
|
}
|
||||||
|
|
||||||
assemble(t, l, r, null);
|
assemble(t, l, r, null);
|
||||||
|
rollback.release();
|
||||||
}
|
}
|
||||||
catch(...){
|
|
||||||
//Exception can only be thrown by comp, but
|
|
||||||
//tree invariants still hold. t is the current root
|
|
||||||
//so link it to the header.
|
|
||||||
NodeTraits::set_parent(t, header);
|
|
||||||
NodeTraits::set_parent(header, t);
|
|
||||||
//Recover leftmost/rightmost pointers
|
|
||||||
NodeTraits::set_left (header, leftmost);
|
|
||||||
NodeTraits::set_right(header, rightmost);
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
//t is the current root
|
//t is the current root
|
||||||
NodeTraits::set_parent(header, t);
|
NodeTraits::set_parent(header, t);
|
||||||
NodeTraits::set_parent(t, header);
|
NodeTraits::set_parent(t, header);
|
||||||
@@ -755,6 +782,17 @@ class splaytree_algorithms
|
|||||||
static node_ptr rebalance_subtree(node_ptr old_root)
|
static node_ptr rebalance_subtree(node_ptr old_root)
|
||||||
{ return tree_algorithms::rebalance_subtree(old_root); }
|
{ return tree_algorithms::rebalance_subtree(old_root); }
|
||||||
|
|
||||||
|
|
||||||
|
//! <b>Requires</b>: "n" must be a node inserted in a tree.
|
||||||
|
//!
|
||||||
|
//! <b>Effects</b>: Returns a pointer to the header node of the tree.
|
||||||
|
//!
|
||||||
|
//! <b>Complexity</b>: Logarithmic.
|
||||||
|
//!
|
||||||
|
//! <b>Throws</b>: Nothing.
|
||||||
|
static node_ptr get_header(node_ptr n)
|
||||||
|
{ return tree_algorithms::get_header(n); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
/// @cond
|
/// @cond
|
||||||
|
@@ -38,7 +38,8 @@ namespace intrusive {
|
|||||||
//!
|
//!
|
||||||
//! The container supports the following options:
|
//! The container supports the following options:
|
||||||
//! \c base_hook<>/member_hook<>/value_traits<>,
|
//! \c base_hook<>/member_hook<>/value_traits<>,
|
||||||
//! \c constant_time_size<>, \c size_type<>, \c hash<> and \c equal<> .
|
//! \c constant_time_size<>, \c size_type<>, \c hash<> and \c equal<>
|
||||||
|
//! \c bucket_traits<>, power_2_buckets<> and cache_begin<>.
|
||||||
//!
|
//!
|
||||||
//! unordered_set only provides forward iterators but it provides 4 iterator types:
|
//! unordered_set only provides forward iterators but it provides 4 iterator types:
|
||||||
//! iterator and const_iterator to navigate through the whole container and
|
//! iterator and const_iterator to navigate through the whole container and
|
||||||
@@ -167,8 +168,8 @@ class unordered_set_impl
|
|||||||
|
|
||||||
//! <b>Effects</b>: Returns an iterator pointing to the beginning of the unordered_set.
|
//! <b>Effects</b>: Returns an iterator pointing to the beginning of the unordered_set.
|
||||||
//!
|
//!
|
||||||
//! <b>Complexity</b>: Amortized constant time.
|
//! <b>Complexity</b>: Constant time if `cache_begin<>` is true. Amortized
|
||||||
//! Worst case (empty unordered_set): O(this->bucket_count())
|
//! constant time with worst case (empty unordered_set) O(this->bucket_count())
|
||||||
//!
|
//!
|
||||||
//! <b>Throws</b>: Nothing.
|
//! <b>Throws</b>: Nothing.
|
||||||
iterator begin()
|
iterator begin()
|
||||||
@@ -177,8 +178,8 @@ class unordered_set_impl
|
|||||||
//! <b>Effects</b>: Returns a const_iterator pointing to the beginning
|
//! <b>Effects</b>: Returns a const_iterator pointing to the beginning
|
||||||
//! of the unordered_set.
|
//! of the unordered_set.
|
||||||
//!
|
//!
|
||||||
//! <b>Complexity</b>: Amortized constant time.
|
//! <b>Complexity</b>: Constant time if `cache_begin<>` is true. Amortized
|
||||||
//! Worst case (empty unordered_set): O(this->bucket_count())
|
//! constant time with worst case (empty unordered_set) O(this->bucket_count())
|
||||||
//!
|
//!
|
||||||
//! <b>Throws</b>: Nothing.
|
//! <b>Throws</b>: Nothing.
|
||||||
const_iterator begin() const
|
const_iterator begin() const
|
||||||
@@ -187,8 +188,8 @@ class unordered_set_impl
|
|||||||
//! <b>Effects</b>: Returns a const_iterator pointing to the beginning
|
//! <b>Effects</b>: Returns a const_iterator pointing to the beginning
|
||||||
//! of the unordered_set.
|
//! of the unordered_set.
|
||||||
//!
|
//!
|
||||||
//! <b>Complexity</b>: Amortized constant time.
|
//! <b>Complexity</b>: Constant time if `cache_begin<>` is true. Amortized
|
||||||
//! Worst case (empty unordered_set): O(this->bucket_count())
|
//! constant time with worst case (empty unordered_set) O(this->bucket_count())
|
||||||
//!
|
//!
|
||||||
//! <b>Throws</b>: Nothing.
|
//! <b>Throws</b>: Nothing.
|
||||||
const_iterator cbegin() const
|
const_iterator cbegin() const
|
||||||
@@ -236,8 +237,8 @@ class unordered_set_impl
|
|||||||
|
|
||||||
//! <b>Effects</b>: Returns true is the container is empty.
|
//! <b>Effects</b>: Returns true is the container is empty.
|
||||||
//!
|
//!
|
||||||
//! <b>Complexity</b>: if constant-time size option is disabled, average constant time
|
//! <b>Complexity</b>: if constant-time size and cache_last options are disabled,
|
||||||
//! (worst case, with empty() == true): O(this->bucket_count()).
|
//! average constant time (worst case, with empty() == true: O(this->bucket_count()).
|
||||||
//! Otherwise constant.
|
//! Otherwise constant.
|
||||||
//!
|
//!
|
||||||
//! <b>Throws</b>: Nothing.
|
//! <b>Throws</b>: Nothing.
|
||||||
@@ -959,7 +960,7 @@ template<class T, class ...Options>
|
|||||||
template<class T, class O1 = none, class O2 = none
|
template<class T, class O1 = none, class O2 = none
|
||||||
, class O3 = none, class O4 = none
|
, class O3 = none, class O4 = none
|
||||||
, class O5 = none, class O6 = none
|
, class O5 = none, class O6 = none
|
||||||
, class O7 = none
|
, class O7 = none, class O8 = none
|
||||||
>
|
>
|
||||||
#endif
|
#endif
|
||||||
struct make_unordered_set
|
struct make_unordered_set
|
||||||
@@ -967,19 +968,19 @@ struct make_unordered_set
|
|||||||
/// @cond
|
/// @cond
|
||||||
typedef unordered_set_impl
|
typedef unordered_set_impl
|
||||||
< typename make_hashtable_opt
|
< typename make_hashtable_opt
|
||||||
<T, O1, O2, O3, O4, O5, O6, O7>::type
|
<T, true, O1, O2, O3, O4, O5, O6, O7, O8>::type
|
||||||
> implementation_defined;
|
> implementation_defined;
|
||||||
/// @endcond
|
/// @endcond
|
||||||
typedef implementation_defined type;
|
typedef implementation_defined type;
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED
|
#ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED
|
||||||
template<class T, class O1, class O2, class O3, class O4, class O5, class O6, class O7>
|
template<class T, class O1, class O2, class O3, class O4, class O5, class O6, class O7, class O8>
|
||||||
class unordered_set
|
class unordered_set
|
||||||
: public make_unordered_set<T, O1, O2, O3, O4, O5, O6, O7>::type
|
: public make_unordered_set<T, O1, O2, O3, O4, O5, O6, O7, O8>::type
|
||||||
{
|
{
|
||||||
typedef typename make_unordered_set
|
typedef typename make_unordered_set
|
||||||
<T, O1, O2, O3, O4, O5, O6, O7>::type Base;
|
<T, O1, O2, O3, O4, O5, O6, O7, O8>::type Base;
|
||||||
|
|
||||||
//Assert if passed value traits are compatible with the type
|
//Assert if passed value traits are compatible with the type
|
||||||
BOOST_STATIC_ASSERT((detail::is_same<typename Base::value_traits::value_type, T>::value));
|
BOOST_STATIC_ASSERT((detail::is_same<typename Base::value_traits::value_type, T>::value));
|
||||||
@@ -1032,7 +1033,8 @@ class unordered_set
|
|||||||
//!
|
//!
|
||||||
//! The container supports the following options:
|
//! The container supports the following options:
|
||||||
//! \c base_hook<>/member_hook<>/value_traits<>,
|
//! \c base_hook<>/member_hook<>/value_traits<>,
|
||||||
//! \c constant_time_size<>, \c size_type<>, \c hash<> and \c equal<> .
|
//! \c constant_time_size<>, \c size_type<>, \c hash<> and \c equal<>
|
||||||
|
//! \c bucket_traits<>, power_2_buckets<> and cache_begin<>.
|
||||||
//!
|
//!
|
||||||
//! unordered_multiset only provides forward iterators but it provides 4 iterator types:
|
//! unordered_multiset only provides forward iterators but it provides 4 iterator types:
|
||||||
//! iterator and const_iterator to navigate through the whole container and
|
//! iterator and const_iterator to navigate through the whole container and
|
||||||
@@ -1161,8 +1163,8 @@ class unordered_multiset_impl
|
|||||||
|
|
||||||
//! <b>Effects</b>: Returns an iterator pointing to the beginning of the unordered_multiset.
|
//! <b>Effects</b>: Returns an iterator pointing to the beginning of the unordered_multiset.
|
||||||
//!
|
//!
|
||||||
//! <b>Complexity</b>: Amortized constant time.
|
//! <b>Complexity</b>: Constant time if `cache_begin<>` is true. Amortized
|
||||||
//! Worst case (empty unordered_multiset): O(this->bucket_count())
|
//! constant time with worst case (empty unordered_set) O(this->bucket_count())
|
||||||
//!
|
//!
|
||||||
//! <b>Throws</b>: Nothing.
|
//! <b>Throws</b>: Nothing.
|
||||||
iterator begin()
|
iterator begin()
|
||||||
@@ -1171,8 +1173,8 @@ class unordered_multiset_impl
|
|||||||
//! <b>Effects</b>: Returns a const_iterator pointing to the beginning
|
//! <b>Effects</b>: Returns a const_iterator pointing to the beginning
|
||||||
//! of the unordered_multiset.
|
//! of the unordered_multiset.
|
||||||
//!
|
//!
|
||||||
//! <b>Complexity</b>: Amortized constant time.
|
//! <b>Complexity</b>: Constant time if `cache_begin<>` is true. Amortized
|
||||||
//! Worst case (empty unordered_multiset): O(this->bucket_count())
|
//! constant time with worst case (empty unordered_set) O(this->bucket_count())
|
||||||
//!
|
//!
|
||||||
//! <b>Throws</b>: Nothing.
|
//! <b>Throws</b>: Nothing.
|
||||||
const_iterator begin() const
|
const_iterator begin() const
|
||||||
@@ -1181,8 +1183,8 @@ class unordered_multiset_impl
|
|||||||
//! <b>Effects</b>: Returns a const_iterator pointing to the beginning
|
//! <b>Effects</b>: Returns a const_iterator pointing to the beginning
|
||||||
//! of the unordered_multiset.
|
//! of the unordered_multiset.
|
||||||
//!
|
//!
|
||||||
//! <b>Complexity</b>: Amortized constant time.
|
//! <b>Complexity</b>: Constant time if `cache_begin<>` is true. Amortized
|
||||||
//! Worst case (empty unordered_multiset): O(this->bucket_count())
|
//! constant time with worst case (empty unordered_set) O(this->bucket_count())
|
||||||
//!
|
//!
|
||||||
//! <b>Throws</b>: Nothing.
|
//! <b>Throws</b>: Nothing.
|
||||||
const_iterator cbegin() const
|
const_iterator cbegin() const
|
||||||
@@ -1230,8 +1232,8 @@ class unordered_multiset_impl
|
|||||||
|
|
||||||
//! <b>Effects</b>: Returns true is the container is empty.
|
//! <b>Effects</b>: Returns true is the container is empty.
|
||||||
//!
|
//!
|
||||||
//! <b>Complexity</b>: if constant-time size option is disabled, average constant time
|
//! <b>Complexity</b>: if constant-time size and cache_last options are disabled,
|
||||||
//! (worst case, with empty() == true): O(this->bucket_count()).
|
//! average constant time (worst case, with empty() == true: O(this->bucket_count()).
|
||||||
//! Otherwise constant.
|
//! Otherwise constant.
|
||||||
//!
|
//!
|
||||||
//! <b>Throws</b>: Nothing.
|
//! <b>Throws</b>: Nothing.
|
||||||
@@ -1891,7 +1893,7 @@ template<class T, class ...Options>
|
|||||||
template<class T, class O1 = none, class O2 = none
|
template<class T, class O1 = none, class O2 = none
|
||||||
, class O3 = none, class O4 = none
|
, class O3 = none, class O4 = none
|
||||||
, class O5 = none, class O6 = none
|
, class O5 = none, class O6 = none
|
||||||
, class O7 = none
|
, class O7 = none, class O8 = none
|
||||||
>
|
>
|
||||||
#endif
|
#endif
|
||||||
struct make_unordered_multiset
|
struct make_unordered_multiset
|
||||||
@@ -1899,19 +1901,19 @@ struct make_unordered_multiset
|
|||||||
/// @cond
|
/// @cond
|
||||||
typedef unordered_multiset_impl
|
typedef unordered_multiset_impl
|
||||||
< typename make_hashtable_opt
|
< typename make_hashtable_opt
|
||||||
<T, O1, O2, O3, O4, O5, O6, O7>::type
|
<T, false, O1, O2, O3, O4, O5, O6, O7, O8>::type
|
||||||
> implementation_defined;
|
> implementation_defined;
|
||||||
/// @endcond
|
/// @endcond
|
||||||
typedef implementation_defined type;
|
typedef implementation_defined type;
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED
|
#ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED
|
||||||
template<class T, class O1, class O2, class O3, class O4, class O5, class O6, class O7>
|
template<class T, class O1, class O2, class O3, class O4, class O5, class O6, class O7, class O8>
|
||||||
class unordered_multiset
|
class unordered_multiset
|
||||||
: public make_unordered_multiset<T, O1, O2, O3, O4, O5, O6, O7>::type
|
: public make_unordered_multiset<T, O1, O2, O3, O4, O5, O6, O7, O8>::type
|
||||||
{
|
{
|
||||||
typedef typename make_unordered_multiset
|
typedef typename make_unordered_multiset
|
||||||
<T, O1, O2, O3, O4, O5, O6, O7>::type Base;
|
<T, O1, O2, O3, O4, O5, O6, O7, O8>::type Base;
|
||||||
//Assert if passed value traits are compatible with the type
|
//Assert if passed value traits are compatible with the type
|
||||||
BOOST_STATIC_ASSERT((detail::is_same<typename Base::value_traits::value_type, T>::value));
|
BOOST_STATIC_ASSERT((detail::is_same<typename Base::value_traits::value_type, T>::value));
|
||||||
|
|
||||||
|
@@ -17,6 +17,7 @@
|
|||||||
#include <boost/intrusive/detail/config_begin.hpp>
|
#include <boost/intrusive/detail/config_begin.hpp>
|
||||||
#include <boost/intrusive/intrusive_fwd.hpp>
|
#include <boost/intrusive/intrusive_fwd.hpp>
|
||||||
#include <boost/intrusive/detail/utilities.hpp>
|
#include <boost/intrusive/detail/utilities.hpp>
|
||||||
|
#include <boost/intrusive/detail/pointer_to_other.hpp>
|
||||||
#include <boost/intrusive/slist_hook.hpp>
|
#include <boost/intrusive/slist_hook.hpp>
|
||||||
#include <boost/intrusive/options.hpp>
|
#include <boost/intrusive/options.hpp>
|
||||||
#include <boost/intrusive/detail/generic_hook.hpp>
|
#include <boost/intrusive/detail/generic_hook.hpp>
|
||||||
@@ -26,35 +27,69 @@ namespace intrusive {
|
|||||||
|
|
||||||
/// @cond
|
/// @cond
|
||||||
|
|
||||||
template<class VoidPointer>
|
template<class VoidPointer, bool StoreHash, bool OptimizeMultiKey>
|
||||||
struct slist_node_plus_hash
|
struct unordered_node
|
||||||
|
: public slist_node<VoidPointer>
|
||||||
{
|
{
|
||||||
typedef typename boost::pointer_to_other
|
typedef typename boost::pointer_to_other
|
||||||
<VoidPointer, slist_node_plus_hash>::type node_ptr;
|
< VoidPointer
|
||||||
node_ptr next_;
|
, unordered_node<VoidPointer, StoreHash, OptimizeMultiKey>
|
||||||
|
>::type node_ptr;
|
||||||
|
// node_ptr next_;
|
||||||
|
node_ptr prev_in_group_;
|
||||||
std::size_t hash_;
|
std::size_t hash_;
|
||||||
};
|
};
|
||||||
|
|
||||||
// slist_node_traits can be used with circular_slist_algorithms and supplies
|
|
||||||
// a slist_node holding the pointers needed for a singly-linked list
|
|
||||||
// it is used by slist_base_hook and slist_member_hook
|
|
||||||
template<class VoidPointer>
|
template<class VoidPointer>
|
||||||
struct slist_node_traits_plus_hash
|
struct unordered_node<VoidPointer, false, true>
|
||||||
|
: public slist_node<VoidPointer>
|
||||||
{
|
{
|
||||||
typedef slist_node_plus_hash<VoidPointer> node;
|
typedef typename boost::pointer_to_other
|
||||||
|
< VoidPointer
|
||||||
|
, unordered_node<VoidPointer, false, true>
|
||||||
|
>::type node_ptr;
|
||||||
|
// node_ptr next_;
|
||||||
|
node_ptr prev_in_group_;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<class VoidPointer>
|
||||||
|
struct unordered_node<VoidPointer, true, false>
|
||||||
|
: public slist_node<VoidPointer>
|
||||||
|
{
|
||||||
|
typedef typename boost::pointer_to_other
|
||||||
|
< VoidPointer
|
||||||
|
, unordered_node<VoidPointer, true, false>
|
||||||
|
>::type node_ptr;
|
||||||
|
// node_ptr next_;
|
||||||
|
std::size_t hash_;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<class VoidPointer, bool StoreHash, bool OptimizeMultiKey>
|
||||||
|
struct unordered_node_traits
|
||||||
|
: public slist_node_traits<VoidPointer>
|
||||||
|
{
|
||||||
|
typedef slist_node_traits<VoidPointer> reduced_slist_node_traits;
|
||||||
|
typedef unordered_node<VoidPointer, StoreHash, OptimizeMultiKey> node;
|
||||||
typedef typename boost::pointer_to_other
|
typedef typename boost::pointer_to_other
|
||||||
<VoidPointer, node>::type node_ptr;
|
<VoidPointer, node>::type node_ptr;
|
||||||
typedef typename boost::pointer_to_other
|
typedef typename boost::pointer_to_other
|
||||||
<VoidPointer, const node>::type const_node_ptr;
|
<VoidPointer, const node>::type const_node_ptr;
|
||||||
|
|
||||||
static const bool store_hash = true;
|
static const bool store_hash = StoreHash;
|
||||||
|
static const bool optimize_multikey = OptimizeMultiKey;
|
||||||
|
|
||||||
static node_ptr get_next(const_node_ptr n)
|
static node_ptr get_next(const_node_ptr n)
|
||||||
{ return n->next_; }
|
{ return node_ptr(&static_cast<node &>(*n->next_)); }
|
||||||
|
|
||||||
static void set_next(node_ptr n, node_ptr next)
|
static void set_next(node_ptr n, node_ptr next)
|
||||||
{ n->next_ = next; }
|
{ n->next_ = next; }
|
||||||
|
|
||||||
|
static node_ptr get_prev_in_group(const_node_ptr n)
|
||||||
|
{ return n->prev_in_group_; }
|
||||||
|
|
||||||
|
static void set_prev_in_group(node_ptr n, node_ptr prev)
|
||||||
|
{ n->prev_in_group_ = prev; }
|
||||||
|
|
||||||
static std::size_t get_hash(const_node_ptr n)
|
static std::size_t get_hash(const_node_ptr n)
|
||||||
{ return n->hash_; }
|
{ return n->hash_; }
|
||||||
|
|
||||||
@@ -62,15 +97,68 @@ struct slist_node_traits_plus_hash
|
|||||||
{ n->hash_ = h; }
|
{ n->hash_ = h; }
|
||||||
};
|
};
|
||||||
|
|
||||||
template<class VoidPointer, bool StoreHash>
|
template<class VoidPointer, class Node>
|
||||||
|
struct unordered_group_node_traits
|
||||||
|
{
|
||||||
|
typedef Node node;
|
||||||
|
typedef typename boost::pointer_to_other
|
||||||
|
<VoidPointer, node>::type node_ptr;
|
||||||
|
typedef typename boost::pointer_to_other
|
||||||
|
<VoidPointer, const node>::type const_node_ptr;
|
||||||
|
|
||||||
|
static node_ptr get_next(const_node_ptr n)
|
||||||
|
{ return n->prev_in_group_; }
|
||||||
|
|
||||||
|
static void set_next(node_ptr n, node_ptr next)
|
||||||
|
{ n->prev_in_group_ = next; }
|
||||||
|
};
|
||||||
|
|
||||||
|
template<class NodeTraits>
|
||||||
|
struct unordered_algorithms
|
||||||
|
: public circular_slist_algorithms<NodeTraits>
|
||||||
|
{
|
||||||
|
typedef circular_slist_algorithms<NodeTraits> base_type;
|
||||||
|
typedef unordered_group_node_traits
|
||||||
|
< typename boost::pointer_to_other
|
||||||
|
< typename NodeTraits::node_ptr
|
||||||
|
, void
|
||||||
|
>::type
|
||||||
|
, typename NodeTraits::node
|
||||||
|
> group_traits;
|
||||||
|
typedef circular_slist_algorithms<group_traits> group_algorithms;
|
||||||
|
|
||||||
|
static void init(typename base_type::node_ptr n)
|
||||||
|
{
|
||||||
|
base_type::init(n);
|
||||||
|
group_algorithms::init(n);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void init_header(typename base_type::node_ptr n)
|
||||||
|
{
|
||||||
|
base_type::init_header(n);
|
||||||
|
group_algorithms::init_header(n);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void unlink(typename base_type::node_ptr n)
|
||||||
|
{
|
||||||
|
base_type::unlink(n);
|
||||||
|
group_algorithms::unlink(n);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<class VoidPointer, bool StoreHash, bool OptimizeMultiKey>
|
||||||
struct get_uset_node_algo
|
struct get_uset_node_algo
|
||||||
{
|
{
|
||||||
typedef typename detail::if_c
|
typedef typename detail::if_c
|
||||||
< StoreHash
|
< (StoreHash || OptimizeMultiKey)
|
||||||
, slist_node_traits_plus_hash<VoidPointer>
|
, unordered_node_traits<VoidPointer, StoreHash, OptimizeMultiKey>
|
||||||
, slist_node_traits<VoidPointer>
|
, slist_node_traits<VoidPointer>
|
||||||
>::type node_traits_type;
|
>::type node_traits_type;
|
||||||
typedef circular_slist_algorithms<node_traits_type> type;
|
typedef typename detail::if_c
|
||||||
|
< OptimizeMultiKey
|
||||||
|
, unordered_algorithms<node_traits_type>
|
||||||
|
, circular_slist_algorithms<node_traits_type>
|
||||||
|
>::type type;
|
||||||
};
|
};
|
||||||
/// @endcond
|
/// @endcond
|
||||||
|
|
||||||
@@ -90,6 +178,7 @@ struct make_unordered_set_base_hook
|
|||||||
typedef detail::generic_hook
|
typedef detail::generic_hook
|
||||||
< get_uset_node_algo<typename packed_options::void_pointer
|
< get_uset_node_algo<typename packed_options::void_pointer
|
||||||
, packed_options::store_hash
|
, packed_options::store_hash
|
||||||
|
, packed_options::optimize_multikey
|
||||||
>
|
>
|
||||||
, typename packed_options::tag
|
, typename packed_options::tag
|
||||||
, packed_options::link_mode
|
, packed_options::link_mode
|
||||||
@@ -104,7 +193,7 @@ struct make_unordered_set_base_hook
|
|||||||
//! the unordered_set/unordered_multi_set and provides an appropriate value_traits class for unordered_set/unordered_multi_set.
|
//! the unordered_set/unordered_multi_set and provides an appropriate value_traits class for unordered_set/unordered_multi_set.
|
||||||
//!
|
//!
|
||||||
//! The hook admits the following options: \c tag<>, \c void_pointer<>,
|
//! The hook admits the following options: \c tag<>, \c void_pointer<>,
|
||||||
//! \c link_mode<> and \c store_hash<>.
|
//! \c link_mode<>, \c store_hash<> and \c optimize_multikey<>.
|
||||||
//!
|
//!
|
||||||
//! \c tag<> defines a tag to identify the node.
|
//! \c tag<> defines a tag to identify the node.
|
||||||
//! The same tag value can be used in different classes, but if a class is
|
//! The same tag value can be used in different classes, but if a class is
|
||||||
@@ -119,6 +208,10 @@ struct make_unordered_set_base_hook
|
|||||||
//!
|
//!
|
||||||
//! \c store_hash<> will tell the hook to store the hash of the value
|
//! \c store_hash<> will tell the hook to store the hash of the value
|
||||||
//! to speed up rehashings.
|
//! to speed up rehashings.
|
||||||
|
//!
|
||||||
|
//! \c optimize_multikey<> will tell the hook to store a link to form a group
|
||||||
|
//! with other value with the same value to speed up searches and insertions
|
||||||
|
//! in unordered_multisets with a great number of with equivalent keys.
|
||||||
#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
|
#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
|
||||||
template<class ...Options>
|
template<class ...Options>
|
||||||
#else
|
#else
|
||||||
@@ -211,6 +304,7 @@ struct make_unordered_set_member_hook
|
|||||||
typedef detail::generic_hook
|
typedef detail::generic_hook
|
||||||
< get_uset_node_algo< typename packed_options::void_pointer
|
< get_uset_node_algo< typename packed_options::void_pointer
|
||||||
, packed_options::store_hash
|
, packed_options::store_hash
|
||||||
|
, packed_options::optimize_multikey
|
||||||
>
|
>
|
||||||
, member_tag
|
, member_tag
|
||||||
, packed_options::link_mode
|
, packed_options::link_mode
|
||||||
|
@@ -4,6 +4,6 @@
|
|||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
Automatic redirection failed, please go to
|
Automatic redirection failed, please go to
|
||||||
<a href="../../doc/html/intrusive.html">../../doc/html/intrusive.html</a>
|
<a href="../../doc/html/intrusive">../../doc/html/intrusive</a>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
@@ -23,7 +23,7 @@ using namespace boost::posix_time;
|
|||||||
//[perf_list_value_type
|
//[perf_list_value_type
|
||||||
//Iteration and element count defines
|
//Iteration and element count defines
|
||||||
const int NumIter = 100;
|
const int NumIter = 100;
|
||||||
const int NumElements = 100000;
|
const int NumElements = 50000;
|
||||||
|
|
||||||
using namespace boost::intrusive;
|
using namespace boost::intrusive;
|
||||||
|
|
||||||
|
@@ -154,10 +154,7 @@
|
|||||||
RelativePath="..\..\..\..\..\boost\intrusive\options.hpp">
|
RelativePath="..\..\..\..\..\boost\intrusive\options.hpp">
|
||||||
</File>
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\..\..\..\boost\intrusive\pointer_plus_2_bits.hpp">
|
RelativePath="..\..\..\..\..\boost\intrusive\pointer_plus_bits.hpp">
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath="..\..\..\..\..\boost\intrusive\pointer_plus_bit.hpp">
|
|
||||||
</File>
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\..\..\..\boost\intrusive\rbtree.hpp">
|
RelativePath="..\..\..\..\..\boost\intrusive\rbtree.hpp">
|
||||||
@@ -240,9 +237,6 @@
|
|||||||
<File
|
<File
|
||||||
RelativePath="..\..\..\..\..\boost\intrusive\detail\mpl.hpp">
|
RelativePath="..\..\..\..\..\boost\intrusive\detail\mpl.hpp">
|
||||||
</File>
|
</File>
|
||||||
<File
|
|
||||||
RelativePath="..\..\..\..\..\boost\intrusive\detail\no_exceptions_support.hpp">
|
|
||||||
</File>
|
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\..\..\..\boost\intrusive\detail\parent_from_member.hpp">
|
RelativePath="..\..\..\..\..\boost\intrusive\detail\parent_from_member.hpp">
|
||||||
</File>
|
</File>
|
||||||
|
11
proj/vc7ide/to-do.txt
Normal file
11
proj/vc7ide/to-do.txt
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
Add resize() to list
|
||||||
|
Implement incremental hashing
|
||||||
|
Add invariants to slist and test them after every operation
|
||||||
|
Create a generic hook that will work with all containers
|
||||||
|
Take advantage of store_hash in lookups: Instead of comparing objects, just
|
||||||
|
compare hashes. This will improve equality for expensive objects.
|
||||||
|
|
||||||
|
Improve the use of cache_begin to unordered containers:
|
||||||
|
-> Speed up rehash
|
||||||
|
|
||||||
|
|
@@ -108,7 +108,6 @@ class test_main_template<VoidPointer, false>
|
|||||||
|
|
||||||
int main( int, char* [] )
|
int main( int, char* [] )
|
||||||
{
|
{
|
||||||
|
|
||||||
test_main_template<void*, false>()();
|
test_main_template<void*, false>()();
|
||||||
test_main_template<boost::intrusive::smart_ptr<void>, false>()();
|
test_main_template<boost::intrusive::smart_ptr<void>, false>()();
|
||||||
test_main_template<void*, true>()();
|
test_main_template<void*, true>()();
|
||||||
|
@@ -52,8 +52,37 @@ struct test_generic_assoc
|
|||||||
static void test_rebalance(std::vector<value_type>& values);
|
static void test_rebalance(std::vector<value_type>& values);
|
||||||
static void test_rebalance(std::vector<value_type>& values, boost::intrusive::detail::true_type);
|
static void test_rebalance(std::vector<value_type>& values, boost::intrusive::detail::true_type);
|
||||||
static void test_rebalance(std::vector<value_type>& values, boost::intrusive::detail::false_type);
|
static void test_rebalance(std::vector<value_type>& values, boost::intrusive::detail::false_type);
|
||||||
|
static void test_container_from_iterator(std::vector<value_type>& values);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<class ValueTraits, template <class = ::boost::intrusive::none, class = ::boost::intrusive::none, class = ::boost::intrusive::none, class = ::boost::intrusive::none> class ContainerDefiner>
|
||||||
|
void test_generic_assoc<ValueTraits, ContainerDefiner>::
|
||||||
|
test_container_from_iterator(std::vector<value_type>& values)
|
||||||
|
{
|
||||||
|
typedef typename ContainerDefiner
|
||||||
|
< value_type
|
||||||
|
, value_traits<ValueTraits>
|
||||||
|
, constant_time_size<value_type::constant_time_size>
|
||||||
|
>::type assoc_type;
|
||||||
|
|
||||||
|
assoc_type testset(values.begin(), values.end());
|
||||||
|
typedef typename assoc_type::iterator it_type;
|
||||||
|
typedef typename assoc_type::const_iterator cit_type;
|
||||||
|
typedef typename assoc_type::size_type sz_type;
|
||||||
|
sz_type sz = testset.size();
|
||||||
|
for(it_type b(testset.begin()), e(testset.end()); b != e; ++b)
|
||||||
|
{
|
||||||
|
assoc_type &s = assoc_type::container_from_iterator(b);
|
||||||
|
const assoc_type &cs = assoc_type::container_from_iterator(cit_type(b));
|
||||||
|
BOOST_TEST(&s == &cs);
|
||||||
|
BOOST_TEST(&s == &testset);
|
||||||
|
s.erase(b);
|
||||||
|
BOOST_TEST(testset.size() == (sz-1));
|
||||||
|
s.insert(*b);
|
||||||
|
BOOST_TEST(testset.size() == sz);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
template<class ValueTraits, template <class = ::boost::intrusive::none, class = ::boost::intrusive::none, class = ::boost::intrusive::none, class = ::boost::intrusive::none> class ContainerDefiner>
|
template<class ValueTraits, template <class = ::boost::intrusive::none, class = ::boost::intrusive::none, class = ::boost::intrusive::none, class = ::boost::intrusive::none> class ContainerDefiner>
|
||||||
void test_generic_assoc<ValueTraits, ContainerDefiner>::test_insert_erase_burst()
|
void test_generic_assoc<ValueTraits, ContainerDefiner>::test_insert_erase_burst()
|
||||||
{
|
{
|
||||||
@@ -103,12 +132,14 @@ void test_generic_assoc<ValueTraits, ContainerDefiner>::test_insert_erase_burst(
|
|||||||
template<class ValueTraits, template <class = ::boost::intrusive::none, class = ::boost::intrusive::none, class = ::boost::intrusive::none, class = ::boost::intrusive::none> class ContainerDefiner>
|
template<class ValueTraits, template <class = ::boost::intrusive::none, class = ::boost::intrusive::none, class = ::boost::intrusive::none, class = ::boost::intrusive::none> class ContainerDefiner>
|
||||||
void test_generic_assoc<ValueTraits, ContainerDefiner>::test_all(std::vector<typename ValueTraits::value_type>& values)
|
void test_generic_assoc<ValueTraits, ContainerDefiner>::test_all(std::vector<typename ValueTraits::value_type>& values)
|
||||||
{
|
{
|
||||||
|
typedef typename ValueTraits::value_type value_type;
|
||||||
test_clone(values);
|
test_clone(values);
|
||||||
test_container_from_end(values);
|
test_container_from_end(values);
|
||||||
test_splay_up(values);
|
test_splay_up(values);
|
||||||
test_splay_down(values);
|
test_splay_down(values);
|
||||||
test_rebalance(values);
|
test_rebalance(values);
|
||||||
test_insert_erase_burst();
|
test_insert_erase_burst();
|
||||||
|
test_container_from_iterator(values);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class ValueTraits, template <class = ::boost::intrusive::none, class = ::boost::intrusive::none, class = ::boost::intrusive::none, class = ::boost::intrusive::none> class ContainerDefiner>
|
template<class ValueTraits, template <class = ::boost::intrusive::none, class = ::boost::intrusive::none, class = ::boost::intrusive::none, class = ::boost::intrusive::none> class ContainerDefiner>
|
||||||
|
@@ -35,6 +35,7 @@ struct test_generic_set
|
|||||||
static void test_impl();
|
static void test_impl();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
template<class ValueTraits, template <class = ::boost::intrusive::none, class = ::boost::intrusive::none, class = ::boost::intrusive::none, class = ::boost::intrusive::none> class ContainerDefiner>
|
template<class ValueTraits, template <class = ::boost::intrusive::none, class = ::boost::intrusive::none, class = ::boost::intrusive::none, class = ::boost::intrusive::none> class ContainerDefiner>
|
||||||
void test_generic_set<ValueTraits, ContainerDefiner>::test_all()
|
void test_generic_set<ValueTraits, ContainerDefiner>::test_all()
|
||||||
{
|
{
|
||||||
|
@@ -126,20 +126,30 @@ template<class VoidPointer>
|
|||||||
struct uset_auto_base_hook_type
|
struct uset_auto_base_hook_type
|
||||||
{
|
{
|
||||||
typedef unordered_set_base_hook
|
typedef unordered_set_base_hook
|
||||||
< link_mode<auto_unlink>, void_pointer<VoidPointer>
|
< link_mode<auto_unlink>
|
||||||
, tag<my_tag>, store_hash<true> > type;
|
, void_pointer<VoidPointer>
|
||||||
|
, tag<my_tag>
|
||||||
|
, store_hash<true>
|
||||||
|
> type;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<class VoidPointer>
|
template<class VoidPointer>
|
||||||
struct uset_member_hook_type
|
struct uset_member_hook_type
|
||||||
{ typedef unordered_set_member_hook<void_pointer<VoidPointer> > type; };
|
{
|
||||||
|
typedef unordered_set_member_hook
|
||||||
|
< void_pointer<VoidPointer>
|
||||||
|
, optimize_multikey<true>
|
||||||
|
> type;
|
||||||
|
};
|
||||||
|
|
||||||
template<class VoidPointer>
|
template<class VoidPointer>
|
||||||
struct uset_auto_member_hook_type
|
struct uset_auto_member_hook_type
|
||||||
{
|
{
|
||||||
typedef unordered_set_member_hook
|
typedef unordered_set_member_hook
|
||||||
< link_mode<auto_unlink>, void_pointer<VoidPointer>
|
< link_mode<auto_unlink>, void_pointer<VoidPointer>
|
||||||
, store_hash<true> > type;
|
, store_hash<true>
|
||||||
|
, optimize_multikey<true>
|
||||||
|
> type;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<class VoidPointer, bool ConstantTimeSize>
|
template<class VoidPointer, bool ConstantTimeSize>
|
||||||
@@ -318,6 +328,49 @@ struct testvalue
|
|||||||
slist_auto_node_.swap_nodes(other.slist_auto_node_);
|
slist_auto_node_.swap_nodes(other.slist_auto_node_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool is_linked() const
|
||||||
|
{
|
||||||
|
//Set
|
||||||
|
return set_base_hook_t::is_linked() ||
|
||||||
|
set_auto_base_hook_t::is_linked() ||
|
||||||
|
set_node_.is_linked() ||
|
||||||
|
set_auto_node_.is_linked() ||
|
||||||
|
|
||||||
|
//SplaySet
|
||||||
|
splay_set_base_hook_t::is_linked() ||
|
||||||
|
splay_set_auto_base_hook_t::is_linked() ||
|
||||||
|
splay_set_node_.is_linked() ||
|
||||||
|
splay_set_auto_node_.is_linked() ||
|
||||||
|
|
||||||
|
//ScapeoatSet
|
||||||
|
bs_set_base_hook_t::is_linked() ||
|
||||||
|
sg_set_node_.is_linked() ||
|
||||||
|
|
||||||
|
//AvlSet
|
||||||
|
avl_set_base_hook_t::is_linked() ||
|
||||||
|
avl_set_auto_base_hook_t::is_linked() ||
|
||||||
|
avl_set_node_.is_linked() ||
|
||||||
|
avl_set_auto_node_.is_linked() ||
|
||||||
|
|
||||||
|
//Unordered set
|
||||||
|
unordered_set_base_hook_t::is_linked() ||
|
||||||
|
unordered_set_auto_base_hook_t::is_linked() ||
|
||||||
|
unordered_set_node_.is_linked() ||
|
||||||
|
unordered_set_auto_node_.is_linked() ||
|
||||||
|
|
||||||
|
//List
|
||||||
|
list_base_hook_t::is_linked() ||
|
||||||
|
list_auto_base_hook_t::is_linked() ||
|
||||||
|
list_node_.is_linked() ||
|
||||||
|
list_auto_node_.is_linked() ||
|
||||||
|
|
||||||
|
//Slist
|
||||||
|
slist_base_hook_t::is_linked() ||
|
||||||
|
slist_auto_base_hook_t::is_linked() ||
|
||||||
|
slist_node_.is_linked() ||
|
||||||
|
slist_auto_node_.is_linked();
|
||||||
|
}
|
||||||
|
|
||||||
~testvalue()
|
~testvalue()
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
@@ -12,8 +12,7 @@
|
|||||||
#define BOOST_INTRUSIVE_SMART_PTR_HPP
|
#define BOOST_INTRUSIVE_SMART_PTR_HPP
|
||||||
|
|
||||||
#include <boost/iterator.hpp>
|
#include <boost/iterator.hpp>
|
||||||
#include <boost/intrusive/pointer_plus_bit.hpp>
|
#include <boost/intrusive/pointer_plus_bits.hpp>
|
||||||
#include <boost/intrusive/pointer_plus_2_bits.hpp>
|
|
||||||
|
|
||||||
#if (defined _MSC_VER) && (_MSC_VER >= 1200)
|
#if (defined _MSC_VER) && (_MSC_VER >= 1200)
|
||||||
# pragma once
|
# pragma once
|
||||||
@@ -109,7 +108,7 @@ class smart_ptr
|
|||||||
public: //Public Functions
|
public: //Public Functions
|
||||||
|
|
||||||
//!Constructor from raw pointer (allows "0" pointer conversion). Never throws.
|
//!Constructor from raw pointer (allows "0" pointer conversion). Never throws.
|
||||||
smart_ptr(pointer ptr = 0)
|
explicit smart_ptr(pointer ptr = 0)
|
||||||
: m_ptr(ptr)
|
: m_ptr(ptr)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
@@ -351,67 +350,34 @@ namespace boost{
|
|||||||
//for intrusive containers, saving space
|
//for intrusive containers, saving space
|
||||||
namespace intrusive {
|
namespace intrusive {
|
||||||
|
|
||||||
template<std::size_t N>
|
template<std::size_t Alignment>
|
||||||
struct has_pointer_plus_bit<smart_ptr<void>, N>
|
struct max_pointer_plus_bits<smart_ptr<void>, Alignment>
|
||||||
{
|
{
|
||||||
static const bool value = has_pointer_plus_bit<void*, N>::value;
|
static const std::size_t value = max_pointer_plus_bits<void*, Alignment>::value;
|
||||||
};
|
};
|
||||||
|
|
||||||
//Specialization
|
template<class T, std::size_t NumBits>
|
||||||
template<class T>
|
struct pointer_plus_bits<smart_ptr<T>, NumBits>
|
||||||
struct pointer_plus_bit<smart_ptr<T> >
|
|
||||||
{
|
{
|
||||||
typedef smart_ptr<T> pointer;
|
typedef smart_ptr<T> pointer;
|
||||||
|
|
||||||
static pointer get_pointer(const pointer &n)
|
static pointer get_pointer(const pointer &n)
|
||||||
{ return pointer_plus_bit<T*>::get_pointer(n.get()); }
|
{ return pointer_plus_bits<T*, NumBits>::get_pointer(n.get()); }
|
||||||
|
|
||||||
static void set_pointer(pointer &n, pointer p)
|
static void set_pointer(pointer &n, pointer p)
|
||||||
{
|
{
|
||||||
T *raw_n = n.get();
|
T *raw_n = n.get();
|
||||||
pointer_plus_bit<T*>::set_pointer(raw_n, p.get());
|
pointer_plus_bits<T*, NumBits>::set_pointer(raw_n, p.get());
|
||||||
n = raw_n;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool get_bit(const pointer &n)
|
|
||||||
{ return pointer_plus_bit<T*>::get_bit(n.get()); }
|
|
||||||
|
|
||||||
static void set_bit(pointer &n, bool c)
|
|
||||||
{
|
|
||||||
T *raw_n = n.get();
|
|
||||||
pointer_plus_bit<T*>::set_bit(raw_n, c);
|
|
||||||
n = raw_n;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<std::size_t N>
|
|
||||||
struct has_pointer_plus_2_bits<smart_ptr<void>, N>
|
|
||||||
{
|
|
||||||
static const bool value = has_pointer_plus_2_bits<void*, N>::value;
|
|
||||||
};
|
|
||||||
|
|
||||||
template<class T>
|
|
||||||
struct pointer_plus_2_bits<smart_ptr<T> >
|
|
||||||
{
|
|
||||||
typedef smart_ptr<T> pointer;
|
|
||||||
|
|
||||||
static pointer get_pointer(const pointer &n)
|
|
||||||
{ return pointer_plus_2_bits<T*>::get_pointer(n.get()); }
|
|
||||||
|
|
||||||
static void set_pointer(pointer &n, pointer p)
|
|
||||||
{
|
|
||||||
T *raw_n = n.get();
|
|
||||||
pointer_plus_2_bits<T*>::set_pointer(raw_n, p.get());
|
|
||||||
n = raw_n;
|
n = raw_n;
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::size_t get_bits(const pointer &n)
|
static std::size_t get_bits(const pointer &n)
|
||||||
{ return pointer_plus_2_bits<T*>::get_bits(n.get()); }
|
{ return pointer_plus_bits<T*, NumBits>::get_bits(n.get()); }
|
||||||
|
|
||||||
static void set_bits(pointer &n, std::size_t c)
|
static void set_bits(pointer &n, std::size_t c)
|
||||||
{
|
{
|
||||||
T *raw_n = n.get();
|
T *raw_n = n.get();
|
||||||
pointer_plus_2_bits<T*>::set_bits(raw_n, c);
|
pointer_plus_bits<T*, NumBits>::set_bits(raw_n, c);
|
||||||
n = raw_n;
|
n = raw_n;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@@ -18,6 +18,7 @@
|
|||||||
#include "smart_ptr.hpp"
|
#include "smart_ptr.hpp"
|
||||||
#include "common_functors.hpp"
|
#include "common_functors.hpp"
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <algorithm> //std::sort std::find
|
||||||
#include <set>
|
#include <set>
|
||||||
#include <boost/detail/lightweight_test.hpp>
|
#include <boost/detail/lightweight_test.hpp>
|
||||||
#include "test_macros.hpp"
|
#include "test_macros.hpp"
|
||||||
@@ -27,7 +28,7 @@ using namespace boost::intrusive;
|
|||||||
|
|
||||||
static const std::size_t BucketSize = 11;
|
static const std::size_t BucketSize = 11;
|
||||||
|
|
||||||
template<class ValueTraits>
|
template<class ValueTraits, bool CacheBegin>
|
||||||
struct test_unordered_multiset
|
struct test_unordered_multiset
|
||||||
{
|
{
|
||||||
typedef typename ValueTraits::value_type value_type;
|
typedef typename ValueTraits::value_type value_type;
|
||||||
@@ -41,14 +42,15 @@ struct test_unordered_multiset
|
|||||||
static void test_clone(std::vector<value_type>& values);
|
static void test_clone(std::vector<value_type>& values);
|
||||||
};
|
};
|
||||||
|
|
||||||
template<class ValueTraits>
|
template<class ValueTraits, bool CacheBegin>
|
||||||
void test_unordered_multiset<ValueTraits>::test_all (std::vector<typename ValueTraits::value_type>& values)
|
void test_unordered_multiset<ValueTraits, CacheBegin>::test_all (std::vector<typename ValueTraits::value_type>& values)
|
||||||
{
|
{
|
||||||
typedef typename ValueTraits::value_type value_type;
|
typedef typename ValueTraits::value_type value_type;
|
||||||
typedef unordered_multiset
|
typedef unordered_multiset
|
||||||
<value_type
|
< value_type
|
||||||
, value_traits<ValueTraits>
|
, value_traits<ValueTraits>
|
||||||
, constant_time_size<value_type::constant_time_size>
|
, constant_time_size<value_type::constant_time_size>
|
||||||
|
, cache_begin<CacheBegin>
|
||||||
> unordered_multiset_type;
|
> unordered_multiset_type;
|
||||||
{
|
{
|
||||||
typedef typename unordered_multiset_type::bucket_traits bucket_traits;
|
typedef typename unordered_multiset_type::bucket_traits bucket_traits;
|
||||||
@@ -76,14 +78,15 @@ void test_unordered_multiset<ValueTraits>::test_all (std::vector<typename ValueT
|
|||||||
}
|
}
|
||||||
|
|
||||||
//test case due to an error in tree implementation:
|
//test case due to an error in tree implementation:
|
||||||
template<class ValueTraits>
|
template<class ValueTraits, bool CacheBegin>
|
||||||
void test_unordered_multiset<ValueTraits>::test_impl()
|
void test_unordered_multiset<ValueTraits, CacheBegin>::test_impl()
|
||||||
{
|
{
|
||||||
typedef typename ValueTraits::value_type value_type;
|
typedef typename ValueTraits::value_type value_type;
|
||||||
typedef unordered_multiset
|
typedef unordered_multiset
|
||||||
<value_type
|
<value_type
|
||||||
, value_traits<ValueTraits>
|
, value_traits<ValueTraits>
|
||||||
, constant_time_size<value_type::constant_time_size>
|
, constant_time_size<value_type::constant_time_size>
|
||||||
|
, cache_begin<CacheBegin>
|
||||||
> unordered_multiset_type;
|
> unordered_multiset_type;
|
||||||
typedef typename unordered_multiset_type::bucket_traits bucket_traits;
|
typedef typename unordered_multiset_type::bucket_traits bucket_traits;
|
||||||
|
|
||||||
@@ -106,14 +109,15 @@ void test_unordered_multiset<ValueTraits>::test_impl()
|
|||||||
}
|
}
|
||||||
|
|
||||||
//test: constructor, iterator, clear, reverse_iterator, front, back, size:
|
//test: constructor, iterator, clear, reverse_iterator, front, back, size:
|
||||||
template<class ValueTraits>
|
template<class ValueTraits, bool CacheBegin>
|
||||||
void test_unordered_multiset<ValueTraits>::test_sort(std::vector<typename ValueTraits::value_type>& values)
|
void test_unordered_multiset<ValueTraits, CacheBegin>::test_sort(std::vector<typename ValueTraits::value_type>& values)
|
||||||
{
|
{
|
||||||
typedef typename ValueTraits::value_type value_type;
|
typedef typename ValueTraits::value_type value_type;
|
||||||
typedef unordered_multiset
|
typedef unordered_multiset
|
||||||
<value_type
|
<value_type
|
||||||
, value_traits<ValueTraits>
|
, value_traits<ValueTraits>
|
||||||
, constant_time_size<value_type::constant_time_size>
|
, constant_time_size<value_type::constant_time_size>
|
||||||
|
, cache_begin<CacheBegin>
|
||||||
> unordered_multiset_type;
|
> unordered_multiset_type;
|
||||||
typedef typename unordered_multiset_type::bucket_traits bucket_traits;
|
typedef typename unordered_multiset_type::bucket_traits bucket_traits;
|
||||||
|
|
||||||
@@ -127,104 +131,187 @@ void test_unordered_multiset<ValueTraits>::test_sort(std::vector<typename ValueT
|
|||||||
}
|
}
|
||||||
|
|
||||||
//test: insert, const_iterator, const_reverse_iterator, erase, iterator_to:
|
//test: insert, const_iterator, const_reverse_iterator, erase, iterator_to:
|
||||||
template<class ValueTraits>
|
template<class ValueTraits, bool CacheBegin>
|
||||||
void test_unordered_multiset<ValueTraits>::test_insert(std::vector<typename ValueTraits::value_type>& values)
|
void test_unordered_multiset<ValueTraits, CacheBegin>::test_insert(std::vector<typename ValueTraits::value_type>& values)
|
||||||
{
|
{
|
||||||
typedef typename ValueTraits::value_type value_type;
|
typedef typename ValueTraits::value_type value_type;
|
||||||
typedef unordered_multiset
|
typedef unordered_multiset
|
||||||
<value_type
|
<value_type
|
||||||
, value_traits<ValueTraits>
|
, value_traits<ValueTraits>
|
||||||
, constant_time_size<value_type::constant_time_size>
|
, constant_time_size<value_type::constant_time_size>
|
||||||
|
, cache_begin<CacheBegin>
|
||||||
> unordered_multiset_type;
|
> unordered_multiset_type;
|
||||||
typedef typename unordered_multiset_type::bucket_traits bucket_traits;
|
typedef typename unordered_multiset_type::bucket_traits bucket_traits;
|
||||||
|
typedef typename unordered_multiset_type::iterator iterator;
|
||||||
|
{
|
||||||
|
typename unordered_multiset_type::bucket_type buckets [BucketSize];
|
||||||
|
unordered_multiset_type testset(bucket_traits(buckets, BucketSize));
|
||||||
|
|
||||||
typename unordered_multiset_type::bucket_type buckets [BucketSize];
|
testset.insert(&values[0] + 2, &values[0] + 5);
|
||||||
unordered_multiset_type testset(bucket_traits(buckets, BucketSize));
|
|
||||||
|
|
||||||
testset.insert(&values[0] + 2, &values[0] + 5);
|
const unordered_multiset_type& const_testset = testset;
|
||||||
|
{ int init_values [] = { 1, 4, 5 };
|
||||||
|
TEST_INTRUSIVE_SEQUENCE( init_values, const_testset.begin() ); }
|
||||||
|
|
||||||
const unordered_multiset_type& const_testset = testset;
|
typename unordered_multiset_type::iterator i = testset.begin();
|
||||||
{ int init_values [] = { 1, 4, 5 };
|
BOOST_TEST (i->value_ == 1);
|
||||||
TEST_INTRUSIVE_SEQUENCE( init_values, const_testset.begin() ); }
|
|
||||||
|
|
||||||
typename unordered_multiset_type::iterator i = testset.begin();
|
i = testset.insert (values[0]);
|
||||||
BOOST_TEST (i->value_ == 1);
|
BOOST_TEST (&*i == &values[0]);
|
||||||
|
|
||||||
|
i = testset.iterator_to (values[2]);
|
||||||
|
BOOST_TEST (&*i == &values[2]);
|
||||||
|
testset.erase(i);
|
||||||
|
|
||||||
i = testset.insert (values[0]);
|
{ int init_values [] = { 1, 3, 5 };
|
||||||
BOOST_TEST (&*i == &values[0]);
|
TEST_INTRUSIVE_SEQUENCE( init_values, const_testset.begin() ); }
|
||||||
|
testset.clear();
|
||||||
i = testset.iterator_to (values[2]);
|
testset.insert(&values[0], &values[0] + values.size());
|
||||||
BOOST_TEST (&*i == &values[2]);
|
|
||||||
testset.erase(i);
|
|
||||||
|
|
||||||
{ int init_values [] = { 1, 3, 5 };
|
{ int init_values [] = { 1, 2, 2, 3, 4, 5 };
|
||||||
TEST_INTRUSIVE_SEQUENCE( init_values, const_testset.begin() ); }
|
TEST_INTRUSIVE_SEQUENCE( init_values, const_testset.begin() ); }
|
||||||
testset.clear();
|
|
||||||
testset.insert(&values[0], &values[0] + values.size());
|
|
||||||
|
|
||||||
{ int init_values [] = { 1, 2, 2, 3, 4, 5 };
|
BOOST_TEST (testset.erase(1) == 1);
|
||||||
TEST_INTRUSIVE_SEQUENCE( init_values, const_testset.begin() ); }
|
BOOST_TEST (testset.erase(2) == 2);
|
||||||
|
BOOST_TEST (testset.erase(3) == 1);
|
||||||
|
BOOST_TEST (testset.erase(4) == 1);
|
||||||
|
BOOST_TEST (testset.erase(5) == 1);
|
||||||
|
BOOST_TEST (testset.empty() == true);
|
||||||
|
|
||||||
BOOST_TEST (testset.erase(1) == 1);
|
//Now with a single bucket
|
||||||
BOOST_TEST (testset.erase(2) == 2);
|
typename unordered_multiset_type::bucket_type single_bucket[1];
|
||||||
BOOST_TEST (testset.erase(3) == 1);
|
unordered_multiset_type testset2(bucket_traits(single_bucket, 1));
|
||||||
BOOST_TEST (testset.erase(4) == 1);
|
testset2.insert(&values[0], &values[0] + values.size());
|
||||||
BOOST_TEST (testset.erase(5) == 1);
|
BOOST_TEST (testset2.erase(5) == 1);
|
||||||
BOOST_TEST (testset.empty() == true);
|
BOOST_TEST (testset2.erase(2) == 2);
|
||||||
|
BOOST_TEST (testset2.erase(1) == 1);
|
||||||
|
BOOST_TEST (testset2.erase(4) == 1);
|
||||||
|
BOOST_TEST (testset2.erase(3) == 1);
|
||||||
|
BOOST_TEST (testset2.empty() == true);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
//Now erase just one per loop
|
||||||
|
const int random_init[] = { 3, 2, 4, 1, 5, 2, 2 };
|
||||||
|
const unsigned int random_size = sizeof(random_init)/sizeof(random_init[0]);
|
||||||
|
typename unordered_multiset_type::bucket_type single_bucket[1];
|
||||||
|
for(unsigned int i = 0, max = random_size; i != max; ++i){
|
||||||
|
std::vector<typename ValueTraits::value_type> data (random_size);
|
||||||
|
for (unsigned int j = 0; j < random_size; ++j)
|
||||||
|
data[j].value_ = random_init[j];
|
||||||
|
unordered_multiset_type testset_new(bucket_traits(single_bucket, 1));
|
||||||
|
testset_new.insert(&data[0], &data[max]);
|
||||||
|
testset_new.erase(testset_new.iterator_to(data[i]));
|
||||||
|
BOOST_TEST (testset_new.size() == (max -1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{
|
||||||
|
typename unordered_multiset_type::bucket_type buckets [BucketSize];
|
||||||
|
const unsigned int NumBucketSize = BucketSize;
|
||||||
|
const unsigned int LoadFactor = 3;
|
||||||
|
const unsigned int NumIterations = NumBucketSize*LoadFactor;
|
||||||
|
std::vector<value_type> random_init(NumIterations);//Preserve memory
|
||||||
|
std::vector<value_type> set_tester;
|
||||||
|
set_tester.reserve(NumIterations);
|
||||||
|
|
||||||
//Now with a single bucket
|
//Initialize values
|
||||||
typename unordered_multiset_type::bucket_type single_bucket[1];
|
for (unsigned int i = 0; i < NumIterations; ++i){
|
||||||
unordered_multiset_type testset2(bucket_traits(single_bucket, 1));
|
random_init[i].value_ = i*2;//(i/LoadFactor)*LoadFactor;
|
||||||
testset2.insert(&values[0], &values[0] + values.size());
|
}
|
||||||
BOOST_TEST (testset2.erase(5) == 1);
|
|
||||||
BOOST_TEST (testset2.erase(2) == 2);
|
for(unsigned int initial_pos = 0; initial_pos != (NumIterations+1); ++initial_pos){
|
||||||
BOOST_TEST (testset2.erase(1) == 1);
|
for(unsigned int final_pos = initial_pos; final_pos != (NumIterations+1); ++final_pos){
|
||||||
BOOST_TEST (testset2.erase(4) == 1);
|
|
||||||
BOOST_TEST (testset2.erase(3) == 1);
|
//Create intrusive container inserting values
|
||||||
BOOST_TEST (testset2.empty() == true);
|
unordered_multiset_type testset
|
||||||
|
( &random_init[0]
|
||||||
|
, &random_init[0] + random_init.size()
|
||||||
|
, bucket_traits(buckets, NumBucketSize));
|
||||||
|
|
||||||
|
BOOST_TEST (testset.size() == random_init.size());
|
||||||
|
|
||||||
|
//Obtain the iterator range to erase
|
||||||
|
iterator it_beg_pos = testset.begin();
|
||||||
|
for(unsigned int it_beg_pos_num = 0; it_beg_pos_num != initial_pos; ++it_beg_pos_num){
|
||||||
|
++it_beg_pos;
|
||||||
|
}
|
||||||
|
iterator it_end_pos(it_beg_pos);
|
||||||
|
for(unsigned int it_end_pos_num = 0; it_end_pos_num != (final_pos - initial_pos); ++it_end_pos_num){
|
||||||
|
++it_end_pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Erase the same values in both the intrusive and original vector
|
||||||
|
std::size_t erased_cnt = std::distance(it_beg_pos, it_end_pos);
|
||||||
|
|
||||||
|
//Erase values from the intrusive container
|
||||||
|
testset.erase(it_beg_pos, it_end_pos);
|
||||||
|
|
||||||
|
BOOST_TEST (testset.size() == (random_init.size()-(final_pos - initial_pos)));
|
||||||
|
|
||||||
|
//Now test...
|
||||||
|
BOOST_TEST ((random_init.size() - erased_cnt) == testset.size());
|
||||||
|
|
||||||
|
//Create an ordered copy of the intrusive container
|
||||||
|
set_tester.insert(set_tester.end(), testset.begin(), testset.end());
|
||||||
|
std::sort(set_tester.begin(), set_tester.end());
|
||||||
|
{
|
||||||
|
typename std::vector<value_type>::iterator it = set_tester.begin(), itend = set_tester.end();
|
||||||
|
typename std::vector<value_type>::iterator random_init_it(random_init.begin());
|
||||||
|
for( ; it != itend; ++it){
|
||||||
|
while(!random_init_it->is_linked())
|
||||||
|
++random_init_it;
|
||||||
|
BOOST_TEST(*it == *random_init_it);
|
||||||
|
++random_init_it;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
set_tester.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//test: insert (seq-version), swap, erase (seq-version), size:
|
//test: insert (seq-version), swap, erase (seq-version), size:
|
||||||
template<class ValueTraits>
|
template<class ValueTraits, bool CacheBegin>
|
||||||
void test_unordered_multiset<ValueTraits>::test_swap(std::vector<typename ValueTraits::value_type>& values)
|
void test_unordered_multiset<ValueTraits, CacheBegin>::test_swap(std::vector<typename ValueTraits::value_type>& values)
|
||||||
{
|
{
|
||||||
typedef typename ValueTraits::value_type value_type;
|
typedef typename ValueTraits::value_type value_type;
|
||||||
typedef unordered_multiset
|
typedef unordered_multiset
|
||||||
<value_type
|
<value_type
|
||||||
, value_traits<ValueTraits>
|
, value_traits<ValueTraits>
|
||||||
, constant_time_size<value_type::constant_time_size>
|
, constant_time_size<value_type::constant_time_size>
|
||||||
|
, cache_begin<CacheBegin>
|
||||||
> unordered_multiset_type;
|
> unordered_multiset_type;
|
||||||
typedef typename unordered_multiset_type::bucket_traits bucket_traits;
|
typedef typename unordered_multiset_type::bucket_traits bucket_traits;
|
||||||
|
|
||||||
typename unordered_multiset_type::bucket_type buckets [BucketSize];
|
typename unordered_multiset_type::bucket_type buckets [BucketSize];
|
||||||
typename unordered_multiset_type::bucket_type buckets2 [BucketSize];
|
{
|
||||||
unordered_multiset_type testset1(&values[0], &values[0] + 2, bucket_traits(buckets, BucketSize));
|
typename unordered_multiset_type::bucket_type buckets2 [BucketSize];
|
||||||
unordered_multiset_type testset2(bucket_traits(buckets2, BucketSize));
|
unordered_multiset_type testset1(&values[0], &values[0] + 2, bucket_traits(buckets, BucketSize));
|
||||||
|
unordered_multiset_type testset2(bucket_traits(buckets2, BucketSize));
|
||||||
|
|
||||||
testset2.insert (&values[0] + 2, &values[0] + 6);
|
testset2.insert (&values[0] + 2, &values[0] + 6);
|
||||||
testset1.swap (testset2);
|
testset1.swap (testset2);
|
||||||
|
|
||||||
{ int init_values [] = { 1, 2, 4, 5 };
|
{ int init_values [] = { 1, 2, 4, 5 };
|
||||||
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
|
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
|
||||||
|
|
||||||
{ int init_values [] = { 2, 3 };
|
{ int init_values [] = { 2, 3 };
|
||||||
TEST_INTRUSIVE_SEQUENCE( init_values, testset2.begin() ); }
|
TEST_INTRUSIVE_SEQUENCE( init_values, testset2.begin() ); }
|
||||||
|
testset1.erase (testset1.iterator_to(values[5]), testset1.end());
|
||||||
testset1.erase (testset1.iterator_to(values[5]), testset1.end());
|
BOOST_TEST (testset1.size() == 1);
|
||||||
BOOST_TEST (testset1.size() == 1);
|
// BOOST_TEST (&testset1.front() == &values[3]);
|
||||||
// BOOST_TEST (&testset1.front() == &values[3]);
|
BOOST_TEST (&*testset1.begin() == &values[3]);
|
||||||
BOOST_TEST (&*testset1.begin() == &values[3]);
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//test: rehash:
|
//test: rehash:
|
||||||
template<class ValueTraits>
|
template<class ValueTraits, bool CacheBegin>
|
||||||
void test_unordered_multiset<ValueTraits>::test_rehash(std::vector<typename ValueTraits::value_type>& values)
|
void test_unordered_multiset<ValueTraits, CacheBegin>::test_rehash(std::vector<typename ValueTraits::value_type>& values)
|
||||||
{
|
{
|
||||||
typedef typename ValueTraits::value_type value_type;
|
typedef typename ValueTraits::value_type value_type;
|
||||||
typedef unordered_multiset
|
typedef unordered_multiset
|
||||||
<value_type
|
<value_type
|
||||||
, value_traits<ValueTraits>
|
, value_traits<ValueTraits>
|
||||||
, constant_time_size<value_type::constant_time_size>
|
, constant_time_size<value_type::constant_time_size>
|
||||||
|
, cache_begin<CacheBegin>
|
||||||
> unordered_multiset_type;
|
> unordered_multiset_type;
|
||||||
typedef typename unordered_multiset_type::bucket_traits bucket_traits;
|
typedef typename unordered_multiset_type::bucket_traits bucket_traits;
|
||||||
|
|
||||||
@@ -261,14 +348,15 @@ void test_unordered_multiset<ValueTraits>::test_rehash(std::vector<typename Valu
|
|||||||
}
|
}
|
||||||
|
|
||||||
//test: find, equal_range (lower_bound, upper_bound):
|
//test: find, equal_range (lower_bound, upper_bound):
|
||||||
template<class ValueTraits>
|
template<class ValueTraits, bool CacheBegin>
|
||||||
void test_unordered_multiset<ValueTraits>::test_find(std::vector<typename ValueTraits::value_type>& values)
|
void test_unordered_multiset<ValueTraits, CacheBegin>::test_find(std::vector<typename ValueTraits::value_type>& values)
|
||||||
{
|
{
|
||||||
typedef typename ValueTraits::value_type value_type;
|
typedef typename ValueTraits::value_type value_type;
|
||||||
typedef unordered_multiset
|
typedef unordered_multiset
|
||||||
<value_type
|
<value_type
|
||||||
, value_traits<ValueTraits>
|
, value_traits<ValueTraits>
|
||||||
, constant_time_size<value_type::constant_time_size>
|
, constant_time_size<value_type::constant_time_size>
|
||||||
|
, cache_begin<CacheBegin>
|
||||||
> unordered_multiset_type;
|
> unordered_multiset_type;
|
||||||
typedef typename unordered_multiset_type::bucket_traits bucket_traits;
|
typedef typename unordered_multiset_type::bucket_traits bucket_traits;
|
||||||
|
|
||||||
@@ -293,8 +381,8 @@ void test_unordered_multiset<ValueTraits>::test_find(std::vector<typename ValueT
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template<class ValueTraits>
|
template<class ValueTraits, bool CacheBegin>
|
||||||
void test_unordered_multiset<ValueTraits>
|
void test_unordered_multiset<ValueTraits, CacheBegin>
|
||||||
::test_clone(std::vector<typename ValueTraits::value_type>& values)
|
::test_clone(std::vector<typename ValueTraits::value_type>& values)
|
||||||
{
|
{
|
||||||
typedef typename ValueTraits::value_type value_type;
|
typedef typename ValueTraits::value_type value_type;
|
||||||
@@ -302,6 +390,7 @@ void test_unordered_multiset<ValueTraits>
|
|||||||
<value_type
|
<value_type
|
||||||
, value_traits<ValueTraits>
|
, value_traits<ValueTraits>
|
||||||
, constant_time_size<value_type::constant_time_size>
|
, constant_time_size<value_type::constant_time_size>
|
||||||
|
, cache_begin<CacheBegin>
|
||||||
> unordered_multiset_type;
|
> unordered_multiset_type;
|
||||||
typedef typename unordered_multiset_type::bucket_traits bucket_traits;
|
typedef typename unordered_multiset_type::bucket_traits bucket_traits;
|
||||||
{
|
{
|
||||||
@@ -373,6 +462,7 @@ class test_main_template
|
|||||||
< value_type
|
< value_type
|
||||||
, typename value_type::unordered_set_base_hook_t
|
, typename value_type::unordered_set_base_hook_t
|
||||||
>::type
|
>::type
|
||||||
|
, true
|
||||||
>::test_all(data);
|
>::test_all(data);
|
||||||
|
|
||||||
test_unordered_multiset < typename detail::get_member_value_traits
|
test_unordered_multiset < typename detail::get_member_value_traits
|
||||||
@@ -382,6 +472,7 @@ class test_main_template
|
|||||||
, &value_type::unordered_set_node_
|
, &value_type::unordered_set_node_
|
||||||
>
|
>
|
||||||
>::type
|
>::type
|
||||||
|
, false
|
||||||
>::test_all(data);
|
>::test_all(data);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -404,6 +495,7 @@ class test_main_template<VoidPointer, false>
|
|||||||
< value_type
|
< value_type
|
||||||
, typename value_type::unordered_set_base_hook_t
|
, typename value_type::unordered_set_base_hook_t
|
||||||
>::type
|
>::type
|
||||||
|
, true
|
||||||
>::test_all(data);
|
>::test_all(data);
|
||||||
|
|
||||||
test_unordered_multiset < typename detail::get_member_value_traits
|
test_unordered_multiset < typename detail::get_member_value_traits
|
||||||
@@ -413,12 +505,14 @@ class test_main_template<VoidPointer, false>
|
|||||||
, &value_type::unordered_set_node_
|
, &value_type::unordered_set_node_
|
||||||
>
|
>
|
||||||
>::type
|
>::type
|
||||||
|
, false
|
||||||
>::test_all(data);
|
>::test_all(data);
|
||||||
|
|
||||||
test_unordered_multiset < typename detail::get_base_value_traits
|
test_unordered_multiset < typename detail::get_base_value_traits
|
||||||
< value_type
|
< value_type
|
||||||
, typename value_type::unordered_set_auto_base_hook_t
|
, typename value_type::unordered_set_auto_base_hook_t
|
||||||
>::type
|
>::type
|
||||||
|
, true
|
||||||
>::test_all(data);
|
>::test_all(data);
|
||||||
|
|
||||||
test_unordered_multiset < typename detail::get_member_value_traits
|
test_unordered_multiset < typename detail::get_member_value_traits
|
||||||
@@ -428,6 +522,7 @@ class test_main_template<VoidPointer, false>
|
|||||||
, &value_type::unordered_set_auto_node_
|
, &value_type::unordered_set_auto_node_
|
||||||
>
|
>
|
||||||
>::type
|
>::type
|
||||||
|
, false
|
||||||
>::test_all(data);
|
>::test_all(data);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@@ -26,7 +26,7 @@ using namespace boost::intrusive;
|
|||||||
|
|
||||||
static const std::size_t BucketSize = 11;
|
static const std::size_t BucketSize = 11;
|
||||||
|
|
||||||
template<class ValueTraits>
|
template<class ValueTraits, bool CacheBegin>
|
||||||
struct test_unordered_set
|
struct test_unordered_set
|
||||||
{
|
{
|
||||||
typedef typename ValueTraits::value_type value_type;
|
typedef typename ValueTraits::value_type value_type;
|
||||||
@@ -40,14 +40,15 @@ struct test_unordered_set
|
|||||||
static void test_clone(std::vector<value_type>& values);
|
static void test_clone(std::vector<value_type>& values);
|
||||||
};
|
};
|
||||||
|
|
||||||
template<class ValueTraits>
|
template<class ValueTraits, bool CacheBegin>
|
||||||
void test_unordered_set<ValueTraits>::test_all(std::vector<typename ValueTraits::value_type>& values)
|
void test_unordered_set<ValueTraits, CacheBegin>::test_all(std::vector<typename ValueTraits::value_type>& values)
|
||||||
{
|
{
|
||||||
typedef typename ValueTraits::value_type value_type;
|
typedef typename ValueTraits::value_type value_type;
|
||||||
typedef unordered_set
|
typedef unordered_set
|
||||||
<value_type
|
<value_type
|
||||||
, value_traits<ValueTraits>
|
, value_traits<ValueTraits>
|
||||||
, constant_time_size<value_type::constant_time_size>
|
, constant_time_size<value_type::constant_time_size>
|
||||||
|
, cache_begin<CacheBegin>
|
||||||
> unordered_set_type;
|
> unordered_set_type;
|
||||||
typedef typename unordered_set_type::bucket_traits bucket_traits;
|
typedef typename unordered_set_type::bucket_traits bucket_traits;
|
||||||
{
|
{
|
||||||
@@ -75,14 +76,15 @@ void test_unordered_set<ValueTraits>::test_all(std::vector<typename ValueTraits:
|
|||||||
}
|
}
|
||||||
|
|
||||||
//test case due to an error in tree implementation:
|
//test case due to an error in tree implementation:
|
||||||
template<class ValueTraits>
|
template<class ValueTraits, bool CacheBegin>
|
||||||
void test_unordered_set<ValueTraits>::test_impl()
|
void test_unordered_set<ValueTraits, CacheBegin>::test_impl()
|
||||||
{
|
{
|
||||||
typedef typename ValueTraits::value_type value_type;
|
typedef typename ValueTraits::value_type value_type;
|
||||||
typedef unordered_set
|
typedef unordered_set
|
||||||
<value_type
|
<value_type
|
||||||
, value_traits<ValueTraits>
|
, value_traits<ValueTraits>
|
||||||
, constant_time_size<value_type::constant_time_size>
|
, constant_time_size<value_type::constant_time_size>
|
||||||
|
, cache_begin<CacheBegin>
|
||||||
> unordered_set_type;
|
> unordered_set_type;
|
||||||
typedef typename unordered_set_type::bucket_traits bucket_traits;
|
typedef typename unordered_set_type::bucket_traits bucket_traits;
|
||||||
|
|
||||||
@@ -103,14 +105,15 @@ void test_unordered_set<ValueTraits>::test_impl()
|
|||||||
}
|
}
|
||||||
|
|
||||||
//test: constructor, iterator, clear, reverse_iterator, front, back, size:
|
//test: constructor, iterator, clear, reverse_iterator, front, back, size:
|
||||||
template<class ValueTraits>
|
template<class ValueTraits, bool CacheBegin>
|
||||||
void test_unordered_set<ValueTraits>::test_sort(std::vector<typename ValueTraits::value_type>& values)
|
void test_unordered_set<ValueTraits, CacheBegin>::test_sort(std::vector<typename ValueTraits::value_type>& values)
|
||||||
{
|
{
|
||||||
typedef typename ValueTraits::value_type value_type;
|
typedef typename ValueTraits::value_type value_type;
|
||||||
typedef unordered_set
|
typedef unordered_set
|
||||||
<value_type
|
<value_type
|
||||||
, value_traits<ValueTraits>
|
, value_traits<ValueTraits>
|
||||||
, constant_time_size<value_type::constant_time_size>
|
, constant_time_size<value_type::constant_time_size>
|
||||||
|
, cache_begin<CacheBegin>
|
||||||
> unordered_set_type;
|
> unordered_set_type;
|
||||||
typedef typename unordered_set_type::bucket_traits bucket_traits;
|
typedef typename unordered_set_type::bucket_traits bucket_traits;
|
||||||
|
|
||||||
@@ -126,14 +129,15 @@ void test_unordered_set<ValueTraits>::test_sort(std::vector<typename ValueTraits
|
|||||||
}
|
}
|
||||||
|
|
||||||
//test: insert, const_iterator, const_reverse_iterator, erase, iterator_to:
|
//test: insert, const_iterator, const_reverse_iterator, erase, iterator_to:
|
||||||
template<class ValueTraits>
|
template<class ValueTraits, bool CacheBegin>
|
||||||
void test_unordered_set<ValueTraits>::test_insert(std::vector<typename ValueTraits::value_type>& values)
|
void test_unordered_set<ValueTraits, CacheBegin>::test_insert(std::vector<typename ValueTraits::value_type>& values)
|
||||||
{
|
{
|
||||||
typedef typename ValueTraits::value_type value_type;
|
typedef typename ValueTraits::value_type value_type;
|
||||||
typedef unordered_set
|
typedef unordered_set
|
||||||
<value_type
|
<value_type
|
||||||
, value_traits<ValueTraits>
|
, value_traits<ValueTraits>
|
||||||
, constant_time_size<value_type::constant_time_size>
|
, constant_time_size<value_type::constant_time_size>
|
||||||
|
, cache_begin<CacheBegin>
|
||||||
> unordered_set_type;
|
> unordered_set_type;
|
||||||
typedef typename unordered_set_type::bucket_traits bucket_traits;
|
typedef typename unordered_set_type::bucket_traits bucket_traits;
|
||||||
|
|
||||||
@@ -161,14 +165,15 @@ void test_unordered_set<ValueTraits>::test_insert(std::vector<typename ValueTrai
|
|||||||
}
|
}
|
||||||
|
|
||||||
//test: insert (seq-version), swap, erase (seq-version), size:
|
//test: insert (seq-version), swap, erase (seq-version), size:
|
||||||
template<class ValueTraits>
|
template<class ValueTraits, bool CacheBegin>
|
||||||
void test_unordered_set<ValueTraits>::test_swap(std::vector<typename ValueTraits::value_type>& values)
|
void test_unordered_set<ValueTraits, CacheBegin>::test_swap(std::vector<typename ValueTraits::value_type>& values)
|
||||||
{
|
{
|
||||||
typedef typename ValueTraits::value_type value_type;
|
typedef typename ValueTraits::value_type value_type;
|
||||||
typedef unordered_set
|
typedef unordered_set
|
||||||
<value_type
|
<value_type
|
||||||
, value_traits<ValueTraits>
|
, value_traits<ValueTraits>
|
||||||
, constant_time_size<value_type::constant_time_size>
|
, constant_time_size<value_type::constant_time_size>
|
||||||
|
, cache_begin<CacheBegin>
|
||||||
> unordered_set_type;
|
> unordered_set_type;
|
||||||
typedef typename unordered_set_type::bucket_traits bucket_traits;
|
typedef typename unordered_set_type::bucket_traits bucket_traits;
|
||||||
|
|
||||||
@@ -192,14 +197,15 @@ void test_unordered_set<ValueTraits>::test_swap(std::vector<typename ValueTraits
|
|||||||
}
|
}
|
||||||
|
|
||||||
//test: rehash:
|
//test: rehash:
|
||||||
template<class ValueTraits>
|
template<class ValueTraits, bool CacheBegin>
|
||||||
void test_unordered_set<ValueTraits>::test_rehash(std::vector<typename ValueTraits::value_type>& values)
|
void test_unordered_set<ValueTraits, CacheBegin>::test_rehash(std::vector<typename ValueTraits::value_type>& values)
|
||||||
{
|
{
|
||||||
typedef typename ValueTraits::value_type value_type;
|
typedef typename ValueTraits::value_type value_type;
|
||||||
typedef unordered_set
|
typedef unordered_set
|
||||||
<value_type
|
<value_type
|
||||||
, value_traits<ValueTraits>
|
, value_traits<ValueTraits>
|
||||||
, constant_time_size<value_type::constant_time_size>
|
, constant_time_size<value_type::constant_time_size>
|
||||||
|
, cache_begin<CacheBegin>
|
||||||
> unordered_set_type;
|
> unordered_set_type;
|
||||||
typedef typename unordered_set_type::bucket_traits bucket_traits;
|
typedef typename unordered_set_type::bucket_traits bucket_traits;
|
||||||
|
|
||||||
@@ -237,14 +243,15 @@ void test_unordered_set<ValueTraits>::test_rehash(std::vector<typename ValueTrai
|
|||||||
|
|
||||||
|
|
||||||
//test: find, equal_range (lower_bound, upper_bound):
|
//test: find, equal_range (lower_bound, upper_bound):
|
||||||
template<class ValueTraits>
|
template<class ValueTraits, bool CacheBegin>
|
||||||
void test_unordered_set<ValueTraits>::test_find(std::vector<typename ValueTraits::value_type>& values)
|
void test_unordered_set<ValueTraits, CacheBegin>::test_find(std::vector<typename ValueTraits::value_type>& values)
|
||||||
{
|
{
|
||||||
typedef typename ValueTraits::value_type value_type;
|
typedef typename ValueTraits::value_type value_type;
|
||||||
typedef unordered_set
|
typedef unordered_set
|
||||||
<value_type
|
<value_type
|
||||||
, value_traits<ValueTraits>
|
, value_traits<ValueTraits>
|
||||||
, constant_time_size<value_type::constant_time_size>
|
, constant_time_size<value_type::constant_time_size>
|
||||||
|
, cache_begin<CacheBegin>
|
||||||
> unordered_set_type;
|
> unordered_set_type;
|
||||||
typedef typename unordered_set_type::bucket_traits bucket_traits;
|
typedef typename unordered_set_type::bucket_traits bucket_traits;
|
||||||
|
|
||||||
@@ -267,8 +274,8 @@ void test_unordered_set<ValueTraits>::test_find(std::vector<typename ValueTraits
|
|||||||
BOOST_TEST (testset.find (cmp_val) == testset.end());
|
BOOST_TEST (testset.find (cmp_val) == testset.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class ValueTraits>
|
template<class ValueTraits, bool CacheBegin>
|
||||||
void test_unordered_set<ValueTraits>
|
void test_unordered_set<ValueTraits, CacheBegin>
|
||||||
::test_clone(std::vector<typename ValueTraits::value_type>& values)
|
::test_clone(std::vector<typename ValueTraits::value_type>& values)
|
||||||
{
|
{
|
||||||
typedef typename ValueTraits::value_type value_type;
|
typedef typename ValueTraits::value_type value_type;
|
||||||
@@ -276,6 +283,7 @@ void test_unordered_set<ValueTraits>
|
|||||||
<value_type
|
<value_type
|
||||||
, value_traits<ValueTraits>
|
, value_traits<ValueTraits>
|
||||||
, constant_time_size<value_type::constant_time_size>
|
, constant_time_size<value_type::constant_time_size>
|
||||||
|
, cache_begin<CacheBegin>
|
||||||
> unordered_set_type;
|
> unordered_set_type;
|
||||||
typedef typename unordered_set_type::bucket_traits bucket_traits;
|
typedef typename unordered_set_type::bucket_traits bucket_traits;
|
||||||
{
|
{
|
||||||
@@ -347,6 +355,7 @@ class test_main_template
|
|||||||
< value_type
|
< value_type
|
||||||
, typename value_type::unordered_set_base_hook_t
|
, typename value_type::unordered_set_base_hook_t
|
||||||
>::type
|
>::type
|
||||||
|
, true
|
||||||
>::test_all(data);
|
>::test_all(data);
|
||||||
test_unordered_set < typename detail::get_member_value_traits
|
test_unordered_set < typename detail::get_member_value_traits
|
||||||
< value_type
|
< value_type
|
||||||
@@ -355,6 +364,7 @@ class test_main_template
|
|||||||
, &value_type::unordered_set_node_
|
, &value_type::unordered_set_node_
|
||||||
>
|
>
|
||||||
>::type
|
>::type
|
||||||
|
, false
|
||||||
>::test_all(data);
|
>::test_all(data);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -377,6 +387,7 @@ class test_main_template<VoidPointer, false>
|
|||||||
< value_type
|
< value_type
|
||||||
, typename value_type::unordered_set_base_hook_t
|
, typename value_type::unordered_set_base_hook_t
|
||||||
>::type
|
>::type
|
||||||
|
, true
|
||||||
>::test_all(data);
|
>::test_all(data);
|
||||||
|
|
||||||
test_unordered_set < typename detail::get_member_value_traits
|
test_unordered_set < typename detail::get_member_value_traits
|
||||||
@@ -386,12 +397,14 @@ class test_main_template<VoidPointer, false>
|
|||||||
, &value_type::unordered_set_node_
|
, &value_type::unordered_set_node_
|
||||||
>
|
>
|
||||||
>::type
|
>::type
|
||||||
|
, false
|
||||||
>::test_all(data);
|
>::test_all(data);
|
||||||
|
|
||||||
test_unordered_set < typename detail::get_base_value_traits
|
test_unordered_set < typename detail::get_base_value_traits
|
||||||
< value_type
|
< value_type
|
||||||
, typename value_type::unordered_set_auto_base_hook_t
|
, typename value_type::unordered_set_auto_base_hook_t
|
||||||
>::type
|
>::type
|
||||||
|
, true
|
||||||
>::test_all(data);
|
>::test_all(data);
|
||||||
|
|
||||||
test_unordered_set < typename detail::get_member_value_traits
|
test_unordered_set < typename detail::get_member_value_traits
|
||||||
@@ -401,6 +414,7 @@ class test_main_template<VoidPointer, false>
|
|||||||
, &value_type::unordered_set_auto_node_
|
, &value_type::unordered_set_auto_node_
|
||||||
>
|
>
|
||||||
>::type
|
>::type
|
||||||
|
, false
|
||||||
>::test_all(data);
|
>::test_all(data);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user