mirror of
https://github.com/boostorg/container.git
synced 2025-08-03 14:34:27 +02:00
Ticket #7114:Destructor not called when using emplace()
[SVN r79422]
This commit is contained in:
@@ -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
|
//!A deleter for scoped_ptr that destroys
|
||||||
//!an object using a STL allocator.
|
//!an object using a STL allocator.
|
||||||
@@ -150,6 +188,27 @@ class scoped_destructor
|
|||||||
A &a_;
|
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>
|
template <class Allocator>
|
||||||
class allocator_destroyer
|
class allocator_destroyer
|
||||||
{
|
{
|
||||||
|
@@ -395,14 +395,13 @@ class flat_tree
|
|||||||
value_type &val = *static_cast<value_type *>(static_cast<void *>(&v));
|
value_type &val = *static_cast<value_type *>(static_cast<void *>(&v));
|
||||||
stored_allocator_type &a = this->get_stored_allocator();
|
stored_allocator_type &a = this->get_stored_allocator();
|
||||||
stored_allocator_traits::construct(a, &val, ::boost::forward<Args>(args)... );
|
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;
|
insert_commit_data data;
|
||||||
std::pair<iterator,bool> ret =
|
std::pair<iterator,bool> ret =
|
||||||
priv_insert_unique_prepare(val, data);
|
priv_insert_unique_prepare(val, data);
|
||||||
if(ret.second){
|
if(ret.second){
|
||||||
ret.first = priv_insert_commit(data, boost::move(val));
|
ret.first = priv_insert_commit(data, boost::move(val));
|
||||||
}
|
}
|
||||||
d.release();
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -413,13 +412,12 @@ class flat_tree
|
|||||||
value_type &val = *static_cast<value_type *>(static_cast<void *>(&v));
|
value_type &val = *static_cast<value_type *>(static_cast<void *>(&v));
|
||||||
stored_allocator_type &a = this->get_stored_allocator();
|
stored_allocator_type &a = this->get_stored_allocator();
|
||||||
stored_allocator_traits::construct(a, &val, ::boost::forward<Args>(args)... );
|
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;
|
insert_commit_data data;
|
||||||
std::pair<iterator,bool> ret = priv_insert_unique_prepare(hint, val, data);
|
std::pair<iterator,bool> ret = priv_insert_unique_prepare(hint, val, data);
|
||||||
if(ret.second){
|
if(ret.second){
|
||||||
ret.first = priv_insert_commit(data, boost::move(val));
|
ret.first = priv_insert_commit(data, boost::move(val));
|
||||||
}
|
}
|
||||||
d.release();
|
|
||||||
return ret.first;
|
return ret.first;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -430,10 +428,9 @@ class flat_tree
|
|||||||
value_type &val = *static_cast<value_type *>(static_cast<void *>(&v));
|
value_type &val = *static_cast<value_type *>(static_cast<void *>(&v));
|
||||||
stored_allocator_type &a = this->get_stored_allocator();
|
stored_allocator_type &a = this->get_stored_allocator();
|
||||||
stored_allocator_traits::construct(a, &val, ::boost::forward<Args>(args)... );
|
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));
|
iterator i = this->upper_bound(KeyOfValue()(val));
|
||||||
i = this->m_data.m_vect.insert(i, boost::move(val));
|
i = this->m_data.m_vect.insert(i, boost::move(val));
|
||||||
d.release();
|
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -444,11 +441,10 @@ class flat_tree
|
|||||||
value_type &val = *static_cast<value_type *>(static_cast<void *>(&v));
|
value_type &val = *static_cast<value_type *>(static_cast<void *>(&v));
|
||||||
stored_allocator_type &a = this->get_stored_allocator();
|
stored_allocator_type &a = this->get_stored_allocator();
|
||||||
stored_allocator_traits::construct(a, &val, ::boost::forward<Args>(args)... );
|
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;
|
insert_commit_data data;
|
||||||
this->priv_insert_equal_prepare(hint, val, data);
|
this->priv_insert_equal_prepare(hint, val, data);
|
||||||
iterator i = priv_insert_commit(data, boost::move(val));
|
iterator i = priv_insert_commit(data, boost::move(val));
|
||||||
d.release();
|
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -464,13 +460,12 @@ class flat_tree
|
|||||||
stored_allocator_type &a = this->get_stored_allocator(); \
|
stored_allocator_type &a = this->get_stored_allocator(); \
|
||||||
stored_allocator_traits::construct(a, &val \
|
stored_allocator_traits::construct(a, &val \
|
||||||
BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _) ); \
|
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; \
|
insert_commit_data data; \
|
||||||
std::pair<iterator,bool> ret = priv_insert_unique_prepare(val, data); \
|
std::pair<iterator,bool> ret = priv_insert_unique_prepare(val, data); \
|
||||||
if(ret.second){ \
|
if(ret.second){ \
|
||||||
ret.first = priv_insert_commit(data, boost::move(val)); \
|
ret.first = priv_insert_commit(data, boost::move(val)); \
|
||||||
} \
|
} \
|
||||||
d.release(); \
|
|
||||||
return ret; \
|
return ret; \
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
@@ -483,13 +478,12 @@ class flat_tree
|
|||||||
stored_allocator_type &a = this->get_stored_allocator(); \
|
stored_allocator_type &a = this->get_stored_allocator(); \
|
||||||
stored_allocator_traits::construct(a, &val \
|
stored_allocator_traits::construct(a, &val \
|
||||||
BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _) ); \
|
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; \
|
insert_commit_data data; \
|
||||||
std::pair<iterator,bool> ret = priv_insert_unique_prepare(hint, val, data); \
|
std::pair<iterator,bool> ret = priv_insert_unique_prepare(hint, val, data); \
|
||||||
if(ret.second){ \
|
if(ret.second){ \
|
||||||
ret.first = priv_insert_commit(data, boost::move(val)); \
|
ret.first = priv_insert_commit(data, boost::move(val)); \
|
||||||
} \
|
} \
|
||||||
d.release(); \
|
|
||||||
return ret.first; \
|
return ret.first; \
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
@@ -501,10 +495,9 @@ class flat_tree
|
|||||||
stored_allocator_type &a = this->get_stored_allocator(); \
|
stored_allocator_type &a = this->get_stored_allocator(); \
|
||||||
stored_allocator_traits::construct(a, &val \
|
stored_allocator_traits::construct(a, &val \
|
||||||
BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _) ); \
|
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)); \
|
iterator i = this->upper_bound(KeyOfValue()(val)); \
|
||||||
i = this->m_data.m_vect.insert(i, boost::move(val)); \
|
i = this->m_data.m_vect.insert(i, boost::move(val)); \
|
||||||
d.release(); \
|
|
||||||
return i; \
|
return i; \
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
@@ -517,11 +510,10 @@ class flat_tree
|
|||||||
stored_allocator_type &a = this->get_stored_allocator(); \
|
stored_allocator_type &a = this->get_stored_allocator(); \
|
||||||
stored_allocator_traits::construct(a, &val \
|
stored_allocator_traits::construct(a, &val \
|
||||||
BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _) ); \
|
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; \
|
insert_commit_data data; \
|
||||||
this->priv_insert_equal_prepare(hint, val, data); \
|
this->priv_insert_equal_prepare(hint, val, data); \
|
||||||
iterator i = priv_insert_commit(data, boost::move(val)); \
|
iterator i = priv_insert_commit(data, boost::move(val)); \
|
||||||
d.release(); \
|
|
||||||
return i; \
|
return i; \
|
||||||
} \
|
} \
|
||||||
|
|
||||||
|
@@ -745,12 +745,14 @@ class rbtree
|
|||||||
{
|
{
|
||||||
value_type &v = p->get_data();
|
value_type &v = p->get_data();
|
||||||
insert_commit_data data;
|
insert_commit_data data;
|
||||||
|
scoped_destroy_deallocator<NodeAlloc> destroy_deallocator(p, this->node_alloc());
|
||||||
std::pair<iterator,bool> ret =
|
std::pair<iterator,bool> ret =
|
||||||
this->insert_unique_check(KeyOfValue()(v), data);
|
this->insert_unique_check(KeyOfValue()(v), data);
|
||||||
if(!ret.second){
|
if(!ret.second){
|
||||||
Destroyer(this->node_alloc())(p);
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
//No throw insertion part, release rollback
|
||||||
|
destroy_deallocator.release();
|
||||||
return std::pair<iterator,bool>
|
return std::pair<iterator,bool>
|
||||||
( iterator(iiterator(this->icont().insert_unique_commit(*p, data)))
|
( iterator(iiterator(this->icont().insert_unique_commit(*p, data)))
|
||||||
, true );
|
, true );
|
||||||
|
Reference in New Issue
Block a user