From a9eb3dad276cb3cced1c6eeb0c8b11a257682eb0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ion=20Gazta=C3=B1aga?= Date: Wed, 11 Jul 2012 17:34:44 +0000 Subject: [PATCH] Ticket #7114:Destructor not called when using emplace() [SVN r79422] --- include/boost/container/detail/destroyers.hpp | 59 +++++++++++++++++++ include/boost/container/detail/flat_tree.hpp | 24 +++----- include/boost/container/detail/tree.hpp | 4 +- 3 files changed, 70 insertions(+), 17 deletions(-) diff --git a/include/boost/container/detail/destroyers.hpp b/include/boost/container/detail/destroyers.hpp index 3a42be3..d1b118c 100644 --- a/include/boost/container/detail/destroyers.hpp +++ b/include/boost/container/detail/destroyers.hpp @@ -65,6 +65,44 @@ struct null_scoped_array_deallocator {} }; +template +struct scoped_destroy_deallocator +{ + typedef boost::container::allocator_traits AllocTraits; + typedef typename AllocTraits::pointer pointer; + typedef typename AllocTraits::size_type size_type; + typedef container_detail::integral_constant::value> alloc_version; + typedef container_detail::integral_constant allocator_v1; + typedef container_detail::integral_constant allocator_v2; + + scoped_destroy_deallocator(pointer p, Allocator& a) + : m_ptr(p), m_alloc(a) {} + + ~scoped_destroy_deallocator() + { + if(m_ptr){ + AllocTraits::destroy(m_alloc, container_detail::to_raw_pointer(m_ptr)); + priv_deallocate(m_ptr, alloc_version()); + } + } + + void release() + { m_ptr = 0; } + + private: + + void priv_deallocate(const pointer &p, allocator_v1) + { AllocTraits::deallocate(m_alloc, p, 1); } + + void priv_deallocate(const pointer &p, allocator_v2) + { m_alloc.deallocate_one(p); } + + pointer m_ptr; + Allocator& m_alloc; +}; + //!A deleter for scoped_ptr that destroys //!an object using a STL allocator. @@ -150,6 +188,27 @@ class scoped_destructor A &a_; }; + +template +class value_destructor +{ + typedef boost::container::allocator_traits AllocTraits; + public: + typedef typename A::value_type value_type; + value_destructor(A &a, value_type &rv) + : rv_(rv), a_(a) + {} + + ~value_destructor() + { + AllocTraits::destroy(a_, &rv_); + } + + private: + value_type &rv_; + A &a_; +}; + template class allocator_destroyer { diff --git a/include/boost/container/detail/flat_tree.hpp b/include/boost/container/detail/flat_tree.hpp index 739c844..23be0bf 100644 --- a/include/boost/container/detail/flat_tree.hpp +++ b/include/boost/container/detail/flat_tree.hpp @@ -395,14 +395,13 @@ class flat_tree value_type &val = *static_cast(static_cast(&v)); stored_allocator_type &a = this->get_stored_allocator(); stored_allocator_traits::construct(a, &val, ::boost::forward(args)... ); - scoped_destructor d(a, &val); + value_destructor d(a, val); insert_commit_data data; std::pair ret = priv_insert_unique_prepare(val, data); if(ret.second){ ret.first = priv_insert_commit(data, boost::move(val)); } - d.release(); return ret; } @@ -413,13 +412,12 @@ class flat_tree value_type &val = *static_cast(static_cast(&v)); stored_allocator_type &a = this->get_stored_allocator(); stored_allocator_traits::construct(a, &val, ::boost::forward(args)... ); - scoped_destructor d(a, &val); + value_destructor d(a, val); insert_commit_data data; std::pair ret = priv_insert_unique_prepare(hint, val, data); if(ret.second){ ret.first = priv_insert_commit(data, boost::move(val)); } - d.release(); return ret.first; } @@ -430,10 +428,9 @@ class flat_tree value_type &val = *static_cast(static_cast(&v)); stored_allocator_type &a = this->get_stored_allocator(); stored_allocator_traits::construct(a, &val, ::boost::forward(args)... ); - scoped_destructor d(a, &val); + value_destructor d(a, val); iterator i = this->upper_bound(KeyOfValue()(val)); i = this->m_data.m_vect.insert(i, boost::move(val)); - d.release(); return i; } @@ -444,11 +441,10 @@ class flat_tree value_type &val = *static_cast(static_cast(&v)); stored_allocator_type &a = this->get_stored_allocator(); stored_allocator_traits::construct(a, &val, ::boost::forward(args)... ); - scoped_destructor d(a, &val); + value_destructor d(a, val); insert_commit_data data; this->priv_insert_equal_prepare(hint, val, data); iterator i = priv_insert_commit(data, boost::move(val)); - d.release(); return i; } @@ -464,13 +460,12 @@ class flat_tree stored_allocator_type &a = this->get_stored_allocator(); \ stored_allocator_traits::construct(a, &val \ BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _) ); \ - scoped_destructor d(a, &val); \ + value_destructor d(a, val); \ insert_commit_data data; \ std::pair ret = priv_insert_unique_prepare(val, data); \ if(ret.second){ \ ret.first = priv_insert_commit(data, boost::move(val)); \ } \ - d.release(); \ return ret; \ } \ \ @@ -483,13 +478,12 @@ class flat_tree stored_allocator_type &a = this->get_stored_allocator(); \ stored_allocator_traits::construct(a, &val \ BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _) ); \ - scoped_destructor d(a, &val); \ + value_destructor d(a, val); \ insert_commit_data data; \ std::pair ret = priv_insert_unique_prepare(hint, val, data); \ if(ret.second){ \ ret.first = priv_insert_commit(data, boost::move(val)); \ } \ - d.release(); \ return ret.first; \ } \ \ @@ -501,10 +495,9 @@ class flat_tree stored_allocator_type &a = this->get_stored_allocator(); \ stored_allocator_traits::construct(a, &val \ BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _) ); \ - scoped_destructor d(a, &val); \ + value_destructor d(a, val); \ iterator i = this->upper_bound(KeyOfValue()(val)); \ i = this->m_data.m_vect.insert(i, boost::move(val)); \ - d.release(); \ return i; \ } \ \ @@ -517,11 +510,10 @@ class flat_tree stored_allocator_type &a = this->get_stored_allocator(); \ stored_allocator_traits::construct(a, &val \ BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _) ); \ - scoped_destructor d(a, &val); \ + value_destructor d(a, val); \ insert_commit_data data; \ this->priv_insert_equal_prepare(hint, val, data); \ iterator i = priv_insert_commit(data, boost::move(val)); \ - d.release(); \ return i; \ } \ diff --git a/include/boost/container/detail/tree.hpp b/include/boost/container/detail/tree.hpp index 50212ce..3ab1536 100644 --- a/include/boost/container/detail/tree.hpp +++ b/include/boost/container/detail/tree.hpp @@ -745,12 +745,14 @@ class rbtree { value_type &v = p->get_data(); insert_commit_data data; + scoped_destroy_deallocator destroy_deallocator(p, this->node_alloc()); std::pair ret = this->insert_unique_check(KeyOfValue()(v), data); if(!ret.second){ - Destroyer(this->node_alloc())(p); return ret; } + //No throw insertion part, release rollback + destroy_deallocator.release(); return std::pair ( iterator(iiterator(this->icont().insert_unique_commit(*p, data))) , true );