Merged Interprocess + Intrusive revision 42982 from trunk to release branch

[SVN r42994]
This commit is contained in:
Ion Gaztañaga
2008-01-27 22:22:22 +00:00
parent cc749e440e
commit 0ddb2b7045
23 changed files with 1896 additions and 838 deletions

View File

@@ -1,3 +1,11 @@
/*=============================================================================
Copyright (c) 2004 Joel de Guzman
http://spirit.sourceforge.net/
Use, modification and distribution is subject to the Boost Software
License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
http://www.boost.org/LICENSE_1_0.txt)
=============================================================================*/
PRE.synopsis { PRE.synopsis {
background-color: #e0ffff; background-color: #e0ffff;
border: thin solid blue; border: thin solid blue;

View File

@@ -38,7 +38,7 @@ int main()
//Create an empty doubly linked list container: //Create an empty doubly linked list container:
//"one" will be the first node of the container //"one" will be the first node of the container
algo::init(&one); algo::init_header(&one);
assert(algo::count(&one) == 1); assert(algo::count(&one) == 1);
//Now add a new node before "one" //Now add a new node before "one"

View File

@@ -36,7 +36,7 @@ int main()
//Create an empty singly linked list container: //Create an empty singly linked list container:
//"one" will be the first node of the container //"one" will be the first node of the container
algo::init(&one); algo::init_header(&one);
assert(algo::count(&one) == 1); assert(algo::count(&one) == 1);
//Now add a new node //Now add a new node

View File

@@ -75,5 +75,4 @@ int main()
algo::erase(&header, &three); algo::erase(&header, &three);
return 0; return 0;
} }
//] //]

View File

@@ -54,6 +54,27 @@ class circular_list_algorithms
typedef typename NodeTraits::const_node_ptr const_node_ptr; typedef typename NodeTraits::const_node_ptr const_node_ptr;
typedef NodeTraits node_traits; typedef NodeTraits node_traits;
//! <b>Effects</b>: Constructs an non-used list element, so that
//! inited(this_node) == true
//!
//! <b>Complexity</b>: Constant
//!
//! <b>Throws</b>: Nothing.
static void init(node_ptr this_node)
{
NodeTraits::set_next(this_node, 0);
NodeTraits::set_previous(this_node, 0);
}
//! <b>Effects</b>: Returns true is "this_node" is in a non-used state
//! as if it was initialized by the "init" function.
//!
//! <b>Complexity</b>: Constant
//!
//! <b>Throws</b>: Nothing.
static bool inited(const_node_ptr this_node)
{ return !NodeTraits::get_next(this_node); }
//! <b>Effects</b>: Constructs an empty list, making this_node the only //! <b>Effects</b>: Constructs an empty list, making this_node the only
//! node of the circular list: //! node of the circular list:
//! <tt>NodeTraits::get_next(this_node) == NodeTraits::get_previous(this_node) //! <tt>NodeTraits::get_next(this_node) == NodeTraits::get_previous(this_node)
@@ -62,12 +83,13 @@ class circular_list_algorithms
//! <b>Complexity</b>: Constant //! <b>Complexity</b>: Constant
//! //!
//! <b>Throws</b>: Nothing. //! <b>Throws</b>: Nothing.
static void init(node_ptr this_node) static void init_header(node_ptr this_node)
{ {
NodeTraits::set_next(this_node, this_node); NodeTraits::set_next(this_node, this_node);
NodeTraits::set_previous(this_node, this_node); NodeTraits::set_previous(this_node, this_node);
} }
//! <b>Requires</b>: this_node must be in a circular list or be an empty circular list. //! <b>Requires</b>: this_node must be in a circular list or be an empty circular list.
//! //!
//! <b>Effects</b>: Returns true is "this_node" is the only node of a circular list: //! <b>Effects</b>: Returns true is "this_node" is the only node of a circular list:
@@ -77,7 +99,10 @@ class circular_list_algorithms
//! //!
//! <b>Throws</b>: Nothing. //! <b>Throws</b>: Nothing.
static bool unique(const_node_ptr this_node) static bool unique(const_node_ptr this_node)
{ return NodeTraits::get_next(this_node) == this_node; } {
node_ptr next = NodeTraits::get_next(this_node);
return !next || next == this_node;
}
//! <b>Requires</b>: this_node must be in a circular list or be an empty circular list. //! <b>Requires</b>: this_node must be in a circular list or be an empty circular list.
//! //!
@@ -107,12 +132,17 @@ class circular_list_algorithms
//! <b>Throws</b>: Nothing. //! <b>Throws</b>: Nothing.
static node_ptr unlink(node_ptr this_node) static node_ptr unlink(node_ptr this_node)
{ {
if(NodeTraits::get_next(this_node)){
node_ptr next(NodeTraits::get_next(this_node)); node_ptr next(NodeTraits::get_next(this_node));
node_ptr prev(NodeTraits::get_previous(this_node)); node_ptr prev(NodeTraits::get_previous(this_node));
NodeTraits::set_next(prev, next); NodeTraits::set_next(prev, next);
NodeTraits::set_previous(next, prev); NodeTraits::set_previous(next, prev);
return next; return next;
} }
else{
return this_node;
}
}
//! <b>Requires</b>: b and e must be nodes of the same circular list or an empty range. //! <b>Requires</b>: b and e must be nodes of the same circular list or an empty range.
//! //!
@@ -124,10 +154,9 @@ class circular_list_algorithms
static void unlink(node_ptr b, node_ptr e) static void unlink(node_ptr b, node_ptr e)
{ {
if (b != e) { if (b != e) {
node_ptr prev(NodeTraits::get_previous(b)); node_ptr prevb(NodeTraits::get_previous(b));
node_ptr next(NodeTraits::get_next(e)); NodeTraits::set_previous(e, prevb);
NodeTraits::set_previous(next, prev); NodeTraits::set_next(prevb, e);
NodeTraits::set_next(prev, next);
} }
} }
@@ -229,6 +258,17 @@ class circular_list_algorithms
public: public:
static void swap_nodes(node_ptr this_node, node_ptr other_node) static void swap_nodes(node_ptr this_node, node_ptr other_node)
{ {
if (other_node == this_node)
return;
bool this_inited = inited(this_node);
bool other_inited = inited(other_node);
if(this_inited){
init_header(this_node);
}
if(other_inited){
init_header(other_node);
}
node_ptr next_this(NodeTraits::get_next(this_node)); node_ptr next_this(NodeTraits::get_next(this_node));
node_ptr prev_this(NodeTraits::get_previous(this_node)); node_ptr prev_this(NodeTraits::get_previous(this_node));
node_ptr next_other(NodeTraits::get_next(other_node)); node_ptr next_other(NodeTraits::get_next(other_node));
@@ -238,6 +278,13 @@ class circular_list_algorithms
swap_next(prev_this, prev_other); swap_next(prev_this, prev_other);
swap_next(this_node, other_node); swap_next(this_node, other_node);
swap_prev(this_node, other_node); swap_prev(this_node, other_node);
if(this_inited){
init(other_node);
}
if(other_inited){
init(this_node);
}
} }
//! <b>Requires</b>: b and e must be nodes of the same circular list or an empty range. //! <b>Requires</b>: b and e must be nodes of the same circular list or an empty range.
@@ -254,8 +301,8 @@ class circular_list_algorithms
{ {
if (b != e) { if (b != e) {
node_ptr prev_p(NodeTraits::get_previous(p)); node_ptr prev_p(NodeTraits::get_previous(p));
node_ptr prev_e(NodeTraits::get_previous(e));
node_ptr prev_b(NodeTraits::get_previous(b)); node_ptr prev_b(NodeTraits::get_previous(b));
node_ptr prev_e(NodeTraits::get_previous(e));
NodeTraits::set_next(prev_e, p); NodeTraits::set_next(prev_e, p);
NodeTraits::set_previous(p, prev_e); NodeTraits::set_previous(p, prev_e);
NodeTraits::set_next(prev_b, e); NodeTraits::set_next(prev_b, e);
@@ -308,6 +355,47 @@ class circular_list_algorithms
f = n; f = n;
} }
} }
//! <b>Effects</b>: Moves the node p n positions towards the end of the list.
//!
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Linear to the number of moved positions.
static void move_backwards(node_ptr p, std::size_t n)
{
//Null shift, nothing to do
if(!n) return;
node_ptr first = NodeTraits::get_next(p);
//size() == 0 or 1, nothing to do
if(first == NodeTraits::get_previous(p)) return;
unlink(p);
//Now get the new first node
while(n--){
first = NodeTraits::get_next(first);
}
link_before(first, p);
}
//! <b>Effects</b>: Moves the node p n positions towards the beginning of the list.
//!
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Linear to the number of moved positions.
static void move_forward(node_ptr p, std::size_t n)
{
//Null shift, nothing to do
if(!n) return;
node_ptr last = NodeTraits::get_previous(p);
//size() == 0 or 1, nothing to do
if(last == NodeTraits::get_next(p)) return;
unlink(p);
//Now get the new last node
while(n--){
last = NodeTraits::get_previous(last);
}
link_after(last, p);
}
}; };
} //namespace intrusive } //namespace intrusive

View File

@@ -16,6 +16,8 @@
#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/common_slist_algorithms.hpp>
#include <boost/intrusive/detail/assert.hpp>
#include <cstddef> #include <cstddef>
namespace boost { namespace boost {
@@ -25,7 +27,7 @@ namespace intrusive {
//! forming a circular singly linked list. An empty circular list is formed by a node //! forming a circular singly linked list. An empty circular list is formed by a node
//! whose pointer to the next node points to itself. //! whose pointer to the next node points to itself.
//! //!
//! circular_slist_algorithms is configured with a NodeTraits class, which capsulates the //! circular_slist_algorithms is configured with a NodeTraits class, which encapsulates the
//! information about the node to be manipulated. NodeTraits must support the //! information about the node to be manipulated. NodeTraits must support the
//! following interface: //! following interface:
//! //!
@@ -44,22 +46,98 @@ namespace intrusive {
//! <tt>static void set_next(node_ptr n, node_ptr next);</tt> //! <tt>static void set_next(node_ptr n, node_ptr next);</tt>
template<class NodeTraits> template<class NodeTraits>
class circular_slist_algorithms class circular_slist_algorithms
/// @cond
: public detail::common_slist_algorithms<NodeTraits>
/// @endcond
{ {
/// @cond
typedef detail::common_slist_algorithms<NodeTraits> base_t;
/// @endcond
public: public:
typedef typename NodeTraits::node_ptr node_ptr; typedef typename NodeTraits::node_ptr node_ptr;
typedef typename NodeTraits::const_node_ptr const_node_ptr; typedef typename NodeTraits::const_node_ptr const_node_ptr;
typedef NodeTraits node_traits; typedef NodeTraits node_traits;
//! <b>Requires</b>: this_node must be in a circular list or be an empty circular list. #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
//! <b>Effects</b>: Constructs an non-used list element, putting the next
//! pointer to null:
//! <tt>NodeTraits::get_next(this_node) == 0
//! //!
//! <b>Effects</b>: Returns the previous node of this_node in the circular list. //! <b>Complexity</b>: Constant
//!
//! <b>Complexity</b>: Linear to the number of elements in the circular list.
//! //!
//! <b>Throws</b>: Nothing. //! <b>Throws</b>: Nothing.
static node_ptr get_previous_node(node_ptr this_node) static void init(node_ptr this_node);
{ return get_previous_node(this_node, this_node); }
//! <b>Requires</b>: this_node must be in a circular list or be an empty circular list.
//!
//! <b>Effects</b>: Returns true is "this_node" is the only node of a circular list:
//! or it's a not inserted node:
//! <tt>return !NodeTraits::get_next(this_node) || NodeTraits::get_next(this_node) == this_node</tt>
//!
//! <b>Complexity</b>: Constant
//!
//! <b>Throws</b>: Nothing.
static bool unique(const_node_ptr this_node);
//! <b>Effects</b>: Returns true is "this_node" has the same state as
//! if it was inited using "init(node_ptr)"
//!
//! <b>Complexity</b>: Constant
//!
//! <b>Throws</b>: Nothing.
static bool inited(const_node_ptr this_node);
//! <b>Requires</b>: prev_node must be in a circular list or be an empty circular list.
//!
//! <b>Effects</b>: Unlinks the next node of prev_node from the circular list.
//!
//! <b>Complexity</b>: Constant
//!
//! <b>Throws</b>: Nothing.
static void unlink_after(node_ptr prev_node);
//! <b>Requires</b>: prev_node and last_node must be in a circular list
//! or be an empty circular list.
//!
//! <b>Effects</b>: Unlinks the range (prev_node, last_node) from the circular list.
//!
//! <b>Complexity</b>: Constant
//!
//! <b>Throws</b>: Nothing.
static void unlink_after(node_ptr prev_node, node_ptr last_node);
//! <b>Requires</b>: prev_node must be a node of a circular list.
//!
//! <b>Effects</b>: Links this_node after prev_node in the circular list.
//!
//! <b>Complexity</b>: Constant
//!
//! <b>Throws</b>: Nothing.
static void link_after(node_ptr prev_node, node_ptr this_node);
//! <b>Requires</b>: b and e must be nodes of the same circular list or an empty range.
//! and p must be a node of a different circular list.
//!
//! <b>Effects</b>: Removes the nodes from (b, e] range from their circular list and inserts
//! them after p in p's circular list.
//!
//! <b>Complexity</b>: Constant
//!
//! <b>Throws</b>: Nothing.
static void transfer_after(node_ptr p, node_ptr b, node_ptr e);
#endif //#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
//! <b>Effects</b>: Constructs an empty list, making this_node the only
//! node of the circular list:
//! <tt>NodeTraits::get_next(this_node) == this_node</tt>.
//!
//! <b>Complexity</b>: Constant
//!
//! <b>Throws</b>: Nothing.
static void init_header(node_ptr this_node)
{ NodeTraits::set_next(this_node, this_node); }
//! <b>Requires</b>: this_node and prev_init_node must be in the same circular list. //! <b>Requires</b>: this_node and prev_init_node must be in the same circular list.
//! //!
@@ -71,15 +149,17 @@ class circular_slist_algorithms
//! //!
//! <b>Throws</b>: Nothing. //! <b>Throws</b>: Nothing.
static node_ptr get_previous_node(node_ptr prev_init_node, node_ptr this_node) static node_ptr get_previous_node(node_ptr prev_init_node, node_ptr this_node)
{ { return base_t::get_previous_node(prev_init_node, this_node); }
node_ptr p = prev_init_node;
for( node_ptr p_next //! <b>Requires</b>: this_node must be in a circular list or be an empty circular list.
; this_node != (p_next = NodeTraits::get_next(p)) //!
; p = p_next){ //! <b>Effects</b>: Returns the previous node of this_node in the circular list.
//empty //!
} //! <b>Complexity</b>: Linear to the number of elements in the circular list.
return p; //!
} //! <b>Throws</b>: Nothing.
static node_ptr get_previous_node(node_ptr this_node)
{ return base_t::get_previous_node(this_node, this_node); }
//! <b>Requires</b>: this_node must be in a circular list or be an empty circular list. //! <b>Requires</b>: this_node must be in a circular list or be an empty circular list.
//! //!
@@ -113,28 +193,6 @@ class circular_slist_algorithms
return p; return p;
} }
//! <b>Effects</b>: Constructs an empty list, making this_node the only
//! node of the circular list:
//! <tt>NodeTraits::get_next(this_node) == NodeTraits::get_previous(this_node)
//! == this_node</tt>.
//!
//! <b>Complexity</b>: Constant
//!
//! <b>Throws</b>: Nothing.
static void init(node_ptr this_node)
{ NodeTraits::set_next(this_node, this_node); }
//! <b>Requires</b>: this_node must be in a circular list or be an empty circular list.
//!
//! <b>Effects</b>: Returns true is "this_node" is the only node of a circular list:
//! <tt>return NodeTraits::get_next(this_node) == this_node</tt>
//!
//! <b>Complexity</b>: Constant
//!
//! <b>Throws</b>: Nothing.
static bool unique(const_node_ptr this_node)
{ return NodeTraits::get_next(this_node) == this_node; }
//! <b>Requires</b>: this_node must be in a circular list or be an empty circular list. //! <b>Requires</b>: this_node must be in a circular list or be an empty circular list.
//! //!
//! <b>Effects</b>: Returns the number of nodes in a circular list. If the circular list //! <b>Effects</b>: Returns the number of nodes in a circular list. If the circular list
@@ -154,34 +212,7 @@ class circular_slist_algorithms
return result; return result;
} }
//! <b>Requires</b>: prev_node must be in a circular list or be an empty circular list. //! <b>Requires</b>: this_node must be in a circular list, be an empty circular list or be inited.
//!
//! <b>Effects</b>: Unlinks the next node of prev_node from the circular list.
//!
//! <b>Complexity</b>: Constant
//!
//! <b>Throws</b>: Nothing.
static void unlink_after(node_ptr prev_node)
{
node_ptr this_node(NodeTraits::get_next(prev_node));
NodeTraits::set_next(prev_node, NodeTraits::get_next(this_node));
NodeTraits::set_next(this_node, this_node);
}
//! <b>Requires</b>: nxt_node must be in a circular list or be an empty circular list.
//!
//! <b>Effects</b>: Unlinks the previous node of nxt_node from the circular list.
//!
//! <b>Complexity</b>: Linear to the elements in the circular list.
//!
//! <b>Throws</b>: Nothing.
static void unlink_before(node_ptr nxt_node)
{
node_ptr prev_to_erase(get_previous_previous_node(nxt_node));
unlink_after(prev_to_erase);
}
//! <b>Requires</b>: this_node must be in a circular list or be an empty circular list.
//! //!
//! <b>Effects</b>: Unlinks the node from the circular list. //! <b>Effects</b>: Unlinks the node from the circular list.
//! //!
@@ -189,20 +220,9 @@ class circular_slist_algorithms
//! //!
//! <b>Throws</b>: Nothing. //! <b>Throws</b>: Nothing.
static void unlink(node_ptr this_node) static void unlink(node_ptr this_node)
{ unlink_after(get_previous_node(this_node)); }
//! <b>Requires</b>: prev_node must be a node of a circular list.
//!
//! <b>Effects</b>: Links this_node after prev_node in the circular list.
//!
//! <b>Complexity</b>: Constant
//!
//! <b>Throws</b>: Nothing.
static void link_after(node_ptr prev_node, node_ptr this_node)
{ {
node_ptr this_nxt = NodeTraits::get_next(prev_node); if(NodeTraits::get_next(this_node))
NodeTraits::set_next(this_node, this_nxt); base_t::unlink_after(get_previous_node(this_node));
NodeTraits::set_next(prev_node, this_node);
} }
//! <b>Requires</b>: nxt_node must be a node of a circular list. //! <b>Requires</b>: nxt_node must be a node of a circular list.
@@ -213,7 +233,7 @@ class circular_slist_algorithms
//! //!
//! <b>Throws</b>: Nothing. //! <b>Throws</b>: Nothing.
static void link_before (node_ptr nxt_node, node_ptr this_node) static void link_before (node_ptr nxt_node, node_ptr this_node)
{ link_after(get_previous_node(nxt_node), this_node); } { base_t::link_after(get_previous_node(nxt_node), this_node); }
//! <b>Requires</b>: this_node and other_node must be nodes inserted //! <b>Requires</b>: this_node and other_node must be nodes inserted
//! in circular lists or be empty circular lists. //! in circular lists or be empty circular lists.
@@ -229,8 +249,17 @@ class circular_slist_algorithms
{ {
if (other_node == this_node) if (other_node == this_node)
return; return;
bool empty1 = unique(this_node); bool this_inited = base_t::inited(this_node);
bool empty2 = unique(other_node); bool other_inited = base_t::inited(other_node);
if(this_inited){
base_t::init_header(this_node);
}
if(other_inited){
base_t::init_header(other_node);
}
bool empty1 = base_t::unique(this_node);
bool empty2 = base_t::unique(other_node);
node_ptr prev_this (get_previous_node(this_node)); node_ptr prev_this (get_previous_node(this_node));
node_ptr prev_other(get_previous_node(other_node)); node_ptr prev_other(get_previous_node(other_node));
@@ -240,26 +269,12 @@ class circular_slist_algorithms
NodeTraits::set_next(other_node, this_next); NodeTraits::set_next(other_node, this_next);
NodeTraits::set_next(empty1 ? other_node : prev_this, other_node); NodeTraits::set_next(empty1 ? other_node : prev_this, other_node);
NodeTraits::set_next(empty2 ? this_node : prev_other, this_node); NodeTraits::set_next(empty2 ? this_node : prev_other, this_node);
}
//! <b>Requires</b>: b and e must be nodes of the same circular list or an empty range. if(this_inited){
//! and p must be a node of a different circular list. base_t::init(other_node);
//! }
//! <b>Effects</b>: Removes the nodes from [b, e) range from their circular list and inserts if(other_inited){
//! them after p in p's circular list. base_t::init(this_node);
//!
//! <b>Complexity</b>: Constant
//!
//! <b>Throws</b>: Nothing.
static void transfer_after(node_ptr p, node_ptr b, node_ptr e)
{
if (p != b && p != e) {
node_ptr next_b = NodeTraits::get_next(b);
node_ptr next_e = NodeTraits::get_next(e);
node_ptr next_p = NodeTraits::get_next(p);
NodeTraits::set_next(b, next_e);
NodeTraits::set_next(e, next_p);
NodeTraits::set_next(p, next_b);
} }
} }
@@ -275,9 +290,110 @@ class circular_slist_algorithms
node_ptr nxt(NodeTraits::get_next(i)); node_ptr nxt(NodeTraits::get_next(i));
if (nxt == e) if (nxt == e)
break; break;
transfer_after(e, i, nxt); base_t::transfer_after(e, i, nxt);
} }
} }
//! <b>Effects</b>: Moves the node p n positions towards the end of the list.
//!
//! <b>Returns</b>: The previous node of p after the function if there has been any movement,
//! Null if n leads to no movement.
//!
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Linear to the number of elements plus the number moved positions.
static node_ptr move_backwards(node_ptr p, std::size_t n)
{
//Null shift, nothing to do
if(!n) return 0;
node_ptr first = NodeTraits::get_next(p);
//count() == 1 or 2, nothing to do
if(NodeTraits::get_next(first) == p)
return 0;
bool end_found = false;
node_ptr new_last(0);
//Now find the new last node according to the shift count.
//If we find p before finding the new last node
//unlink p, shortcut the search now that we know the size of the list
//and continue.
for(std::size_t i = 1; i <= n; ++i){
new_last = first;
first = NodeTraits::get_next(first);
if(first == p){
//Shortcut the shift with the modulo of the size of the list
n %= i;
if(!n)
return 0;
i = 0;
//Unlink p and continue the new first node search
first = NodeTraits::get_next(p);
base_t::unlink_after(new_last);
end_found = true;
}
}
//If the p has not been found in the previous loop, find it
//starting in the new first node and unlink it
if(!end_found){
base_t::unlink_after(base_t::get_previous_node(first, p));
}
//Now link p after the new last node
base_t::link_after(new_last, p);
return new_last;
}
//! <b>Effects</b>: Moves the node p n positions towards the beginning of the list.
//!
//! <b>Returns</b>: The previous node of p after the function if there has been any movement,
//! Null if n leads equals to no movement.
//!
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Linear to the number of elements plus the number moved positions.
static node_ptr move_forward(node_ptr p, std::size_t n)
{
//Null shift, nothing to do
if(!n) return 0;
node_ptr first = node_traits::get_next(p);
//count() == 1 or 2, nothing to do
if(node_traits::get_next(first) == p) return 0;
//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
//the position of the new last node after the shift.
node_ptr old_last(first), next_to_it, new_last(p);
std::size_t distance = 1;
while(p != (next_to_it = node_traits::get_next(old_last))){
if(++distance > n)
new_last = node_traits::get_next(new_last);
old_last = next_to_it;
}
//If the shift was bigger or equal than the size, obtain the equivalent
//forward shifts and find the new last node.
if(distance <= n){
//Now find the equivalent forward shifts.
//Shortcut the shift with the modulo of the size of the list
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(!new_before_last_pos) return 0;
for( new_last = p
; new_before_last_pos--
; new_last = node_traits::get_next(new_last)){
//empty
}
}
//Now unlink p and link it after the new last node
base_t::unlink_after(old_last);
base_t::link_after(new_last, p);
return new_last;
}
}; };
} //namespace intrusive } //namespace intrusive

View File

@@ -0,0 +1,95 @@
/////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2007-2008
//
// 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_COMMON_SLIST_ALGORITHMS_HPP
#define BOOST_INTRUSIVE_COMMON_SLIST_ALGORITHMS_HPP
#include <boost/intrusive/detail/config_begin.hpp>
#include <boost/intrusive/intrusive_fwd.hpp>
#include <boost/intrusive/detail/assert.hpp>
#include <cstddef>
namespace boost {
namespace intrusive {
namespace detail {
template<class NodeTraits>
class common_slist_algorithms
{
public:
typedef typename NodeTraits::node_ptr node_ptr;
typedef typename NodeTraits::const_node_ptr const_node_ptr;
typedef NodeTraits node_traits;
static node_ptr get_previous_node(node_ptr prev_init_node, node_ptr this_node)
{
node_ptr p = prev_init_node;
for( node_ptr p_next
; this_node != (p_next = NodeTraits::get_next(p))
; p = p_next){
//Logic error: possible use of linear lists with
//operations only permitted with lists
BOOST_INTRUSIVE_INVARIANT_ASSERT(p);
}
return p;
}
static void init_header(node_ptr this_node)
{ NodeTraits::set_next(this_node, this_node); }
static void init(node_ptr this_node)
{ NodeTraits::set_next(this_node, 0); }
static bool unique(const_node_ptr this_node)
{
node_ptr next = NodeTraits::get_next(this_node);
return !next || next == this_node;
}
static bool inited(const_node_ptr this_node)
{ return !NodeTraits::get_next(this_node); }
static void unlink_after(node_ptr prev_node)
{
node_ptr this_node(NodeTraits::get_next(prev_node));
NodeTraits::set_next(prev_node, NodeTraits::get_next(this_node));
}
static void unlink_after(node_ptr prev_node, node_ptr last_node)
{ NodeTraits::set_next(prev_node, last_node); }
static void link_after(node_ptr prev_node, node_ptr this_node)
{
NodeTraits::set_next(this_node, NodeTraits::get_next(prev_node));
NodeTraits::set_next(prev_node, this_node);
}
static void transfer_after(node_ptr p, node_ptr b, node_ptr e)
{
if (p != b && p != e) {
node_ptr next_b = NodeTraits::get_next(b);
node_ptr next_e = NodeTraits::get_next(e);
node_ptr next_p = NodeTraits::get_next(p);
NodeTraits::set_next(b, next_e);
NodeTraits::set_next(e, next_p);
NodeTraits::set_next(p, next_b);
}
}
};
} //namespace detail
} //namespace intrusive
} //namespace boost
#include <boost/intrusive/detail/config_end.hpp>
#endif //BOOST_INTRUSIVE_COMMON_SLIST_ALGORITHMS_HPP

View File

@@ -137,9 +137,9 @@ class tree_algorithms
{ return uncast(header); } { return uncast(header); }
//! <b>Requires</b>: node is a node of the tree or an node initialized //! <b>Requires</b>: node is a node of the tree or an node initialized
//! by init(...). //! by init(...) or init_node.
//! //!
//! <b>Effects</b>: Returns true if the node is initialized by init(). //! <b>Effects</b>: Returns true if the node is initialized by init() or init_node().
//! //!
//! <b>Complexity</b>: Constant time. //! <b>Complexity</b>: Constant time.
//! //!

View File

@@ -498,7 +498,8 @@ inline std::size_t floor_log2 (std::size_t x)
inline float fast_log2 (float val) inline float fast_log2 (float val)
{ {
boost::uint32_t * const exp_ptr = reinterpret_cast <boost::uint32_t *>(&val); boost::uint32_t * exp_ptr =
static_cast<boost::uint32_t *>(static_cast<void*>(&val));
boost::uint32_t x = *exp_ptr; boost::uint32_t x = *exp_ptr;
const int log_2 = (int)(((x >> 23) & 255) - 128); const int log_2 = (int)(((x >> 23) & 255) - 128);
x &= ~(255 << 23); x &= ~(255 << 23);

View File

@@ -747,7 +747,7 @@ class hashtable_impl
} }
BOOST_INTRUSIVE_CATCH(...){ BOOST_INTRUSIVE_CATCH(...){
this->clear_and_dispose(disposer); this->clear_and_dispose(disposer);
BOOST_RETHROW; BOOST_INTRUSIVE_RETHROW;
} }
BOOST_INTRUSIVE_CATCH_END BOOST_INTRUSIVE_CATCH_END
} }

View File

@@ -69,6 +69,8 @@ template
, class O1 = none , class O1 = none
, class O2 = none , class O2 = none
, class O3 = none , class O3 = none
, class O4 = none
, class O5 = none
> >
class slist; class slist;

View File

@@ -0,0 +1,326 @@
/////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Olaf Krzikalla 2004-2006.
// (C) Copyright Ion Gaztanaga 2006-2007
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/intrusive for documentation.
//
/////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_INTRUSIVE_LINEAR_SLIST_ALGORITHMS_HPP
#define BOOST_INTRUSIVE_LINEAR_SLIST_ALGORITHMS_HPP
#include <boost/intrusive/detail/config_begin.hpp>
#include <boost/intrusive/intrusive_fwd.hpp>
#include <boost/intrusive/detail/common_slist_algorithms.hpp>
#include <cstddef>
#include <utility>
namespace boost {
namespace intrusive {
//! linear_slist_algorithms provides basic algorithms to manipulate nodes
//! forming a linear singly linked list.
//!
//! linear_slist_algorithms is configured with a NodeTraits class, which encapsulates the
//! information about the node to be manipulated. NodeTraits must support the
//! following interface:
//!
//! <b>Typedefs</b>:
//!
//! <tt>node</tt>: The type of the node that forms the linear list
//!
//! <tt>node_ptr</tt>: A pointer to a node
//!
//! <tt>const_node_ptr</tt>: A pointer to a const node
//!
//! <b>Static functions</b>:
//!
//! <tt>static node_ptr get_next(const_node_ptr n);</tt>
//!
//! <tt>static void set_next(node_ptr n, node_ptr next);</tt>
template<class NodeTraits>
class linear_slist_algorithms
/// @cond
: public detail::common_slist_algorithms<NodeTraits>
/// @endcond
{
/// @cond
typedef detail::common_slist_algorithms<NodeTraits> base_t;
/// @endcond
public:
typedef typename NodeTraits::node_ptr node_ptr;
typedef typename NodeTraits::const_node_ptr const_node_ptr;
typedef NodeTraits node_traits;
#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
//! <b>Effects</b>: Constructs an non-used list element, putting the next
//! pointer to null:
//! <tt>NodeTraits::get_next(this_node) == 0
//!
//! <b>Complexity</b>: Constant
//!
//! <b>Throws</b>: Nothing.
static void init(node_ptr this_node);
//! <b>Requires</b>: this_node must be in a circular list or be an empty circular list.
//!
//! <b>Effects</b>: Returns true is "this_node" is the only node of a circular list:
//! or it's a not inserted node:
//! <tt>return !NodeTraits::get_next(this_node) || NodeTraits::get_next(this_node) == this_node</tt>
//!
//! <b>Complexity</b>: Constant
//!
//! <b>Throws</b>: Nothing.
static bool unique(const_node_ptr this_node);
//! <b>Effects</b>: Returns true is "this_node" has the same state as if
//! it was inited using "init(node_ptr)"
//!
//! <b>Complexity</b>: Constant
//!
//! <b>Throws</b>: Nothing.
static bool inited(const_node_ptr this_node);
//! <b>Requires</b>: prev_node must be in a circular list or be an empty circular list.
//!
//! <b>Effects</b>: Unlinks the next node of prev_node from the circular list.
//!
//! <b>Complexity</b>: Constant
//!
//! <b>Throws</b>: Nothing.
static void unlink_after(node_ptr prev_node);
//! <b>Requires</b>: prev_node and last_node must be in a circular list
//! or be an empty circular list.
//!
//! <b>Effects</b>: Unlinks the range (prev_node, last_node) from the linear list.
//!
//! <b>Complexity</b>: Constant
//!
//! <b>Throws</b>: Nothing.
static void unlink_after(node_ptr prev_node, node_ptr last_node);
//! <b>Requires</b>: prev_node must be a node of a linear list.
//!
//! <b>Effects</b>: Links this_node after prev_node in the linear list.
//!
//! <b>Complexity</b>: Constant
//!
//! <b>Throws</b>: Nothing.
static void link_after(node_ptr prev_node, node_ptr this_node);
//! <b>Requires</b>: b and e must be nodes of the same linear list or an empty range.
//! and p must be a node of a different linear list.
//!
//! <b>Effects</b>: Removes the nodes from (b, e] range from their linear list and inserts
//! them after p in p's linear list.
//!
//! <b>Complexity</b>: Constant
//!
//! <b>Throws</b>: Nothing.
static void transfer_after(node_ptr p, node_ptr b, node_ptr e);
#endif //#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
//! <b>Effects</b>: Constructs an empty list, making this_node the only
//! node of the circular list:
//! <tt>NodeTraits::get_next(this_node) == this_node</tt>.
//!
//! <b>Complexity</b>: Constant
//!
//! <b>Throws</b>: Nothing.
static void init_header(node_ptr this_node)
{ NodeTraits::set_next(this_node, 0); }
//! <b>Requires</b>: this_node and prev_init_node must be in the same linear list.
//!
//! <b>Effects</b>: Returns the previous node of this_node in the linear list starting.
//! the search from prev_init_node. The first node checked for equality
//! is NodeTraits::get_next(prev_init_node).
//!
//! <b>Complexity</b>: Linear to the number of elements between prev_init_node and this_node.
//!
//! <b>Throws</b>: Nothing.
static node_ptr get_previous_node(node_ptr prev_init_node, node_ptr this_node)
{ return base_t::get_previous_node(prev_init_node, this_node); }
//! <b>Requires</b>: this_node must be in a linear list or be an empty linear list.
//!
//! <b>Effects</b>: Returns the number of nodes in a linear list. If the linear list
//! is empty, returns 1.
//!
//! <b>Complexity</b>: Constant
//!
//! <b>Throws</b>: Nothing.
static std::size_t count(const_node_ptr this_node)
{
std::size_t result = 0;
const_node_ptr p = this_node;
do{
p = NodeTraits::get_next(p);
++result;
} while (p);
return result;
}
//! <b>Requires</b>: this_node and other_node must be nodes inserted
//! in linear lists or be empty linear lists.
//!
//! <b>Effects</b>: Moves all the nodes previously chained after this_node after other_node
//! and vice-versa.
//!
//! <b>Complexity</b>: Constant
//!
//! <b>Throws</b>: Nothing.
static void swap_trailing_nodes(node_ptr this_node, node_ptr other_node)
{
node_ptr this_nxt = NodeTraits::get_next(this_node);
node_ptr other_nxt = NodeTraits::get_next(other_node);
NodeTraits::set_next(this_node, other_nxt);
NodeTraits::set_next(other_node, this_nxt);
}
//! <b>Effects</b>: Reverses the order of elements in the list.
//!
//! <b>Returns</b>: The new first node of the list.
//!
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: This function is linear to the contained elements.
static node_ptr reverse(node_ptr p)
{
if(!p) return 0;
node_ptr i = NodeTraits::get_next(p);
node_ptr first(p);
while(i){
node_ptr nxti(NodeTraits::get_next(i));
base_t::unlink_after(p);
NodeTraits::set_next(i, first);
first = i;
i = nxti;
}
return first;
}
//! <b>Effects</b>: Moves the first n nodes starting at p to the end of the list.
//!
//! <b>Returns</b>: A pair containing the new first and last node of the list or
//! if there has been any movement, a null pair if n leads to no movement.
//!
//! <b>Throws</b>: Nothing.
//!
//! <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)
{
std::pair<node_ptr, node_ptr> ret(0, 0);
//Null shift, or count() == 0 or 1, nothing to do
if(!n || !p || !NodeTraits::get_next(p)){
return ret;
}
node_ptr first = p;
bool end_found = false;
node_ptr new_last(0);
node_ptr old_last(0);
//Now find the new last node according to the shift count.
//If we find 0 before finding the new last node
//unlink p, shortcut the search now that we know the size of the list
//and continue.
for(std::size_t i = 1; i <= n; ++i){
new_last = first;
first = NodeTraits::get_next(first);
if(first == 0){
//Shortcut the shift with the modulo of the size of the list
n %= i;
if(!n) return ret;
old_last = new_last;
i = 0;
//Unlink p and continue the new first node search
first = p;
//unlink_after(new_last);
end_found = true;
}
}
//If the p has not been found in the previous loop, find it
//starting in the new first node and unlink it
if(!end_found){
old_last = base_t::get_previous_node(first, 0);
}
//Now link p after the new last node
NodeTraits::set_next(old_last, p);
NodeTraits::set_next(new_last, 0);
ret.first = first;
ret.second = new_last;
return ret;
}
//! <b>Effects</b>: Moves the first n nodes starting at p to the beginning of the list.
//!
//! <b>Returns</b>: A pair containing the new first and last node of the list or
//! if there has been any movement, a null pair if n leads to no movement.
//!
//! <b>Throws</b>: Nothing.
//!
//! <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)
{
std::pair<node_ptr, node_ptr> ret(0, 0);
//Null shift, or count() == 0 or 1, nothing to do
if(!n || !p || !NodeTraits::get_next(p))
return ret;
node_ptr first = p;
//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
//the position of the new last node after the shift.
node_ptr old_last(first), next_to_it, new_last(p);
std::size_t distance = 1;
while(!!(next_to_it = node_traits::get_next(old_last))){
if(distance++ > n)
new_last = node_traits::get_next(new_last);
old_last = next_to_it;
}
//If the shift was bigger or equal than the size, obtain the equivalent
//forward shifts and find the new last node.
if(distance <= n){
//Now find the equivalent forward shifts.
//Shortcut the shift with the modulo of the size of the list
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(!new_before_last_pos)
return ret;
for( new_last = p
; --new_before_last_pos
; new_last = node_traits::get_next(new_last)){
//empty
}
}
//Get the first new node
node_ptr new_first(node_traits::get_next(new_last));
//Now put the old beginning after the old end
NodeTraits::set_next(old_last, p);
NodeTraits::set_next(new_last, 0);
ret.first = new_first;
ret.second = new_last;
return ret;
}
};
} //namespace intrusive
} //namespace boost
#include <boost/intrusive/detail/config_end.hpp>
#endif //BOOST_INTRUSIVE_LINEAR_SLIST_ALGORITHMS_HPP

View File

@@ -208,7 +208,7 @@ class list_impl
: data_(v_traits) : data_(v_traits)
{ {
this->priv_size_traits().set_size(size_type(0)); this->priv_size_traits().set_size(size_type(0));
node_algorithms::init(this->get_root_node()); node_algorithms::init_header(this->get_root_node());
} }
//! <b>Requires</b>: Dereferencing iterator must yield an lvalue of type value_type. //! <b>Requires</b>: Dereferencing iterator must yield an lvalue of type value_type.
@@ -224,7 +224,7 @@ class list_impl
: data_(v_traits) : data_(v_traits)
{ {
this->priv_size_traits().set_size(size_type(0)); this->priv_size_traits().set_size(size_type(0));
node_algorithms::init(this->get_root_node()); node_algorithms::init_header(this->get_root_node());
this->insert(this->end(), b, e); this->insert(this->end(), b, e);
} }
@@ -258,7 +258,7 @@ class list_impl
{ {
node_ptr to_insert = get_real_value_traits().to_node_ptr(value); node_ptr to_insert = get_real_value_traits().to_node_ptr(value);
if(safemode_or_autounlink) if(safemode_or_autounlink)
BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::unique(to_insert)); BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::inited(to_insert));
node_algorithms::link_before(this->get_root_node(), to_insert); node_algorithms::link_before(this->get_root_node(), to_insert);
this->priv_size_traits().increment(); this->priv_size_traits().increment();
} }
@@ -277,7 +277,7 @@ class list_impl
{ {
node_ptr to_insert = get_real_value_traits().to_node_ptr(value); node_ptr to_insert = get_real_value_traits().to_node_ptr(value);
if(safemode_or_autounlink) if(safemode_or_autounlink)
BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::unique(to_insert)); BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::inited(to_insert));
node_algorithms::link_before(node_traits::get_next(this->get_root_node()), to_insert); node_algorithms::link_before(node_traits::get_next(this->get_root_node()), to_insert);
this->priv_size_traits().increment(); this->priv_size_traits().increment();
} }
@@ -291,13 +291,7 @@ class list_impl
//! //!
//! <b>Note</b>: Invalidates the iterators (but not the references) to the erased element. //! <b>Note</b>: Invalidates the iterators (but not the references) to the erased element.
void pop_back() void pop_back()
{ { return this->pop_back_and_dispose(detail::null_disposer()); }
node_ptr to_erase = node_traits::get_previous(this->get_root_node());
node_algorithms::unlink(to_erase);
this->priv_size_traits().decrement();
if(safemode_or_autounlink)
node_algorithms::init(to_erase);
}
//! <b>Requires</b>: Disposer::operator()(pointer) shouldn't throw. //! <b>Requires</b>: Disposer::operator()(pointer) shouldn't throw.
//! //!
@@ -330,13 +324,7 @@ class list_impl
//! //!
//! <b>Note</b>: Invalidates the iterators (but not the references) to the erased element. //! <b>Note</b>: Invalidates the iterators (but not the references) to the erased element.
void pop_front() void pop_front()
{ { return this->pop_front_and_dispose(detail::null_disposer()); }
node_ptr to_erase = node_traits::get_next(this->get_root_node());
node_algorithms::unlink(to_erase);
this->priv_size_traits().decrement();
if(safemode_or_autounlink)
node_algorithms::init(to_erase);
}
//! <b>Requires</b>: Disposer::operator()(pointer) shouldn't throw. //! <b>Requires</b>: Disposer::operator()(pointer) shouldn't throw.
//! //!
@@ -406,7 +394,7 @@ class list_impl
//! //!
//! <b>Complexity</b>: Constant. //! <b>Complexity</b>: Constant.
const_iterator begin() const const_iterator begin() const
{ return cbegin(); } { return this->cbegin(); }
//! <b>Effects</b>: Returns a const_iterator to the first element contained in the list. //! <b>Effects</b>: Returns a const_iterator to the first element contained in the list.
//! //!
@@ -430,7 +418,7 @@ class list_impl
//! //!
//! <b>Complexity</b>: Constant. //! <b>Complexity</b>: Constant.
const_iterator end() const const_iterator end() const
{ return cend(); } { return this->cend(); }
//! <b>Effects</b>: Returns a constant iterator to the end of the list. //! <b>Effects</b>: Returns a constant iterator to the end of the list.
//! //!
@@ -447,7 +435,7 @@ class list_impl
//! //!
//! <b>Complexity</b>: Constant. //! <b>Complexity</b>: Constant.
reverse_iterator rbegin() reverse_iterator rbegin()
{ return reverse_iterator(end()); } { return reverse_iterator(this->end()); }
//! <b>Effects</b>: Returns a const_reverse_iterator pointing to the beginning //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the beginning
//! of the reversed list. //! of the reversed list.
@@ -456,7 +444,7 @@ class list_impl
//! //!
//! <b>Complexity</b>: Constant. //! <b>Complexity</b>: Constant.
const_reverse_iterator rbegin() const const_reverse_iterator rbegin() const
{ return crbegin(); } { return this->crbegin(); }
//! <b>Effects</b>: Returns a const_reverse_iterator pointing to the beginning //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the beginning
//! of the reversed list. //! of the reversed list.
@@ -483,7 +471,7 @@ class list_impl
//! //!
//! <b>Complexity</b>: Constant. //! <b>Complexity</b>: Constant.
const_reverse_iterator rend() const const_reverse_iterator rend() const
{ return crend(); } { return this->crend(); }
//! <b>Effects</b>: Returns a const_reverse_iterator pointing to the end //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the end
//! of the reversed list. //! of the reversed list.
@@ -492,7 +480,7 @@ class list_impl
//! //!
//! <b>Complexity</b>: Constant. //! <b>Complexity</b>: Constant.
const_reverse_iterator crend() const const_reverse_iterator crend() const
{ return const_reverse_iterator(begin()); } { return const_reverse_iterator(this->begin()); }
//! <b>Precondition</b>: end_iterator must be a valid end iterator //! <b>Precondition</b>: end_iterator must be a valid end iterator
//! of list. //! of list.
@@ -503,7 +491,7 @@ class list_impl
//! //!
//! <b>Complexity</b>: Constant. //! <b>Complexity</b>: Constant.
static list_impl &container_from_end_iterator(iterator end_iterator) static list_impl &container_from_end_iterator(iterator end_iterator)
{ return priv_container_from_end_iterator(end_iterator); } { return list_impl::priv_container_from_end_iterator(end_iterator); }
//! <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 list. //! of list.
@@ -514,7 +502,7 @@ class list_impl
//! //!
//! <b>Complexity</b>: Constant. //! <b>Complexity</b>: Constant.
static const list_impl &container_from_end_iterator(const_iterator end_iterator) static const list_impl &container_from_end_iterator(const_iterator end_iterator)
{ return priv_container_from_end_iterator(end_iterator); } { return list_impl::priv_container_from_end_iterator(end_iterator); }
//! <b>Effects</b>: Returns the number of the elements contained in the list. //! <b>Effects</b>: Returns the number of the elements contained in the list.
//! //!
@@ -569,21 +557,7 @@ class list_impl
//! //!
//! <b>Note</b>: Does not affect the validity of iterators and references. //! <b>Note</b>: Does not affect the validity of iterators and references.
void shift_backwards(size_type n = 1) void shift_backwards(size_type n = 1)
{ { node_algorithms::move_forward(this->get_root_node(), n); }
//Null shift, nothing to do
if(!n) return;
node_ptr root = this->get_root_node();
node_ptr last = node_traits::get_previous(root);
//size() == 0 or 1, nothing to do
if(last == node_traits::get_next(root)) return;
node_algorithms::unlink(root);
//Now get the new last node
while(n--){
last = node_traits::get_previous(last);
}
node_algorithms::link_after(last, root);
}
//! <b>Effects</b>: Moves forward all the elements, so that the second //! <b>Effects</b>: Moves forward all the elements, so that the second
//! element becomes the first, the third becomes the second... //! element becomes the first, the third becomes the second...
@@ -595,20 +569,7 @@ class list_impl
//! //!
//! <b>Note</b>: Does not affect the validity of iterators and references. //! <b>Note</b>: Does not affect the validity of iterators and references.
void shift_forward(size_type n = 1) void shift_forward(size_type n = 1)
{ { node_algorithms::move_backwards(this->get_root_node(), n); }
//Null shift, nothing to do
if(!n) return;
node_ptr root = this->get_root_node();
node_ptr first = node_traits::get_next(root);
//size() == 0 or 1, nothing to do
if(first == node_traits::get_previous(root)) return;
node_algorithms::unlink(root);
//Now get the new first node
while(n--){
first = node_traits::get_next(first);
}
node_algorithms::link_before(first, root);
}
//! <b>Effects</b>: Erases the element pointed by i of the list. //! <b>Effects</b>: Erases the element pointed by i of the list.
//! No destructors are called. //! No destructors are called.
@@ -623,16 +584,7 @@ class list_impl
//! <b>Note</b>: Invalidates the iterators (but not the references) to the //! <b>Note</b>: Invalidates the iterators (but not the references) to the
//! erased element. //! erased element.
iterator erase(iterator i) iterator erase(iterator i)
{ { return this->erase_and_dispose(i, detail::null_disposer()); }
iterator erase = i;
++i;
node_ptr to_erase = erase.pointed_node();
node_algorithms::unlink(to_erase);
this->priv_size_traits().decrement();
if(safemode_or_autounlink)
node_algorithms::init(to_erase);
return i;
}
//! <b>Requires</b>: first and last must be valid iterator to elements in *this. //! <b>Requires</b>: first and last must be valid iterator to elements in *this.
//! //!
@@ -652,10 +604,7 @@ class list_impl
iterator erase(iterator b, iterator e) iterator erase(iterator b, iterator e)
{ {
if(safemode_or_autounlink || constant_time_size){ if(safemode_or_autounlink || constant_time_size){
while(b != e){ return this->erase_and_dispose(b, e, detail::null_disposer());
b = this->erase(b);
}
return b;
} }
else{ else{
node_algorithms::unlink(b.pointed_node(), e.pointed_node()); node_algorithms::unlink(b.pointed_node(), e.pointed_node());
@@ -680,14 +629,13 @@ class list_impl
template <class Disposer> template <class Disposer>
iterator erase_and_dispose(iterator i, Disposer disposer) iterator erase_and_dispose(iterator i, Disposer disposer)
{ {
iterator erase = i; node_ptr to_erase(i.pointed_node());
++i; ++i;
node_ptr to_erase = erase.pointed_node();
node_algorithms::unlink(to_erase); node_algorithms::unlink(to_erase);
this->priv_size_traits().decrement(); 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(this->get_real_value_traits().to_value_ptr(to_erase));
return i; return i;
} }
@@ -708,10 +656,17 @@ class list_impl
template <class Disposer> template <class Disposer>
iterator erase_and_dispose(iterator b, iterator e, Disposer disposer) iterator erase_and_dispose(iterator b, iterator e, Disposer disposer)
{ {
while(b != e){ node_ptr bp(b.pointed_node()), ep(e.pointed_node());
b = this->erase_and_dispose(b, disposer); node_algorithms::unlink(bp, ep);
while(bp != ep){
node_ptr to_erase(bp);
bp = node_traits::get_next(bp);
if(safemode_or_autounlink)
node_algorithms::init(to_erase);
disposer(get_real_value_traits().to_value_ptr(to_erase));
this->priv_size_traits().decrement();
} }
return b; return e;
} }
//! <b>Effects</b>: Erases all the elements of the container. //! <b>Effects</b>: Erases all the elements of the container.
@@ -726,10 +681,10 @@ class list_impl
void clear() void clear()
{ {
if(safemode_or_autounlink){ if(safemode_or_autounlink){
this->erase(this->begin(), this->end()); this->clear_and_dispose(detail::null_disposer());
} }
else{ else{
node_algorithms::init(this->get_root_node()); node_algorithms::init_header(this->get_root_node());
this->priv_size_traits().set_size(size_type(0)); this->priv_size_traits().set_size(size_type(0));
} }
} }
@@ -747,7 +702,18 @@ class list_impl
//! <b>Note</b>: Invalidates the iterators to the erased elements. //! <b>Note</b>: Invalidates the iterators to the erased elements.
template <class Disposer> template <class Disposer>
void clear_and_dispose(Disposer disposer) void clear_and_dispose(Disposer disposer)
{ this->erase_and_dispose(this->begin(), this->end(), disposer); } {
iterator it(this->begin()), itend(this->end());
while(it != itend){
node_ptr to_erase(it.pointed_node());
++it;
if(safemode_or_autounlink)
node_algorithms::init(to_erase);
disposer(get_real_value_traits().to_value_ptr(to_erase));
}
node_algorithms::init_header(this->get_root_node());
this->priv_size_traits().set_size(0);
}
//! <b>Requires</b>: Disposer::operator()(pointer) shouldn't throw. //! <b>Requires</b>: Disposer::operator()(pointer) shouldn't throw.
//! //!
@@ -792,9 +758,9 @@ class list_impl
//! <b>Note</b>: Does not affect the validity of iterators and references. //! <b>Note</b>: Does not affect the validity of iterators and references.
iterator insert(iterator p, reference value) iterator insert(iterator p, reference value)
{ {
node_ptr to_insert = get_real_value_traits().to_node_ptr(value); node_ptr to_insert = this->get_real_value_traits().to_node_ptr(value);
if(safemode_or_autounlink) if(safemode_or_autounlink)
BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::unique(to_insert)); BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::inited(to_insert));
node_algorithms::link_before(p.pointed_node(), to_insert); node_algorithms::link_before(p.pointed_node(), to_insert);
this->priv_size_traits().increment(); this->priv_size_traits().increment();
return iterator(to_insert, this); return iterator(to_insert, this);
@@ -921,19 +887,10 @@ class list_impl
//! list. Iterators of this list and all the references are not invalidated. //! list. Iterators of this list and all the references are not invalidated.
void splice(iterator p, list_impl&x, iterator start, iterator end) void splice(iterator p, list_impl&x, iterator start, iterator end)
{ {
if(start != end){ if(constant_time_size)
if(constant_time_size){ this->splice(p, x, start, end, std::distance(start, end));
size_traits &thist = this->priv_size_traits(); else
size_traits &xt = x.priv_size_traits(); this->splice(p, x, start, end, 1);//distance is a dummy value
size_type increment = std::distance(start, end);
node_algorithms::transfer(p.pointed_node(), start.pointed_node(), end.pointed_node());
thist.set_size(thist.get_size() + increment);
xt.set_size(xt.get_size() - increment);
}
else{
node_algorithms::transfer(p.pointed_node(), start.pointed_node(), end.pointed_node());
}
}
} }
//! <b>Requires</b>: p must be a valid iterator of *this. //! <b>Requires</b>: p must be a valid iterator of *this.
@@ -978,7 +935,7 @@ class list_impl
//! <b>Complexity</b>: The number of comparisons is approximately N log N, where N //! <b>Complexity</b>: The number of comparisons is approximately N log N, where N
//! is the list's size. //! is the list's size.
void sort() void sort()
{ sort(std::less<value_type>()); } { this->sort(std::less<value_type>()); }
//! <b>Requires</b>: p must be a comparison function that induces a strict weak ordering //! <b>Requires</b>: p must be a comparison function that induces a strict weak ordering
//! //!
@@ -1031,7 +988,7 @@ class list_impl
//! //!
//! <b>Note</b>: Iterators and references are not invalidated //! <b>Note</b>: Iterators and references are not invalidated
void merge(list_impl& x) void merge(list_impl& x)
{ merge(x, std::less<value_type>()); } { this->merge(x, std::less<value_type>()); }
//! <b>Requires</b>: p must be a comparison function that induces a strict weak //! <b>Requires</b>: p must be a comparison function that induces a strict weak
//! ordering and both *this and x must be sorted according to that ordering //! ordering and both *this and x must be sorted according to that ordering
@@ -1050,9 +1007,9 @@ class list_impl
template<class Predicate> template<class Predicate>
void merge(list_impl& x, Predicate p) void merge(list_impl& x, Predicate p)
{ {
iterator e = this->end(); iterator e(this->end());
iterator bx = x.begin(); iterator bx(x.begin());
iterator ex = x.end(); iterator ex(x.end());
for (iterator b = this->begin(); b != e; ++b) { for (iterator b = this->begin(); b != e; ++b) {
size_type n(0); size_type n(0);
@@ -1087,7 +1044,7 @@ class list_impl
//! <b>Note</b>: The relative order of elements that are not removed is unchanged, //! <b>Note</b>: The relative order of elements that are not removed is unchanged,
//! and iterators to elements that are not removed remain valid. //! and iterators to elements that are not removed remain valid.
void remove(const_reference value) void remove(const_reference value)
{ remove_if(detail::equal_to_value<const_reference>(value)); } { this->remove_if(detail::equal_to_value<const_reference>(value)); }
//! <b>Requires</b>: Disposer::operator()(pointer) shouldn't throw. //! <b>Requires</b>: Disposer::operator()(pointer) shouldn't throw.
//! //!
@@ -1102,7 +1059,7 @@ class list_impl
//! and iterators to elements that are not removed remain valid. //! and iterators to elements that are not removed remain valid.
template<class Disposer> template<class Disposer>
void remove_and_dispose(const_reference value, Disposer disposer) void remove_and_dispose(const_reference value, Disposer disposer)
{ remove_and_dispose_if(detail::equal_to_value<const_reference>(value), disposer); } { this->remove_and_dispose_if(detail::equal_to_value<const_reference>(value), disposer); }
//! <b>Effects</b>: Removes all the elements for which a specified //! <b>Effects</b>: Removes all the elements for which a specified
//! predicate is satisfied. No destructors are called. //! predicate is satisfied. No destructors are called.
@@ -1115,7 +1072,7 @@ class list_impl
//! and iterators to elements that are not removed remain valid. //! and iterators to elements that are not removed remain valid.
template<class Pred> template<class Pred>
void remove_if(Pred pred) void remove_if(Pred pred)
{ remove_and_dispose_if(pred, detail::null_disposer()); } { this->remove_and_dispose_if(pred, detail::null_disposer()); }
//! <b>Requires</b>: Disposer::operator()(pointer) shouldn't throw. //! <b>Requires</b>: Disposer::operator()(pointer) shouldn't throw.
//! //!
@@ -1132,17 +1089,15 @@ class list_impl
template<class Pred, class Disposer> template<class Pred, class Disposer>
void remove_and_dispose_if(Pred pred, Disposer disposer) void remove_and_dispose_if(Pred pred, Disposer disposer)
{ {
iterator first = begin(); iterator cur(this->begin());
iterator last = end(); iterator last(this->end());
while(first != last) { while(cur != last) {
iterator next = first; if(pred(*cur)){
++next; cur = this->erase_and_dispose(cur, disposer);
if(pred(*first)){ }
pointer p = first.operator->(); else{
this->erase(first); ++cur;
disposer(p);
} }
first = next;
} }
} }
@@ -1156,7 +1111,7 @@ class list_impl
//! <b>Note</b>: The relative order of elements that are not removed is unchanged, //! <b>Note</b>: The relative order of elements that are not removed is unchanged,
//! and iterators to elements that are not removed remain valid. //! and iterators to elements that are not removed remain valid.
void unique() void unique()
{ unique_and_dispose(std::equal_to<value_type>(), detail::null_disposer()); } { this->unique_and_dispose(std::equal_to<value_type>(), detail::null_disposer()); }
//! <b>Effects</b>: Removes adjacent duplicate elements or adjacent //! <b>Effects</b>: Removes adjacent duplicate elements or adjacent
//! elements that satisfy some binary predicate from the list. //! elements that satisfy some binary predicate from the list.
@@ -1170,7 +1125,7 @@ class list_impl
//! and iterators to elements that are not removed remain valid. //! and iterators to elements that are not removed remain valid.
template<class BinaryPredicate> template<class BinaryPredicate>
void unique(BinaryPredicate pred) void unique(BinaryPredicate pred)
{ unique_and_dispose(pred, detail::null_disposer()); } { this->unique_and_dispose(pred, detail::null_disposer()); }
//! <b>Requires</b>: Disposer::operator()(pointer) shouldn't throw. //! <b>Requires</b>: Disposer::operator()(pointer) shouldn't throw.
//! //!
@@ -1186,7 +1141,7 @@ class list_impl
//! and iterators to elements that are not removed remain valid. //! and iterators to elements that are not removed remain valid.
template<class Disposer> template<class Disposer>
void unique_and_dispose(Disposer disposer) void unique_and_dispose(Disposer disposer)
{ unique_and_dispose(std::equal_to<value_type>(), disposer); } { this->unique_and_dispose(std::equal_to<value_type>(), disposer); }
//! <b>Requires</b>: Disposer::operator()(pointer) shouldn't throw. //! <b>Requires</b>: Disposer::operator()(pointer) shouldn't throw.
//! //!
@@ -1203,18 +1158,19 @@ class list_impl
template<class BinaryPredicate, class Disposer> template<class BinaryPredicate, class Disposer>
void unique_and_dispose(BinaryPredicate pred, Disposer disposer) void unique_and_dispose(BinaryPredicate pred, Disposer disposer)
{ {
if(!this->empty()){ iterator itend(this->end());
iterator first = begin(); iterator cur(this->begin());
iterator after = first;
if(cur != itend){
iterator after(cur);
++after; ++after;
while(after != this->end()){ while(after != itend){
if(pred(*first, *after)){ if(pred(*cur, *after)){
pointer p = after.operator->(); after = this->erase_and_dispose(after, disposer);
after = erase(after);
disposer(p);
} }
else{ else{
first = after++; cur = after;
++after;
} }
} }
} }
@@ -1234,7 +1190,7 @@ class list_impl
static iterator s_iterator_to(reference value) static iterator s_iterator_to(reference value)
{ {
BOOST_STATIC_ASSERT((!stateful_value_traits)); BOOST_STATIC_ASSERT((!stateful_value_traits));
BOOST_INTRUSIVE_INVARIANT_ASSERT(!node_algorithms::unique(real_value_traits::to_node_ptr(value))); BOOST_INTRUSIVE_INVARIANT_ASSERT(!node_algorithms::inited(real_value_traits::to_node_ptr(value)));
return iterator(real_value_traits::to_node_ptr(value), 0); return iterator(real_value_traits::to_node_ptr(value), 0);
} }
@@ -1252,7 +1208,7 @@ class list_impl
static const_iterator s_iterator_to(const_reference value) static const_iterator s_iterator_to(const_reference value)
{ {
BOOST_STATIC_ASSERT((!stateful_value_traits)); BOOST_STATIC_ASSERT((!stateful_value_traits));
BOOST_INTRUSIVE_INVARIANT_ASSERT(!node_algorithms::unique(real_value_traits::to_node_ptr(const_cast<reference> (value)))); BOOST_INTRUSIVE_INVARIANT_ASSERT(!node_algorithms::inited(real_value_traits::to_node_ptr(const_cast<reference> (value))));
return const_iterator(real_value_traits::to_node_ptr(const_cast<reference> (value)), 0); return const_iterator(real_value_traits::to_node_ptr(const_cast<reference> (value)), 0);
} }
@@ -1267,7 +1223,7 @@ class list_impl
//! <b>Note</b>: Iterators and references are not invalidated. //! <b>Note</b>: Iterators and references are not invalidated.
iterator iterator_to(reference value) iterator iterator_to(reference value)
{ {
BOOST_INTRUSIVE_INVARIANT_ASSERT(!node_algorithms::unique(real_value_traits::to_node_ptr(value))); BOOST_INTRUSIVE_INVARIANT_ASSERT(!node_algorithms::inited(real_value_traits::to_node_ptr(value)));
return iterator(real_value_traits::to_node_ptr(value), this); return iterator(real_value_traits::to_node_ptr(value), this);
} }
@@ -1282,7 +1238,7 @@ class list_impl
//! <b>Note</b>: Iterators and references are not invalidated. //! <b>Note</b>: Iterators and references are not invalidated.
const_iterator iterator_to(const_reference value) const const_iterator iterator_to(const_reference value) const
{ {
BOOST_INTRUSIVE_INVARIANT_ASSERT(!node_algorithms::unique(real_value_traits::to_node_ptr(const_cast<reference> (value)))); BOOST_INTRUSIVE_INVARIANT_ASSERT(!node_algorithms::inited(real_value_traits::to_node_ptr(const_cast<reference> (value))));
return const_iterator(real_value_traits::to_node_ptr(const_cast<reference> (value)), this); return const_iterator(real_value_traits::to_node_ptr(const_cast<reference> (value)), this);
} }

View File

@@ -318,10 +318,8 @@ struct tag
/// @endcond /// @endcond
}; };
//!This option setter specifies the type of //!This option setter specifies the link mode
//!a void pointer. This will instruct the hook //!(normal_link, safe_link or auto_unlink)
//!to use this type of pointer instead of the
//!default one
template<link_mode_type LinkType> template<link_mode_type LinkType>
struct link_mode struct link_mode
{ {
@@ -334,10 +332,8 @@ struct link_mode
/// @endcond /// @endcond
}; };
//!This option setter specifies the type of //!This option setter specifies if the hook
//!a void pointer. This will instruct the hook //!should be optimized for size instead of for speed.
//!to use this type of pointer instead of the
//!default one
template<bool Enabled> template<bool Enabled>
struct optimize_size struct optimize_size
{ {
@@ -350,6 +346,34 @@ struct optimize_size
/// @endcond /// @endcond
}; };
//!This option setter specifies if the list container should
//!use a linear implementation instead of a circular one.
template<bool Enabled>
struct linear
{
/// @cond
template<class Base>
struct pack : Base
{
static const bool linear = Enabled;
};
/// @endcond
};
//!This option setter specifies if the list container should
//!use a linear implementation instead of a circular one.
template<bool Enabled>
struct cache_last
{
/// @cond
template<class Base>
struct pack : Base
{
static const bool cache_last = Enabled;
};
/// @endcond
};
//!This option setter specifies the bucket traits //!This option setter specifies the bucket traits
//!class for unordered associative containers. When this option is specified, //!class for unordered associative containers. When this option is specified,
//!instead of using the default bucket traits, a user defined holder will be defined //!instead of using the default bucket traits, a user defined holder will be defined
@@ -475,6 +499,7 @@ struct hook_defaults
, tag<default_tag> , tag<default_tag>
, optimize_size<false> , optimize_size<false>
, store_hash<false> , store_hash<false>
, linear<false>
>::type >::type
{}; {};

File diff suppressed because it is too large Load Diff

View File

@@ -19,6 +19,7 @@
#include <boost/intrusive/detail/utilities.hpp> #include <boost/intrusive/detail/utilities.hpp>
#include <boost/intrusive/detail/slist_node.hpp> #include <boost/intrusive/detail/slist_node.hpp>
#include <boost/intrusive/circular_slist_algorithms.hpp> #include <boost/intrusive/circular_slist_algorithms.hpp>
#include <boost/intrusive/link_mode.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>
@@ -31,6 +32,7 @@ struct get_slist_node_algo
{ {
typedef circular_slist_algorithms<slist_node_traits<VoidPointer> > type; typedef circular_slist_algorithms<slist_node_traits<VoidPointer> > type;
}; };
/// @endcond /// @endcond
//! Helper metafunction to define a \c slist_base_hook that yields to the same //! Helper metafunction to define a \c slist_base_hook that yields to the same

View File

@@ -135,6 +135,9 @@
<File <File
RelativePath="..\..\..\..\..\boost\intrusive\intrusive_fwd.hpp"> RelativePath="..\..\..\..\..\boost\intrusive\intrusive_fwd.hpp">
</File> </File>
<File
RelativePath="..\..\..\..\..\boost\intrusive\linear_slist_algorithms.hpp">
</File>
<File <File
RelativePath="..\..\..\..\..\boost\intrusive\link_mode.hpp"> RelativePath="..\..\..\..\..\boost\intrusive\link_mode.hpp">
</File> </File>
@@ -213,6 +216,9 @@
<File <File
RelativePath="..\..\..\..\..\boost\intrusive\detail\avltree_node.hpp"> RelativePath="..\..\..\..\..\boost\intrusive\detail\avltree_node.hpp">
</File> </File>
<File
RelativePath="..\..\..\..\..\boost\intrusive\detail\common_slist_algorithms.hpp">
</File>
<File <File
RelativePath="..\..\..\..\..\boost\intrusive\detail\config_begin.hpp"> RelativePath="..\..\..\..\..\boost\intrusive\detail\config_begin.hpp">
</File> </File>

View File

@@ -1,7 +0,0 @@
add includes needed for the snippets
add section explaining splice(...,n)
Faltar<EFBFBD>a, en mi opini<6E>n, una gu<67>a de qu<71> headers incluyen a cu<63>les. P.ej.,
los *_hook.hpp t<>picamente est<73>n incluidos por el header del contenedor asociado, etc.
Add resize() to list
Optimize rehash for when shrinking: there is no need to hash the values.
Optimize store_hash<true> to work with the same node and type traits as store_hash<false>

View File

@@ -237,7 +237,7 @@ struct testvalue
// have to be handled appropriately when copied: // have to be handled appropriately when copied:
testvalue & operator= (const testvalue& src) testvalue & operator= (const testvalue& src)
{ {/*
set_base_hook_t::operator=(src); set_base_hook_t::operator=(src);
set_auto_base_hook_t::operator=(src); set_auto_base_hook_t::operator=(src);
this->set_node_ = src.set_node_; this->set_node_ = src.set_node_;
@@ -270,7 +270,7 @@ struct testvalue
slist_auto_base_hook_t::operator=(src); slist_auto_base_hook_t::operator=(src);
this->slist_node_ = src.slist_node_; this->slist_node_ = src.slist_node_;
this->slist_auto_node_ = src.slist_auto_node_; this->slist_auto_node_ = src.slist_auto_node_;
*/
value_ = src.value_; value_ = src.value_;
return *this; return *this;
} }
@@ -366,6 +366,14 @@ struct even_odd
} }
}; };
struct is_even
{
template<class VoidPointer, bool constant_time_size>
bool operator()
(const testvalue<VoidPointer, constant_time_size>& v1) const
{ return (v1.value_ & 1) == 0; }
};
} //namespace boost{ } //namespace boost{
} //namespace intrusive{ } //namespace intrusive{

View File

@@ -31,6 +31,8 @@ struct test_list
static void test_all(std::vector<value_type>& values); static void test_all(std::vector<value_type>& values);
static void test_front_back(std::vector<value_type>& values); static void test_front_back(std::vector<value_type>& values);
static void test_sort(std::vector<value_type>& values); static void test_sort(std::vector<value_type>& values);
static void test_merge(std::vector<value_type>& values);
static void test_remove_unique(std::vector<value_type>& values);
static void test_insert(std::vector<value_type>& values); static void test_insert(std::vector<value_type>& values);
static void test_shift(std::vector<value_type>& values); static void test_shift(std::vector<value_type>& values);
static void test_swap(std::vector<value_type>& values); static void test_swap(std::vector<value_type>& values);
@@ -58,19 +60,13 @@ void test_list<ValueTraits>::test_all(std::vector<typename ValueTraits::value_ty
test_front_back(values); test_front_back(values);
test_sort(values); test_sort(values);
test_merge(values);
test_remove_unique(values);
test_insert(values); test_insert(values);
test_shift(values); test_shift(values);
test_swap(values); test_swap(values);
test_clone(values); test_clone(values);
test_container_from_end(values); test_container_from_end(values);
/*
const char *list_name = typeid(list_type).name();
std::cout << list_name << std::endl << strlen(list_name) << std::endl;
const char *value_t = typeid(typename list_type::value_traits).name();
std::cout << value_t << std::endl << strlen(value_t) << std::endl;
const char *list_it_name = typeid(typename list_type::iterator).name();
std::cout << list_it_name << std::endl << strlen(list_it_name ) << std::endl;
*/
} }
//test: push_front, pop_front, push_back, pop_back, front, back, size, empty: //test: push_front, pop_front, push_back, pop_back, front, back, size, empty:
@@ -135,6 +131,60 @@ void test_list<ValueTraits>
TEST_INTRUSIVE_SEQUENCE( init_values, testlist.begin() ); } TEST_INTRUSIVE_SEQUENCE( init_values, testlist.begin() ); }
} }
//test: merge due to error in merge implementation:
template<class ValueTraits>
void test_list<ValueTraits>
::test_remove_unique (std::vector<typename ValueTraits::value_type>& values)
{
typedef typename ValueTraits::value_type value_type;
typedef list
< value_type
, value_traits<ValueTraits>
, size_type<std::size_t>
, constant_time_size<value_type::constant_time_size>
> list_type;
{
list_type list(values.begin(), values.end());
list.remove_if(is_even());
int init_values [] = { 1, 3, 5 };
TEST_INTRUSIVE_SEQUENCE( init_values, list.begin() );
}
{
std::vector<typename ValueTraits::value_type> values2(values);
list_type list(values.begin(), values.end());
list.insert(list.end(), values2.begin(), values2.end());
list.sort();
int init_values [] = { 1, 1, 2, 2, 3, 3, 4, 4, 5, 5 };
TEST_INTRUSIVE_SEQUENCE( init_values, list.begin() );
list.unique();
int init_values2 [] = { 1, 2, 3, 4, 5 };
TEST_INTRUSIVE_SEQUENCE( init_values2, list.begin() );
}
}
//test: merge due to error in merge implementation:
template<class ValueTraits>
void test_list<ValueTraits>
::test_merge (std::vector<typename ValueTraits::value_type>& values)
{
typedef typename ValueTraits::value_type value_type;
typedef list
< value_type
, value_traits<ValueTraits>
, size_type<std::size_t>
, constant_time_size<value_type::constant_time_size>
> list_type;
list_type testlist1, testlist2;
testlist1.push_front (values[0]);
testlist2.push_front (values[4]);
testlist2.push_front (values[3]);
testlist2.push_front (values[2]);
testlist1.merge (testlist2);
int init_values [] = { 1, 3, 4, 5 };
TEST_INTRUSIVE_SEQUENCE( init_values, testlist1.begin() );
}
//test: assign, insert, const_iterator, const_reverse_iterator, erase, s_iterator_to: //test: assign, insert, const_iterator, const_reverse_iterator, erase, s_iterator_to:
template<class ValueTraits> template<class ValueTraits>
void test_list<ValueTraits> void test_list<ValueTraits>
@@ -194,27 +244,30 @@ void test_list<ValueTraits>
const int num_values = (int)values.size(); const int num_values = (int)values.size();
std::vector<int> expected_values(num_values); std::vector<int> expected_values(num_values);
for(int s = 1; s <= num_values; ++s){
expected_values.resize(s);
//Shift forward all possible positions 3 times //Shift forward all possible positions 3 times
for(int i = 0; i < num_values*3; ++i){ for(int i = 0; i < s*3; ++i){
testlist.assign(values.begin(), values.end()); testlist.insert(testlist.begin(), &values[0], &values[0] + s);
testlist.shift_forward(i); testlist.shift_forward(i);
for(int j = 0; j < num_values; ++j){ for(int j = 0; j < s; ++j){
expected_values[(j + num_values - i%num_values) % num_values] = (j + 1); expected_values[(j + s - i%s) % s] = (j + 1);
} }
TEST_INTRUSIVE_SEQUENCE_EXPECTED(expected_values, testlist.begin()); TEST_INTRUSIVE_SEQUENCE_EXPECTED(expected_values, testlist.begin());
testlist.clear(); testlist.clear();
} }
//Shift backwards all possible positions //Shift backwards all possible positions
for(int i = 0; i < num_values*3; ++i){ for(int i = 0; i < s*3; ++i){
testlist.assign(values.begin(), values.end()); testlist.insert(testlist.begin(), &values[0], &values[0] + s);
testlist.shift_backwards(i); testlist.shift_backwards(i);
for(int j = 0; j < num_values; ++j){ for(int j = 0; j < s; ++j){
expected_values[(j + i) % num_values] = (j + 1); expected_values[(j + i) % s] = (j + 1);
} }
TEST_INTRUSIVE_SEQUENCE_EXPECTED(expected_values, testlist.begin()); TEST_INTRUSIVE_SEQUENCE_EXPECTED(expected_values, testlist.begin());
testlist.clear(); testlist.clear();
} }
}
} }
//test: insert (seq-version), swap, splice, erase (seq-version): //test: insert (seq-version), swap, splice, erase (seq-version):
@@ -278,6 +331,28 @@ void test_list<ValueTraits>
{ int init_values [] = { 4, 3 }; { int init_values [] = { 4, 3 };
TEST_INTRUSIVE_SEQUENCE( init_values, testlist2.begin() ); } TEST_INTRUSIVE_SEQUENCE( init_values, testlist2.begin() ); }
} }
{
list_type testlist1 (&values[0], &values[1]);
{ int init_values [] = { 1 };
TEST_INTRUSIVE_SEQUENCE( init_values, testlist1.begin() ); }
values[1].swap_nodes(values[2]);
{ int init_values [] = { 1 };
TEST_INTRUSIVE_SEQUENCE( init_values, testlist1.begin() ); }
values[0].swap_nodes(values[2]);
{ int init_values [] = { 3 };
TEST_INTRUSIVE_SEQUENCE( init_values, testlist1.begin() ); }
values[0].swap_nodes(values[2]);
{ int init_values [] = { 1 };
TEST_INTRUSIVE_SEQUENCE( init_values, testlist1.begin() ); }
}
} }
template<class ValueTraits> template<class ValueTraits>

View File

@@ -24,24 +24,28 @@
using namespace boost::intrusive; using namespace boost::intrusive;
template<class ValueTraits> template<class ValueTraits, bool Linear, bool CacheLast>
struct test_slist struct test_slist
{ {
typedef typename ValueTraits::value_type value_type; typedef typename ValueTraits::value_type value_type;
static void test_all (std::vector<value_type>& values); static void test_all(std::vector<value_type>& values);
static void test_front_back (std::vector<value_type>& values); static void test_front(std::vector<value_type>& values);
static void test_back(std::vector<value_type>& values, detail::bool_<true>);
static void test_back(std::vector<value_type>& values, detail::bool_<false>);
static void test_sort(std::vector<value_type>& values); static void test_sort(std::vector<value_type>& values);
static void test_merge (std::vector<value_type>& values); static void test_merge(std::vector<value_type>& values);
static void test_remove_unique(std::vector<value_type>& values);
static void test_insert(std::vector<value_type>& values); static void test_insert(std::vector<value_type>& values);
static void test_shift(std::vector<value_type>& values); static void test_shift(std::vector<value_type>& values);
static void test_swap(std::vector<value_type>& values); static void test_swap(std::vector<value_type>& values);
static void test_slow_insert (std::vector<value_type>& values); static void test_slow_insert(std::vector<value_type>& values);
static void test_clone (std::vector<value_type>& values); static void test_clone(std::vector<value_type>& values);
static void test_container_from_end(std::vector<value_type> &values); static void test_container_from_end(std::vector<value_type> &, detail::bool_<true>){}
static void test_container_from_end(std::vector<value_type> &values, detail::bool_<false>);
}; };
template<class ValueTraits> template<class ValueTraits, bool Linear, bool CacheLast>
void test_slist<ValueTraits> void test_slist<ValueTraits, Linear, CacheLast>
::test_all (std::vector<typename ValueTraits::value_type>& values) ::test_all (std::vector<typename ValueTraits::value_type>& values)
{ {
typedef typename ValueTraits::value_type value_type; typedef typename ValueTraits::value_type value_type;
@@ -50,6 +54,8 @@ void test_slist<ValueTraits>
, value_traits<ValueTraits> , value_traits<ValueTraits>
, size_type<std::size_t> , size_type<std::size_t>
, constant_time_size<value_type::constant_time_size> , constant_time_size<value_type::constant_time_size>
, linear<Linear>
, cache_last<CacheLast>
> list_type; > list_type;
{ {
list_type list(values.begin(), values.end()); list_type list(values.begin(), values.end());
@@ -58,21 +64,23 @@ void test_slist<ValueTraits>
list.insert(list.end(), values.begin(), values.end()); list.insert(list.end(), values.begin(), values.end());
test::test_sequence_container(list, values); test::test_sequence_container(list, values);
} }
test_front_back (values); test_front(values);
test_back(values, detail::bool_<CacheLast>());
test_sort(values); test_sort(values);
test_merge (values); test_merge (values);
test_remove_unique(values);
test_insert(values); test_insert(values);
test_shift(values); test_shift(values);
test_slow_insert (values); test_slow_insert (values);
test_swap(values); test_swap(values);
test_clone(values); test_clone(values);
test_container_from_end(values); test_container_from_end(values, detail::bool_<Linear>());
} }
//test: push_front, pop_front, front, size, empty: //test: push_front, pop_front, front, size, empty:
template<class ValueTraits> template<class ValueTraits, bool Linear, bool CacheLast>
void test_slist<ValueTraits> void test_slist<ValueTraits, Linear, CacheLast>
::test_front_back (std::vector<typename ValueTraits::value_type>& values) ::test_front(std::vector<typename ValueTraits::value_type>& values)
{ {
typedef typename ValueTraits::value_type value_type; typedef typename ValueTraits::value_type value_type;
typedef slist typedef slist
@@ -80,6 +88,8 @@ void test_slist<ValueTraits>
, value_traits<ValueTraits> , value_traits<ValueTraits>
, size_type<std::size_t> , size_type<std::size_t>
, constant_time_size<value_type::constant_time_size> , constant_time_size<value_type::constant_time_size>
, linear<Linear>
, cache_last<CacheLast>
> list_type; > list_type;
list_type testlist; list_type testlist;
BOOST_TEST (testlist.empty()); BOOST_TEST (testlist.empty());
@@ -100,9 +110,43 @@ void test_slist<ValueTraits>
BOOST_TEST (testlist.empty()); BOOST_TEST (testlist.empty());
} }
//test: push_front, pop_front, front, size, empty:
template<class ValueTraits, bool Linear, bool CacheLast>
void test_slist<ValueTraits, Linear, CacheLast>
::test_back(std::vector<typename ValueTraits::value_type>& values, detail::bool_<true>)
{
typedef typename ValueTraits::value_type value_type;
typedef slist
< value_type
, value_traits<ValueTraits>
, size_type<std::size_t>
, constant_time_size<value_type::constant_time_size>
, linear<Linear>
, cache_last<CacheLast>
> list_type;
list_type testlist;
BOOST_TEST (testlist.empty());
testlist.push_back (values[0]);
BOOST_TEST (testlist.size() == 1);
BOOST_TEST (&testlist.front() == &values[0]);
BOOST_TEST (&testlist.back() == &values[0]);
testlist.push_back(values[1]);
BOOST_TEST(*testlist.previous(testlist.end()) == values[1]);
BOOST_TEST (&testlist.front() == &values[0]);
BOOST_TEST (&testlist.back() == &values[1]);
}
//test: push_front, pop_front, front, size, empty:
template<class ValueTraits, bool Linear, bool CacheLast>
void test_slist<ValueTraits, Linear, CacheLast>
::test_back(std::vector<typename ValueTraits::value_type>&, detail::bool_<false>)
{}
//test: merge due to error in merge implementation: //test: merge due to error in merge implementation:
template<class ValueTraits> template<class ValueTraits, bool Linear, bool CacheLast>
void test_slist<ValueTraits> void test_slist<ValueTraits, Linear, CacheLast>
::test_merge (std::vector<typename ValueTraits::value_type>& values) ::test_merge (std::vector<typename ValueTraits::value_type>& values)
{ {
typedef typename ValueTraits::value_type value_type; typedef typename ValueTraits::value_type value_type;
@@ -111,6 +155,8 @@ void test_slist<ValueTraits>
, value_traits<ValueTraits> , value_traits<ValueTraits>
, size_type<std::size_t> , size_type<std::size_t>
, constant_time_size<value_type::constant_time_size> , constant_time_size<value_type::constant_time_size>
, linear<Linear>
, cache_last<CacheLast>
> list_type; > list_type;
list_type testlist1, testlist2; list_type testlist1, testlist2;
testlist1.push_front (values[0]); testlist1.push_front (values[0]);
@@ -123,9 +169,42 @@ void test_slist<ValueTraits>
TEST_INTRUSIVE_SEQUENCE( init_values, testlist1.begin() ); TEST_INTRUSIVE_SEQUENCE( init_values, testlist1.begin() );
} }
//test: merge due to error in merge implementation:
template<class ValueTraits, bool Linear, bool CacheLast>
void test_slist<ValueTraits, Linear, CacheLast>
::test_remove_unique (std::vector<typename ValueTraits::value_type>& values)
{
typedef typename ValueTraits::value_type value_type;
typedef slist
< value_type
, value_traits<ValueTraits>
, size_type<std::size_t>
, constant_time_size<value_type::constant_time_size>
, linear<Linear>
, cache_last<CacheLast>
> list_type;
{
list_type list(values.begin(), values.end());
list.remove_if(is_even());
int init_values [] = { 1, 3, 5 };
TEST_INTRUSIVE_SEQUENCE( init_values, list.begin() );
}
{
std::vector<typename ValueTraits::value_type> values2(values);
list_type list(values.begin(), values.end());
list.insert_after(list.before_begin(), values2.begin(), values2.end());
list.sort();
int init_values [] = { 1, 1, 2, 2, 3, 3, 4, 4, 5, 5 };
TEST_INTRUSIVE_SEQUENCE( init_values, list.begin() );
list.unique();
int init_values2 [] = { 1, 2, 3, 4, 5 };
TEST_INTRUSIVE_SEQUENCE( init_values2, list.begin() );
}
}
//test: constructor, iterator, sort, reverse: //test: constructor, iterator, sort, reverse:
template<class ValueTraits> template<class ValueTraits, bool Linear, bool CacheLast>
void test_slist<ValueTraits> void test_slist<ValueTraits, Linear, CacheLast>
::test_sort(std::vector<typename ValueTraits::value_type>& values) ::test_sort(std::vector<typename ValueTraits::value_type>& values)
{ {
typedef typename ValueTraits::value_type value_type; typedef typename ValueTraits::value_type value_type;
@@ -134,6 +213,8 @@ void test_slist<ValueTraits>
, value_traits<ValueTraits> , value_traits<ValueTraits>
, size_type<std::size_t> , size_type<std::size_t>
, constant_time_size<value_type::constant_time_size> , constant_time_size<value_type::constant_time_size>
, linear<Linear>
, cache_last<CacheLast>
> list_type; > list_type;
list_type testlist (values.begin(), values.end()); list_type testlist (values.begin(), values.end());
@@ -145,13 +226,13 @@ void test_slist<ValueTraits>
TEST_INTRUSIVE_SEQUENCE( init_values, testlist.begin() ); } TEST_INTRUSIVE_SEQUENCE( init_values, testlist.begin() ); }
testlist.reverse(); testlist.reverse();
{ int init_values [] = { 5, 3, 1, 4, 2, }; { int init_values [] = { 5, 3, 1, 4, 2 };
TEST_INTRUSIVE_SEQUENCE( init_values, testlist.begin() ); } TEST_INTRUSIVE_SEQUENCE( init_values, testlist.begin() ); }
} }
//test: assign, insert_after, const_iterator, erase_after, s_iterator_to, previous: //test: assign, insert_after, const_iterator, erase_after, s_iterator_to, previous:
template<class ValueTraits> template<class ValueTraits, bool Linear, bool CacheLast>
void test_slist<ValueTraits> void test_slist<ValueTraits, Linear, CacheLast>
::test_insert(std::vector<typename ValueTraits::value_type>& values) ::test_insert(std::vector<typename ValueTraits::value_type>& values)
{ {
typedef typename ValueTraits::value_type value_type; typedef typename ValueTraits::value_type value_type;
@@ -160,6 +241,8 @@ void test_slist<ValueTraits>
, value_traits<ValueTraits> , value_traits<ValueTraits>
, size_type<std::size_t> , size_type<std::size_t>
, constant_time_size<value_type::constant_time_size> , constant_time_size<value_type::constant_time_size>
, linear<Linear>
, cache_last<CacheLast>
> list_type; > list_type;
list_type testlist; list_type testlist;
testlist.assign (&values[0] + 2, &values[0] + 5); testlist.assign (&values[0] + 2, &values[0] + 5);
@@ -189,8 +272,8 @@ void test_slist<ValueTraits>
} }
//test: insert, const_iterator, erase, siterator_to: //test: insert, const_iterator, erase, siterator_to:
template<class ValueTraits> template<class ValueTraits, bool Linear, bool CacheLast>
void test_slist<ValueTraits> void test_slist<ValueTraits, Linear, CacheLast>
::test_slow_insert (std::vector<typename ValueTraits::value_type>& values) ::test_slow_insert (std::vector<typename ValueTraits::value_type>& values)
{ {
typedef typename ValueTraits::value_type value_type; typedef typename ValueTraits::value_type value_type;
@@ -199,6 +282,8 @@ void test_slist<ValueTraits>
, value_traits<ValueTraits> , value_traits<ValueTraits>
, size_type<std::size_t> , size_type<std::size_t>
, constant_time_size<value_type::constant_time_size> , constant_time_size<value_type::constant_time_size>
, linear<Linear>
, cache_last<CacheLast>
> list_type; > list_type;
list_type testlist; list_type testlist;
testlist.push_front (values[4]); testlist.push_front (values[4]);
@@ -232,8 +317,8 @@ void test_slist<ValueTraits>
BOOST_TEST (testlist.front().value_ == 3); BOOST_TEST (testlist.front().value_ == 3);
} }
template<class ValueTraits> template<class ValueTraits, bool Linear, bool CacheLast>
void test_slist<ValueTraits> void test_slist<ValueTraits, Linear, CacheLast>
::test_shift(std::vector<typename ValueTraits::value_type>& values) ::test_shift(std::vector<typename ValueTraits::value_type>& values)
{ {
typedef typename ValueTraits::value_type value_type; typedef typename ValueTraits::value_type value_type;
@@ -242,6 +327,8 @@ void test_slist<ValueTraits>
, value_traits<ValueTraits> , value_traits<ValueTraits>
, size_type<std::size_t> , size_type<std::size_t>
, constant_time_size<value_type::constant_time_size> , constant_time_size<value_type::constant_time_size>
, linear<Linear>
, cache_last<CacheLast>
> list_type; > list_type;
list_type testlist; list_type testlist;
@@ -249,11 +336,13 @@ void test_slist<ValueTraits>
std::vector<int> expected_values(num_values); std::vector<int> expected_values(num_values);
//Shift forward all possible positions 3 times //Shift forward all possible positions 3 times
for(int i = 0; i < num_values*3; ++i){ for(int s = 1; s <= num_values; ++s){
testlist.assign(values.begin(), values.end()); expected_values.resize(s);
for(int i = 0; i < s*3; ++i){
testlist.insert_after(testlist.before_begin(), &values[0], &values[0] + s);
testlist.shift_forward(i); testlist.shift_forward(i);
for(int j = 0; j < num_values; ++j){ for(int j = 0; j < s; ++j){
expected_values[(j + num_values - i%num_values) % num_values] = (j + 1); expected_values[(j + s - i%s) % s] = (j + 1);
} }
TEST_INTRUSIVE_SEQUENCE_EXPECTED(expected_values, testlist.begin()) TEST_INTRUSIVE_SEQUENCE_EXPECTED(expected_values, testlist.begin())
@@ -261,21 +350,22 @@ void test_slist<ValueTraits>
} }
//Shift backwards all possible positions //Shift backwards all possible positions
for(int i = 0; i < num_values*3; ++i){ for(int i = 0; i < s*3; ++i){
testlist.assign(values.begin(), values.end()); testlist.insert_after(testlist.before_begin(), &values[0], &values[0] + s);
testlist.shift_backwards(i); testlist.shift_backwards(i);
for(int j = 0; j < num_values; ++j){ for(int j = 0; j < s; ++j){
expected_values[(j + i) % num_values] = (j + 1); expected_values[(j + i) % s] = (j + 1);
} }
TEST_INTRUSIVE_SEQUENCE_EXPECTED(expected_values, testlist.begin()) TEST_INTRUSIVE_SEQUENCE_EXPECTED(expected_values, testlist.begin())
testlist.clear(); testlist.clear();
} }
}
} }
//test: insert_after (seq-version), swap, splice_after: //test: insert_after (seq-version), swap, splice_after:
template<class ValueTraits> template<class ValueTraits, bool Linear, bool CacheLast>
void test_slist<ValueTraits> void test_slist<ValueTraits, Linear, CacheLast>
::test_swap(std::vector<typename ValueTraits::value_type>& values) ::test_swap(std::vector<typename ValueTraits::value_type>& values)
{ {
typedef typename ValueTraits::value_type value_type; typedef typename ValueTraits::value_type value_type;
@@ -284,11 +374,13 @@ void test_slist<ValueTraits>
, value_traits<ValueTraits> , value_traits<ValueTraits>
, size_type<std::size_t> , size_type<std::size_t>
, constant_time_size<value_type::constant_time_size> , constant_time_size<value_type::constant_time_size>
, linear<Linear>
, cache_last<CacheLast>
> list_type; > list_type;
{ {
list_type testlist1 (&values[0], &values[0] + 2); list_type testlist1 (&values[0], &values[0] + 2);
list_type testlist2; list_type testlist2;
testlist2.insert_after (testlist2.end(), &values[0] + 2, &values[0] + 5); testlist2.insert_after (testlist2.before_begin(), &values[0] + 2, &values[0] + 5);
testlist1.swap(testlist2); testlist1.swap(testlist2);
{ int init_values [] = { 3, 4, 5 }; { int init_values [] = { 3, 4, 5 };
TEST_INTRUSIVE_SEQUENCE( init_values, testlist1.begin() ); } TEST_INTRUSIVE_SEQUENCE( init_values, testlist1.begin() ); }
@@ -299,19 +391,20 @@ void test_slist<ValueTraits>
TEST_INTRUSIVE_SEQUENCE( init_values, testlist2.begin() ); } TEST_INTRUSIVE_SEQUENCE( init_values, testlist2.begin() ); }
BOOST_TEST (testlist1.empty()); BOOST_TEST (testlist1.empty());
testlist1.splice_after (testlist1.end(), testlist2, ++testlist2.begin()); testlist1.splice_after (testlist1.before_begin(), testlist2, ++testlist2.begin());
{ int init_values [] = { 4 }; { int init_values [] = { 4 };
TEST_INTRUSIVE_SEQUENCE( init_values, testlist1.begin() ); } TEST_INTRUSIVE_SEQUENCE( init_values, testlist1.begin() ); }
{ int init_values [] = { 1, 3, 5, 2 }; { int init_values [] = { 1, 3, 5, 2 };
TEST_INTRUSIVE_SEQUENCE( init_values, testlist2.begin() ); } TEST_INTRUSIVE_SEQUENCE( init_values, testlist2.begin() ); }
testlist1.splice_after (testlist1.begin(), testlist2, testlist1.splice_after (testlist1.begin(), testlist2,
testlist2.end(), ++++testlist2.begin()); testlist2.before_begin(), ++++testlist2.begin());
{ int init_values [] = { 4, 1, 3, 5 }; { int init_values [] = { 4, 1, 3, 5 };
TEST_INTRUSIVE_SEQUENCE( init_values, testlist1.begin() ); } TEST_INTRUSIVE_SEQUENCE( init_values, testlist1.begin() ); }
{ int init_values [] = { 2 }; { int init_values [] = { 2 };
TEST_INTRUSIVE_SEQUENCE( init_values, testlist2.begin() ); } TEST_INTRUSIVE_SEQUENCE( init_values, testlist2.begin() ); }
} }
if(!list_type::linear)
{ {
list_type testlist1 (&values[0], &values[0] + 2); list_type testlist1 (&values[0], &values[0] + 2);
list_type testlist2 (&values[0] + 3, &values[0] + 5); list_type testlist2 (&values[0] + 3, &values[0] + 5);
@@ -326,10 +419,32 @@ void test_slist<ValueTraits>
{ int init_values [] = { 4, 3 }; { int init_values [] = { 4, 3 };
TEST_INTRUSIVE_SEQUENCE( init_values, testlist2.begin() ); } TEST_INTRUSIVE_SEQUENCE( init_values, testlist2.begin() ); }
} }
if(!list_type::linear)
{
list_type testlist1 (&values[0], &values[1]);
{ int init_values [] = { 1 };
TEST_INTRUSIVE_SEQUENCE( init_values, testlist1.begin() ); }
values[1].swap_nodes(values[2]);
{ int init_values [] = { 1 };
TEST_INTRUSIVE_SEQUENCE( init_values, testlist1.begin() ); }
values[0].swap_nodes(values[2]);
{ int init_values [] = { 3 };
TEST_INTRUSIVE_SEQUENCE( init_values, testlist1.begin() ); }
values[0].swap_nodes(values[2]);
{ int init_values [] = { 1 };
TEST_INTRUSIVE_SEQUENCE( init_values, testlist1.begin() ); }
}
} }
template<class ValueTraits> template<class ValueTraits, bool Linear, bool CacheLast>
void test_slist<ValueTraits> void test_slist<ValueTraits, Linear, CacheLast>
::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;
@@ -338,6 +453,8 @@ void test_slist<ValueTraits>
, value_traits<ValueTraits> , value_traits<ValueTraits>
, size_type<std::size_t> , size_type<std::size_t>
, constant_time_size<value_type::constant_time_size> , constant_time_size<value_type::constant_time_size>
, linear<Linear>
, cache_last<CacheLast>
> list_type; > list_type;
list_type testlist1 (&values[0], &values[0] + values.size()); list_type testlist1 (&values[0], &values[0] + values.size());
@@ -349,9 +466,10 @@ void test_slist<ValueTraits>
BOOST_TEST (testlist2.empty()); BOOST_TEST (testlist2.empty());
} }
template<class ValueTraits> template<class ValueTraits, bool Linear, bool CacheLast>
void test_slist<ValueTraits> void test_slist<ValueTraits, Linear, CacheLast>
::test_container_from_end(std::vector<typename ValueTraits::value_type>& values) ::test_container_from_end(std::vector<typename ValueTraits::value_type>& values
,detail::bool_<false>)
{ {
typedef typename ValueTraits::value_type value_type; typedef typename ValueTraits::value_type value_type;
typedef slist typedef slist
@@ -359,6 +477,8 @@ void test_slist<ValueTraits>
, value_traits<ValueTraits> , value_traits<ValueTraits>
, size_type<std::size_t> , size_type<std::size_t>
, constant_time_size<value_type::constant_time_size> , constant_time_size<value_type::constant_time_size>
, linear<Linear>
, cache_last<CacheLast>
> list_type; > list_type;
list_type testlist1 (&values[0], &values[0] + values.size()); list_type testlist1 (&values[0], &values[0] + values.size());
BOOST_TEST (testlist1 == list_type::container_from_end_iterator(testlist1.end())); BOOST_TEST (testlist1 == list_type::container_from_end_iterator(testlist1.end()));
@@ -380,6 +500,8 @@ class test_main_template
< value_type < value_type
, typename value_type::slist_base_hook_t , typename value_type::slist_base_hook_t
>::type >::type
, false
, false
>::test_all(data); >::test_all(data);
test_slist < typename detail::get_member_value_traits test_slist < typename detail::get_member_value_traits
< value_type < value_type
@@ -388,8 +510,68 @@ class test_main_template
, &value_type::slist_node_ , &value_type::slist_node_
> >
>::type >::type
, false
, false
>::test_all(data); >::test_all(data);
//Now linear slists
test_slist < typename detail::get_base_value_traits
< value_type
, typename value_type::slist_base_hook_t
>::type
, true
, false
>::test_all(data);
test_slist < typename detail::get_member_value_traits
< value_type
, member_hook< value_type
, typename value_type::slist_member_hook_t
, &value_type::slist_node_
>
>::type
, true
, false
>::test_all(data);
//Now the same but caching the last node
test_slist < typename detail::get_base_value_traits
< value_type
, typename value_type::slist_base_hook_t
>::type
, false
, true
>::test_all(data);
test_slist < typename detail::get_member_value_traits
< value_type
, member_hook< value_type
, typename value_type::slist_member_hook_t
, &value_type::slist_node_
>
>::type
, false
, true
>::test_all(data);
//Now linear slists
test_slist < typename detail::get_base_value_traits
< value_type
, typename value_type::slist_base_hook_t
>::type
, true
, true
>::test_all(data);
test_slist < typename detail::get_member_value_traits
< value_type
, member_hook< value_type
, typename value_type::slist_member_hook_t
, &value_type::slist_node_
>
>::type
, true
, true
>::test_all(data);
return 0; return 0;
} }
}; };
@@ -409,6 +591,8 @@ class test_main_template<VoidPointer, false>
< value_type < value_type
, typename value_type::slist_base_hook_t , typename value_type::slist_base_hook_t
>::type >::type
, false
, false
>::test_all(data); >::test_all(data);
test_slist < typename detail::get_member_value_traits test_slist < typename detail::get_member_value_traits
@@ -418,12 +602,16 @@ class test_main_template<VoidPointer, false>
, &value_type::slist_node_ , &value_type::slist_node_
> >
>::type >::type
, false
, false
>::test_all(data); >::test_all(data);
test_slist < typename detail::get_base_value_traits test_slist < typename detail::get_base_value_traits
< value_type < value_type
, typename value_type::slist_auto_base_hook_t , typename value_type::slist_auto_base_hook_t
>::type >::type
, false
, false
>::test_all(data); >::test_all(data);
test_slist < typename detail::get_member_value_traits test_slist < typename detail::get_member_value_traits
@@ -433,6 +621,66 @@ class test_main_template<VoidPointer, false>
, &value_type::slist_auto_node_ , &value_type::slist_auto_node_
> >
>::type >::type
, false
, false
>::test_all(data);
test_slist < typename detail::get_base_value_traits
< value_type
, typename value_type::slist_base_hook_t
>::type
, true
, false
>::test_all(data);
test_slist < typename detail::get_member_value_traits
< value_type
, member_hook< value_type
, typename value_type::slist_member_hook_t
, &value_type::slist_node_
>
>::type
, true
, false
>::test_all(data);
//Now cache last
test_slist < typename detail::get_base_value_traits
< value_type
, typename value_type::slist_base_hook_t
>::type
, false
, true
>::test_all(data);
test_slist < typename detail::get_member_value_traits
< value_type
, member_hook< value_type
, typename value_type::slist_member_hook_t
, &value_type::slist_node_
>
>::type
, false
, true
>::test_all(data);
test_slist < typename detail::get_base_value_traits
< value_type
, typename value_type::slist_base_hook_t
>::type
, true
, true
>::test_all(data);
test_slist < typename detail::get_member_value_traits
< value_type
, member_hook< value_type
, typename value_type::slist_member_hook_t
, &value_type::slist_node_
>
>::type
, true
, true
>::test_all(data); >::test_all(data);
return 0; return 0;
} }

View File

@@ -1,65 +0,0 @@
#ifndef BOOST_INTRUSIVE_TEST_TEST_TEMPLATES_HPP
#define BOOST_INTRUSIVE_TEST_TEST_TEMPLATES_HPP
#include <vector>
namespace boost {
namespace intrusive {
namespace test {
template<class Container>
void test_shift()
{
typedef typename ValueTraits::value_type testvalue_t;
boost::test_tools::output_test_stream test_seq;
Container test_cont;
const int NumElem = 6;
std::vector<typename Container::value_type> values(NumElem);
for(int i = 0; i < NumElem; ++i){
values[i] = i+1;
}
const int num_values = (int)values.size();
std::vector<int> expected_values(num_values);
//Shift forward all possible positions 3 times
for(int i = 0; i < num_values*3; ++i){
test_cont.assign(values.begin(), values.end());
test_cont.shift_forward(i);
for(int j = 0; j < num_values; ++j){
expected_values[(j + num_values - i%num_values) % num_values] = (j + 1);
}
std::copy (test_cont.begin(), test_cont.end(),
std::ostream_iterator<testvalue_t> (test_seq));
std::stringstream stream;
std::copy (expected_values.begin(), expected_values.end(),
std::ostream_iterator<testvalue_t> (stream));
stream << std::ends;
BOOST_CHECK (test_seq.is_equal (stream.str().c_str()));
test_cont.clear();
}
//Shift backwards all possible positions
for(int i = 0; i < num_values*2; ++i){
test_cont.assign(values.begin(), values.end());
test_cont.shift_backwards(i);
for(int j = 0; j < num_values; ++j){
expected_values[(j + i) % num_values] = (j + 1);
}
std::copy (test_cont.begin(), test_cont.end(),
std::ostream_iterator<testvalue_t> (test_seq));
std::stringstream stream;
std::copy (expected_values.begin(), expected_values.end(),
std::ostream_iterator<testvalue_t> (stream));
stream << std::ends;
BOOST_CHECK (test_seq.is_equal (stream.str().c_str()));
test_cont.clear();
}
}
} //namespace test {
} //namespace intrusive {
} //namespace boost {
#endif //#ifndef BOOST_INTRUSIVE_TEST_TEST_TEMPLATES_HPP