From 119fb288ff69bd0c90bda4bd092a98443f6330fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ion=20Gazta=C3=B1aga?= Date: Sat, 13 Dec 2008 13:56:15 +0000 Subject: [PATCH] * New treap-based containers: treap, treap_set, treap_multiset. * Corrected compilation bug for Windows-based 64 bit compilers. * Corrected exception-safety bugs in container constructors. * Updated documentation to show rvalue-references funcions instead of emulation functions. [SVN r50261] --- include/boost/intrusive/detail/assert.hpp | 2 +- .../detail/clear_on_destructor_base.hpp | 36 ++++ .../boost/intrusive/detail/config_begin.hpp | 4 +- include/boost/intrusive/detail/config_end.hpp | 2 +- .../intrusive/detail/ebo_functor_holder.hpp | 2 +- .../boost/intrusive/detail/generic_hook.hpp | 2 +- .../boost/intrusive/detail/hashtable_node.hpp | 2 +- include/boost/intrusive/detail/list_node.hpp | 2 +- include/boost/intrusive/detail/mpl.hpp | 4 +- .../intrusive/detail/parent_from_member.hpp | 2 +- .../boost/intrusive/detail/rbtree_node.hpp | 2 +- include/boost/intrusive/detail/slist_node.hpp | 2 +- .../intrusive/detail/transform_iterator.hpp | 2 +- .../intrusive/detail/tree_algorithms.hpp | 162 +++++++++--------- include/boost/intrusive/detail/tree_node.hpp | 3 + include/boost/intrusive/detail/utilities.hpp | 13 +- 16 files changed, 146 insertions(+), 96 deletions(-) create mode 100644 include/boost/intrusive/detail/clear_on_destructor_base.hpp diff --git a/include/boost/intrusive/detail/assert.hpp b/include/boost/intrusive/detail/assert.hpp index e742b7e..0fe98f8 100644 --- a/include/boost/intrusive/detail/assert.hpp +++ b/include/boost/intrusive/detail/assert.hpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006-2007 +// (C) Copyright Ion Gaztanaga 2006-2008 // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at diff --git a/include/boost/intrusive/detail/clear_on_destructor_base.hpp b/include/boost/intrusive/detail/clear_on_destructor_base.hpp new file mode 100644 index 0000000..838dd67 --- /dev/null +++ b/include/boost/intrusive/detail/clear_on_destructor_base.hpp @@ -0,0 +1,36 @@ +//////} // /////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2008-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_DETAIL_CLEAR_ON_DESTRUCTOR_HPP +#define BOOST_INTRUSIVE_DETAIL_CLEAR_ON_DESTRUCTOR_HPP + +#include + +namespace boost { +namespace intrusive { +namespace detail { + +template +class clear_on_destructor_base +{ + protected: + ~clear_on_destructor_base() + { + static_cast(this)->clear(); + } +}; + +} // namespace detail { +} // namespace intrusive { +} // namespace boost { + +#include + +#endif //#ifndef BOOST_INTRUSIVE_DETAIL_CLEAR_ON_DESTRUCTOR_HPP diff --git a/include/boost/intrusive/detail/config_begin.hpp b/include/boost/intrusive/detail/config_begin.hpp index 411b8ae..1c390be 100644 --- a/include/boost/intrusive/detail/config_begin.hpp +++ b/include/boost/intrusive/detail/config_begin.hpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006-2007 +// (C) Copyright Ion Gaztanaga 2006-2008 // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at @@ -44,6 +44,8 @@ #pragma warning (disable : 4267) //conversion from 'X' to 'Y', possible loss of data #pragma warning (disable : 4127) //conditional expression is constant #pragma warning (disable : 4706) //assignment within conditional expression + #pragma warning (disable : 4541) //'typeid' used on polymorphic type 'boost::exception' with /GR- + #pragma warning (disable : 4512) //'typeid' used on polymorphic type 'boost::exception' with /GR- #endif //#define BOOST_INTRUSIVE_USE_ITERATOR_FACADE diff --git a/include/boost/intrusive/detail/config_end.hpp b/include/boost/intrusive/detail/config_end.hpp index 703d038..f04b2e9 100644 --- a/include/boost/intrusive/detail/config_end.hpp +++ b/include/boost/intrusive/detail/config_end.hpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006-2007 +// (C) Copyright Ion Gaztanaga 2006-2008 // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at diff --git a/include/boost/intrusive/detail/ebo_functor_holder.hpp b/include/boost/intrusive/detail/ebo_functor_holder.hpp index 369d2ca..43cc975 100644 --- a/include/boost/intrusive/detail/ebo_functor_holder.hpp +++ b/include/boost/intrusive/detail/ebo_functor_holder.hpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Joaquin M Lopez Munoz 2006-2007 +// (C) Copyright Joaquin M Lopez Munoz 2006-2008 // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at diff --git a/include/boost/intrusive/detail/generic_hook.hpp b/include/boost/intrusive/detail/generic_hook.hpp index 837f928..1b4736b 100644 --- a/include/boost/intrusive/detail/generic_hook.hpp +++ b/include/boost/intrusive/detail/generic_hook.hpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2007 +// (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 diff --git a/include/boost/intrusive/detail/hashtable_node.hpp b/include/boost/intrusive/detail/hashtable_node.hpp index 44a5f5a..fbb150d 100644 --- a/include/boost/intrusive/detail/hashtable_node.hpp +++ b/include/boost/intrusive/detail/hashtable_node.hpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2007 +// (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 diff --git a/include/boost/intrusive/detail/list_node.hpp b/include/boost/intrusive/detail/list_node.hpp index a0bc8ba..effd36a 100644 --- a/include/boost/intrusive/detail/list_node.hpp +++ b/include/boost/intrusive/detail/list_node.hpp @@ -1,7 +1,7 @@ ///////////////////////////////////////////////////////////////////////////// // // (C) Copyright Olaf Krzikalla 2004-2006. -// (C) Copyright Ion Gaztanaga 2006-2007 +// (C) Copyright Ion Gaztanaga 2006-2008 // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at diff --git a/include/boost/intrusive/detail/mpl.hpp b/include/boost/intrusive/detail/mpl.hpp index 27e7f37..15954b9 100644 --- a/include/boost/intrusive/detail/mpl.hpp +++ b/include/boost/intrusive/detail/mpl.hpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006-2007 +// (C) Copyright Ion Gaztanaga 2006-2008 // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at @@ -129,7 +129,7 @@ struct identity #define BOOST_INTRUSIVE_TT_DECL #endif -#if defined(_MSC_EXTENSIONS) && !defined(__BORLAND__) +#if defined(_MSC_EXTENSIONS) && !defined(__BORLAND__) && !defined(_WIN64) #define BOOST_INTRUSIVE_TT_TEST_MSC_FUNC_SIGS #endif diff --git a/include/boost/intrusive/detail/parent_from_member.hpp b/include/boost/intrusive/detail/parent_from_member.hpp index d5fc96a..c99ac6c 100644 --- a/include/boost/intrusive/detail/parent_from_member.hpp +++ b/include/boost/intrusive/detail/parent_from_member.hpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2007 +// (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 diff --git a/include/boost/intrusive/detail/rbtree_node.hpp b/include/boost/intrusive/detail/rbtree_node.hpp index 5345209..6d6dd84 100644 --- a/include/boost/intrusive/detail/rbtree_node.hpp +++ b/include/boost/intrusive/detail/rbtree_node.hpp @@ -1,7 +1,7 @@ ///////////////////////////////////////////////////////////////////////////// // // (C) Copyright Olaf Krzikalla 2004-2006. -// (C) Copyright Ion Gaztanaga 2006-2007. +// (C) Copyright Ion Gaztanaga 2006-2008. // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at diff --git a/include/boost/intrusive/detail/slist_node.hpp b/include/boost/intrusive/detail/slist_node.hpp index c0636e1..4101092 100644 --- a/include/boost/intrusive/detail/slist_node.hpp +++ b/include/boost/intrusive/detail/slist_node.hpp @@ -1,7 +1,7 @@ ///////////////////////////////////////////////////////////////////////////// // // (C) Copyright Olaf Krzikalla 2004-2006. -// (C) Copyright Ion Gaztanaga 2006-2007 +// (C) Copyright Ion Gaztanaga 2006-2008 // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at diff --git a/include/boost/intrusive/detail/transform_iterator.hpp b/include/boost/intrusive/detail/transform_iterator.hpp index f5fe05c..a4afd77 100644 --- a/include/boost/intrusive/detail/transform_iterator.hpp +++ b/include/boost/intrusive/detail/transform_iterator.hpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2007 +// (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 diff --git a/include/boost/intrusive/detail/tree_algorithms.hpp b/include/boost/intrusive/detail/tree_algorithms.hpp index 0aa06f7..1fe196b 100644 --- a/include/boost/intrusive/detail/tree_algorithms.hpp +++ b/include/boost/intrusive/detail/tree_algorithms.hpp @@ -721,22 +721,6 @@ class tree_algorithms static bool is_header(const_node_ptr p) { -/* - node_ptr p_parent = NodeTraits::get_parent(p); - if(!p_parent) - return true; - if(!NodeTraits::get_parent(p_parent) != p) - return false; - if(NodeTraits::get_left(p) != 0){ - if(NodeTraits::get_parent(NodeTraits::get_left(p)) != p){ - is_header = true; - } - if(NodeTraits::get_parent(p) == NodeTraits::get_left(p)){ - is_header = true; - } - } -*/ - bool is_header = false; if(NodeTraits::get_parent(p) == p){ is_header = true; @@ -1015,42 +999,71 @@ class tree_algorithms } } - //! Requires: "header" must be the header node of a tree. - //! NodePtrCompare is a function object that induces a strict weak - //! ordering compatible with the strict weak ordering used to create the - //! the tree. NodePtrCompare compares two node_ptrs. "hint" is node from - //! the "header"'s tree. - //! - //! Effects: Inserts new_node into the tree, using "hint" as a hint to - //! where it will be inserted. If "hint" is the upper_bound - //! the insertion takes constant time (two comparisons in the worst case). - //! - //! Complexity: Logarithmic in general, but it is amortized - //! constant time if new_node is inserted immediately before "hint". - //! - //! Throws: If "comp" throws. template - static node_ptr insert_equal - (node_ptr header, node_ptr hint, node_ptr new_node, NodePtrCompare comp, std::size_t *pdepth = 0) + static void insert_equal_check + ( node_ptr header, node_ptr hint, node_ptr new_node, NodePtrCompare comp + , insert_commit_data &commit_data, std::size_t *pdepth = 0) { if(hint == header || !comp(hint, new_node)){ node_ptr prev(hint); if(hint == NodeTraits::get_left(header) || !comp(new_node, (prev = prev_node(hint)))){ bool link_left = unique(header) || !NodeTraits::get_left(hint); - link(header, new_node, link_left ? hint : prev, link_left); - if(pdepth) *pdepth = depth(new_node) + 1; - return new_node; + commit_data.link_left = link_left; + commit_data.node = link_left ? hint : prev; + if(pdepth){ + *pdepth = commit_data.node == header ? 0 : depth(commit_data.node) + 1; + } } else{ - return insert_equal_upper_bound(header, new_node, comp, pdepth); + insert_equal_upper_bound_check(header, new_node, comp, commit_data, pdepth); } } else{ - return insert_equal_lower_bound(header, new_node, comp, pdepth); + insert_equal_lower_bound_check(header, new_node, comp, commit_data, pdepth); } } + template + static void insert_equal_upper_bound_check + (node_ptr h, node_ptr new_node, NodePtrCompare comp, insert_commit_data & commit_data, std::size_t *pdepth = 0) + { insert_equal_check_impl(true, h, new_node, comp, commit_data, pdepth); } + + template + static void insert_equal_lower_bound_check + (node_ptr h, node_ptr new_node, NodePtrCompare comp, insert_commit_data & commit_data, std::size_t *pdepth = 0) + { insert_equal_check_impl(false, h, new_node, comp, commit_data, pdepth); } + + template + static node_ptr insert_equal + (node_ptr h, node_ptr hint, node_ptr new_node, NodePtrCompare comp, std::size_t *pdepth = 0) + { + insert_commit_data commit_data; + insert_equal_check(h, hint, new_node, comp, commit_data, pdepth); + link(h, new_node, commit_data.node, commit_data.link_left); + return new_node; + } + + template + static node_ptr insert_equal_upper_bound + (node_ptr h, node_ptr new_node, NodePtrCompare comp, std::size_t *pdepth = 0) + { + insert_commit_data commit_data; + insert_equal_upper_bound_check(h, new_node, comp, commit_data, pdepth); + link(h, new_node, commit_data.node, commit_data.link_left); + return new_node; + } + + template + static node_ptr insert_equal_lower_bound + (node_ptr h, node_ptr new_node, NodePtrCompare comp, std::size_t *pdepth = 0) + { + insert_commit_data commit_data; + insert_equal_lower_bound_check(h, new_node, comp, commit_data, pdepth); + link(h, new_node, commit_data.node, commit_data.link_left); + return new_node; + } + //! Requires: p can't be a header node. //! //! Effects: Calculates the depth of a node: the depth of a @@ -1071,48 +1084,6 @@ class tree_algorithms return depth; } - template - static node_ptr insert_equal_upper_bound - (node_ptr h, node_ptr new_node, NodePtrCompare comp, std::size_t *pdepth = 0) - { - std::size_t depth = 0; - node_ptr y(h); - node_ptr x(NodeTraits::get_parent(y)); - - while(x){ - ++depth; - y = x; - x = comp(new_node, x) ? - NodeTraits::get_left(x) : NodeTraits::get_right(x); - } - - bool link_left = (y == h) || comp(new_node, y); - link(h, new_node, y, link_left); - if(pdepth) *pdepth = depth; - return new_node; - } - - template - static node_ptr insert_equal_lower_bound - (node_ptr h, node_ptr new_node, NodePtrCompare comp, std::size_t *pdepth = 0) - { - std::size_t depth = 0; - node_ptr y(h); - node_ptr x(NodeTraits::get_parent(y)); - - while(x){ - ++depth; - y = x; - x = !comp(x, new_node) ? - NodeTraits::get_left(x) : NodeTraits::get_right(x); - } - - bool link_left = (y == h) || !comp(y, new_node); - link(h, new_node, y, link_left); - if(pdepth) *pdepth = depth; - return new_node; - } - //! Requires: "cloner" must be a function //! object taking a node_ptr and returning a new cloned node of it. "disposer" must //! take a node_ptr and shouldn't throw. @@ -1557,6 +1528,39 @@ class tree_algorithms } private: + template + static void insert_equal_check_impl + (bool upper, node_ptr h, node_ptr new_node, NodePtrCompare comp, insert_commit_data & commit_data, std::size_t *pdepth = 0) + { + std::size_t depth = 0; + node_ptr y(h); + node_ptr x(NodeTraits::get_parent(y)); + bool link_left; + + if(upper){ + while(x){ + ++depth; + y = x; + x = comp(new_node, x) ? + NodeTraits::get_left(x) : NodeTraits::get_right(x); + } + link_left = (y == h) || comp(new_node, y); + } + else{ + while(x){ + ++depth; + y = x; + x = !comp(x, new_node) ? + NodeTraits::get_left(x) : NodeTraits::get_right(x); + } + link_left = (y == h) || !comp(y, new_node); + } + + commit_data.link_left = link_left; + commit_data.node = y; + if(pdepth) *pdepth = depth; + } + static void erase_impl(node_ptr header, node_ptr z, data_for_rebalance &info) { node_ptr y(z); diff --git a/include/boost/intrusive/detail/tree_node.hpp b/include/boost/intrusive/detail/tree_node.hpp index a375cba..be3c976 100644 --- a/include/boost/intrusive/detail/tree_node.hpp +++ b/include/boost/intrusive/detail/tree_node.hpp @@ -173,6 +173,9 @@ class tree_iterator return tree_iterator(node_algorithms::get_header(this->pointed_node()), this->get_container()); } + tree_iterator unconst() const + { return tree_iterator(this->pointed_node(), this->get_container()); } + private: struct members : public detail::select_constptr diff --git a/include/boost/intrusive/detail/utilities.hpp b/include/boost/intrusive/detail/utilities.hpp index 7a92449..ad81dc2 100644 --- a/include/boost/intrusive/detail/utilities.hpp +++ b/include/boost/intrusive/detail/utilities.hpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006-2007 +// (C) Copyright Ion Gaztanaga 2006-2008 // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at @@ -211,20 +211,25 @@ struct key_nodeptr_comp { typedef typename Container::real_value_traits real_value_traits; typedef typename real_value_traits::node_ptr node_ptr; + typedef typename real_value_traits::const_node_ptr const_node_ptr; typedef detail::ebo_functor_holder base_t; key_nodeptr_comp(KeyValueCompare kcomp, const Container *cont) : base_t(kcomp), cont_(cont) {} template - bool operator()(node_ptr node, const KeyType &key) const + bool operator()( const_node_ptr node, const KeyType &key + , typename enable_if_c + ::value>::type * = 0) const { return base_t::get()(*cont_->get_real_value_traits().to_value_ptr(node), key); } template - bool operator()(const KeyType &key, node_ptr node) const + bool operator()(const KeyType &key, const_node_ptr node + , typename enable_if_c + ::value>::type * = 0) const { return base_t::get()(key, *cont_->get_real_value_traits().to_value_ptr(node)); } - bool operator()(node_ptr node1, node_ptr node2) const + bool operator()(const_node_ptr node1, const_node_ptr node2) const { return base_t::get() ( *cont_->get_real_value_traits().to_value_ptr(node1)