$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
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 );