Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r79422 - trunk/boost/container/detail
From: igaztanaga_at_[hidden]
Date: 2012-07-11 13:34:45


Author: igaztanaga
Date: 2012-07-11 13:34:44 EDT (Wed, 11 Jul 2012)
New Revision: 79422
URL: http://svn.boost.org/trac/boost/changeset/79422

Log:
Ticket #7114:Destructor not called when using emplace()
Text files modified:
   trunk/boost/container/detail/destroyers.hpp | 59 ++++++++++++++++++++++++++++++++++++++++
   trunk/boost/container/detail/flat_tree.hpp | 24 +++++----------
   trunk/boost/container/detail/tree.hpp | 4 ++
   3 files changed, 70 insertions(+), 17 deletions(-)

Modified: trunk/boost/container/detail/destroyers.hpp
==============================================================================
--- trunk/boost/container/detail/destroyers.hpp (original)
+++ trunk/boost/container/detail/destroyers.hpp 2012-07-11 13:34:44 EDT (Wed, 11 Jul 2012)
@@ -65,6 +65,44 @@
    {}
 };
 
+template <class Allocator>
+struct scoped_destroy_deallocator
+{
+ typedef boost::container::allocator_traits<Allocator> AllocTraits;
+ typedef typename AllocTraits::pointer pointer;
+ typedef typename AllocTraits::size_type size_type;
+ typedef container_detail::integral_constant<unsigned,
+ boost::container::container_detail::
+ version<Allocator>::value> alloc_version;
+ typedef container_detail::integral_constant<unsigned, 1> allocator_v1;
+ typedef container_detail::integral_constant<unsigned, 2> 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 @@
    A &a_;
 };
 
+
+template<class A>
+class value_destructor
+{
+ typedef boost::container::allocator_traits<A> 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>
 class allocator_destroyer
 {

Modified: trunk/boost/container/detail/flat_tree.hpp
==============================================================================
--- trunk/boost/container/detail/flat_tree.hpp (original)
+++ trunk/boost/container/detail/flat_tree.hpp 2012-07-11 13:34:44 EDT (Wed, 11 Jul 2012)
@@ -395,14 +395,13 @@
       value_type &val = *static_cast<value_type *>(static_cast<void *>(&v));
       stored_allocator_type &a = this->get_stored_allocator();
       stored_allocator_traits::construct(a, &val, ::boost::forward<Args>(args)... );
- scoped_destructor<stored_allocator_type> d(a, &val);
+ value_destructor<stored_allocator_type> d(a, val);
       insert_commit_data data;
       std::pair<iterator,bool> 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 @@
       value_type &val = *static_cast<value_type *>(static_cast<void *>(&v));
       stored_allocator_type &a = this->get_stored_allocator();
       stored_allocator_traits::construct(a, &val, ::boost::forward<Args>(args)... );
- scoped_destructor<stored_allocator_type> d(a, &val);
+ value_destructor<stored_allocator_type> d(a, val);
       insert_commit_data data;
       std::pair<iterator,bool> 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 @@
       value_type &val = *static_cast<value_type *>(static_cast<void *>(&v));
       stored_allocator_type &a = this->get_stored_allocator();
       stored_allocator_traits::construct(a, &val, ::boost::forward<Args>(args)... );
- scoped_destructor<stored_allocator_type> d(a, &val);
+ value_destructor<stored_allocator_type> 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 @@
       value_type &val = *static_cast<value_type *>(static_cast<void *>(&v));
       stored_allocator_type &a = this->get_stored_allocator();
       stored_allocator_traits::construct(a, &val, ::boost::forward<Args>(args)... );
- scoped_destructor<stored_allocator_type> d(a, &val);
+ value_destructor<stored_allocator_type> 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 @@
       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<stored_allocator_type> d(a, &val); \
+ value_destructor<stored_allocator_type> d(a, val); \
       insert_commit_data data; \
       std::pair<iterator,bool> 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 @@
       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<stored_allocator_type> d(a, &val); \
+ value_destructor<stored_allocator_type> d(a, val); \
       insert_commit_data data; \
       std::pair<iterator,bool> 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 @@
       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<stored_allocator_type> d(a, &val); \
+ value_destructor<stored_allocator_type> 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 @@
       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<stored_allocator_type> d(a, &val); \
+ value_destructor<stored_allocator_type> 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; \
    } \
 

Modified: trunk/boost/container/detail/tree.hpp
==============================================================================
--- trunk/boost/container/detail/tree.hpp (original)
+++ trunk/boost/container/detail/tree.hpp 2012-07-11 13:34:44 EDT (Wed, 11 Jul 2012)
@@ -745,12 +745,14 @@
    {
       value_type &v = p->get_data();
       insert_commit_data data;
+ scoped_destroy_deallocator<NodeAlloc> destroy_deallocator(p, this->node_alloc());
       std::pair<iterator,bool> 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,bool>
          ( iterator(iiterator(this->icont().insert_unique_commit(*p, data)))
          , true );


Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk