diff --git a/include/boost/intrusive/detail/parent_from_member.hpp b/include/boost/intrusive/detail/parent_from_member.hpp index 2afffb4..f86a0e7 100644 --- a/include/boost/intrusive/detail/parent_from_member.hpp +++ b/include/boost/intrusive/detail/parent_from_member.hpp @@ -16,9 +16,9 @@ #include #if defined(BOOST_MSVC) || ((defined(_WIN32) || defined(__WIN32__) || defined(WIN32)) && defined(BOOST_INTEL)) - -#define BOOST_INTRUSIVE_MSVC_COMPLIANT_PTR_TO_MEMBER -#include + #define BOOST_INTRUSIVE_MSVC_ABI_PTR_TO_MEMBER + #include + #include #endif namespace boost { @@ -29,7 +29,7 @@ template inline std::ptrdiff_t offset_from_pointer_to_member(const Member Parent::* ptr_to_member) { //The implementation of a pointer to member is compiler dependent. - #if defined(BOOST_INTRUSIVE_MSVC_COMPLIANT_PTR_TO_MEMBER) + #if defined(BOOST_INTRUSIVE_MSVC_ABI_PTR_TO_MEMBER) //msvc compliant compilers use their the first 32 bits as offset (even in 64 bit mode) union caster_union { @@ -37,6 +37,10 @@ inline std::ptrdiff_t offset_from_pointer_to_member(const Member Parent::* ptr_t boost::int32_t offset; } caster; caster.ptr_to_member = ptr_to_member; + //MSVC ABI can use up to 3 int32 to represent pointer to member data + //with virtual base classes, in those cases there is no simple to + //obtain the address of parent. So static assert to avoid runtime errors + BOOST_STATIC_ASSERT( sizeof(caster) == sizeof(boost::int32_t) ); return std::ptrdiff_t(caster.offset); //This works with gcc, msvc, ac++, ibmcpp #elif defined(__GNUC__) || defined(__HP_aCC) || defined(BOOST_INTEL) || \ @@ -84,8 +88,8 @@ inline const Parent *parent_from_member(const Member *member, const Member Paren } //namespace intrusive { } //namespace boost { -#ifdef BOOST_INTRUSIVE_MSVC_COMPLIANT_PTR_TO_MEMBER -#undef BOOST_INTRUSIVE_MSVC_COMPLIANT_PTR_TO_MEMBER +#ifdef BOOST_INTRUSIVE_MSVC_ABI_PTR_TO_MEMBER +#undef BOOST_INTRUSIVE_MSVC_ABI_PTR_TO_MEMBER #endif #include diff --git a/include/boost/intrusive/detail/utilities.hpp b/include/boost/intrusive/detail/utilities.hpp index 722a7a3..bb34220 100644 --- a/include/boost/intrusive/detail/utilities.hpp +++ b/include/boost/intrusive/detail/utilities.hpp @@ -28,6 +28,7 @@ #include #include #include +#include namespace boost { namespace intrusive { @@ -131,6 +132,12 @@ struct size_holder void increment() { ++size_; } + void increase(SizeType n) + { size_ += n; } + + void decrease(SizeType n) + { size_ -= n; } + SizeType size_; }; @@ -151,6 +158,12 @@ struct size_holder void increment() {} + + void increase(SizeType) + {} + + void decrease(SizeType) + {} }; template @@ -692,19 +705,20 @@ class array_initializer { char *init_buf = (char*)rawbuf; std::size_t i = 0; - try{ + BOOST_TRY{ for(; i != N; ++i){ new(init_buf)T(init); init_buf += sizeof(T); } } - catch(...){ + BOOST_CATCH(...){ while(i--){ init_buf -= sizeof(T); ((T*)init_buf)->~T(); } - throw; + BOOST_RETHROW; } + BOOST_CATCH_END } operator T* () diff --git a/include/boost/intrusive/list.hpp b/include/boost/intrusive/list.hpp index fb2c89a..5909152 100644 --- a/include/boost/intrusive/list.hpp +++ b/include/boost/intrusive/list.hpp @@ -645,7 +645,7 @@ class list_impl } else{ if(constant_time_size){ - this->priv_size_traits().set_size(this->priv_size_traits().get_size() - n); + this->priv_size_traits().decrease(n); } node_algorithms::unlink(b.pointed_node(), e.pointed_node()); return e.unconst(); @@ -886,11 +886,11 @@ class list_impl void splice(const_iterator p, list_impl& x) { if(!x.empty()){ - size_traits &thist = this->priv_size_traits(); - size_traits &xt = x.priv_size_traits(); node_algorithms::transfer (p.pointed_node(), x.begin().pointed_node(), x.end().pointed_node()); - thist.set_size(thist.get_size() + xt.get_size()); + size_traits &thist = this->priv_size_traits(); + size_traits &xt = x.priv_size_traits(); + thist.increase(xt.get_size()); xt.set_size(size_type(0)); } } @@ -953,12 +953,12 @@ class list_impl { if(n){ if(constant_time_size){ - size_traits &thist = this->priv_size_traits(); - size_traits &xt = x.priv_size_traits(); BOOST_INTRUSIVE_INVARIANT_ASSERT(n == std::distance(f, e)); node_algorithms::transfer(p.pointed_node(), f.pointed_node(), e.pointed_node()); - thist.set_size(thist.get_size() + n); - xt.set_size(xt.get_size() - n); + size_traits &thist = this->priv_size_traits(); + size_traits &xt = x.priv_size_traits(); + thist.increase(n); + xt.decrease(n); } else{ node_algorithms::transfer(p.pointed_node(), f.pointed_node(), e.pointed_node()); diff --git a/include/boost/intrusive/options.hpp b/include/boost/intrusive/options.hpp index b1dd944..5449a44 100644 --- a/include/boost/intrusive/options.hpp +++ b/include/boost/intrusive/options.hpp @@ -33,6 +33,8 @@ namespace detail{ struct default_hook_tag{}; +#ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED + #define BOOST_INTRUSIVE_DEFAULT_HOOK_MARKER_DEFINITION(BOOST_INTRUSIVE_DEFAULT_HOOK_MARKER) \ struct BOOST_INTRUSIVE_DEFAULT_HOOK_MARKER : public default_hook_tag\ {\ @@ -51,6 +53,8 @@ BOOST_INTRUSIVE_DEFAULT_HOOK_MARKER_DEFINITION(default_bs_set_hook); #undef BOOST_INTRUSIVE_DEFAULT_HOOK_MARKER_DEFINITION +#endif //BOOST_INTRUSIVE_DOXYGEN_INVOKED + template struct eval_value_traits { diff --git a/include/boost/intrusive/pointer_plus_bits.hpp b/include/boost/intrusive/pointer_plus_bits.hpp index a2a9f1b..273452c 100644 --- a/include/boost/intrusive/pointer_plus_bits.hpp +++ b/include/boost/intrusive/pointer_plus_bits.hpp @@ -47,7 +47,11 @@ struct max_pointer_plus_bits //!has_pointer_plus_bits<>::value is non-zero can make use of these //!operations to embed the bits in the pointer. template -struct pointer_plus_bits; +struct pointer_plus_bits + #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED + {} + #endif +; //!This is the specialization to embed extra bits of information //!in a raw pointer. The extra bits are stored in the lower bits of the pointer. diff --git a/include/boost/intrusive/slist.hpp b/include/boost/intrusive/slist.hpp index b0629b4..bee6ac7 100644 --- a/include/boost/intrusive/slist.hpp +++ b/include/boost/intrusive/slist.hpp @@ -819,8 +819,23 @@ class slist_impl template void insert_after(const_iterator prev_p, Iterator f, Iterator l) { - for (; f != l; ++f) - prev_p = this->insert_after(prev_p, *f); + //Insert first nodes avoiding cache and size checks + size_type count = 0; + node_ptr prev_n(prev_p.pointed_node()); + for (; f != l; ++f, ++count){ + const node_ptr n = get_real_value_traits().to_node_ptr(*f); + if(safemode_or_autounlink) + BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::inited(n)); + node_algorithms::link_after(prev_n, n); + prev_n = n; + } + //Now fix special cases if needed + if(cache_last && (this->get_last_node() == prev_p.pointed_node())){ + this->set_last_node(prev_n); + } + if(constant_time_size){ + this->priv_size_traits().increase(count); + } } //! Requires: value must be an lvalue and p must point to an element @@ -932,7 +947,7 @@ class slist_impl } node_algorithms::unlink_after(bfp, lp); if(constant_time_size){ - this->priv_size_traits().set_size(this->priv_size_traits().get_size() - n); + this->priv_size_traits().decrease(n); } return l.unconst(); } @@ -1209,7 +1224,7 @@ class slist_impl } } node_algorithms::transfer_after( prev_n, x.before_begin().pointed_node(), last_x_n); - this->priv_size_traits().set_size(this->priv_size_traits().get_size() + x.priv_size_traits().get_size()); + this->priv_size_traits().increase(x.priv_size_traits().get_size()); x.priv_size_traits().set_size(size_type(0)); if(l) *l = last_x; } @@ -1278,8 +1293,8 @@ class slist_impl this->priv_splice_after (prev_pos.pointed_node(), x, before_f.pointed_node(), before_l.pointed_node()); if(constant_time_size){ - this->priv_size_traits().set_size(this->priv_size_traits().get_size() + n); - x.priv_size_traits().set_size(x.priv_size_traits().get_size() - n); + this->priv_size_traits().increase(n); + x.priv_size_traits().decrease(n); } } @@ -1834,7 +1849,7 @@ class slist_impl BOOST_INTRUSIVE_INVARIANT_ASSERT(size_type(std::distance(iterator(f, this), iterator(before_l, this)))+1 == n); this->priv_incorporate_after(prev_pos.pointed_node(), f, before_l); if(constant_time_size){ - this->priv_size_traits().set_size(this->priv_size_traits().get_size() + n); + this->priv_size_traits().increase(n); } } } diff --git a/include/boost/intrusive/treap_algorithms.hpp b/include/boost/intrusive/treap_algorithms.hpp index 967e731..e891ef9 100644 --- a/include/boost/intrusive/treap_algorithms.hpp +++ b/include/boost/intrusive/treap_algorithms.hpp @@ -389,7 +389,6 @@ class treap_algorithms { rebalance_for_erasure(header, z, pcomp); tree_algorithms::erase(header, z); -// assert(check_invariant(header, pcomp)); return z; }