Ticket #7114:Destructor not called when using emplace()

[SVN r79422]
This commit is contained in:
Ion Gaztañaga
2012-07-11 17:34:44 +00:00
parent 390dce6172
commit a9eb3dad27
3 changed files with 70 additions and 17 deletions

View File

@@ -65,6 +65,44 @@ struct null_scoped_array_deallocator
{}
};
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 @@ class scoped_destructor
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
{

View File

@@ -395,14 +395,13 @@ class flat_tree
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 @@ class flat_tree
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 @@ class flat_tree
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 @@ class flat_tree
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 @@ 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<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 @@ 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<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 @@ 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<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 @@ 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<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; \
} \

View File

@@ -745,12 +745,14 @@ class rbtree
{
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 );