mirror of
https://github.com/boostorg/container.git
synced 2025-08-02 14:04:26 +02:00
Use uninitialized memory for node-based containers to improve aliasing conformance
This commit is contained in:
@@ -227,14 +227,18 @@ struct node_alloc_holder
|
|||||||
NodePtr create_node(Args &&...args)
|
NodePtr create_node(Args &&...args)
|
||||||
{
|
{
|
||||||
NodePtr p = this->allocate_one();
|
NodePtr p = this->allocate_one();
|
||||||
Deallocator node_deallocator(p, this->node_alloc());
|
BOOST_TRY{
|
||||||
allocator_traits<NodeAlloc>::construct
|
::new(boost::movelib::iterator_to_raw_pointer(p), boost_container_new_t()) Node;
|
||||||
( this->node_alloc()
|
allocator_traits<NodeAlloc>::construct
|
||||||
, dtl::addressof(p->m_data), boost::forward<Args>(args)...);
|
(this->node_alloc()
|
||||||
node_deallocator.release();
|
, p->get_real_data_ptr(), boost::forward<Args>(args)...);
|
||||||
//This does not throw
|
}
|
||||||
typedef typename Node::hook_type hook_type;
|
BOOST_CATCH(...) {
|
||||||
::new(static_cast<hook_type*>(boost::movelib::to_raw_pointer(p)), boost_container_new_t()) hook_type;
|
p->destroy_header();
|
||||||
|
this->node_alloc().deallocate(p, 1);
|
||||||
|
BOOST_RETHROW
|
||||||
|
}
|
||||||
|
BOOST_CATCH_END
|
||||||
return (p);
|
return (p);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -245,14 +249,19 @@ struct node_alloc_holder
|
|||||||
NodePtr create_node(BOOST_MOVE_UREF##N)\
|
NodePtr create_node(BOOST_MOVE_UREF##N)\
|
||||||
{\
|
{\
|
||||||
NodePtr p = this->allocate_one();\
|
NodePtr p = this->allocate_one();\
|
||||||
Deallocator node_deallocator(p, this->node_alloc());\
|
BOOST_TRY{\
|
||||||
allocator_traits<NodeAlloc>::construct\
|
::new(boost::movelib::iterator_to_raw_pointer(p), boost_container_new_t()) Node;\
|
||||||
( this->node_alloc()\
|
allocator_traits<NodeAlloc>::construct\
|
||||||
, dtl::addressof(p->m_data)\
|
( this->node_alloc()\
|
||||||
BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\
|
, p->get_real_data_ptr()\
|
||||||
node_deallocator.release();\
|
BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\
|
||||||
typedef typename Node::hook_type hook_type;\
|
}\
|
||||||
::new(static_cast<hook_type*>(boost::movelib::to_raw_pointer(p)), boost_container_new_t()) hook_type;\
|
BOOST_CATCH(...) {\
|
||||||
|
p->destroy_header();\
|
||||||
|
this->node_alloc().deallocate(p, 1);\
|
||||||
|
BOOST_RETHROW\
|
||||||
|
}\
|
||||||
|
BOOST_CATCH_END\
|
||||||
return (p);\
|
return (p);\
|
||||||
}\
|
}\
|
||||||
//
|
//
|
||||||
@@ -265,12 +274,16 @@ struct node_alloc_holder
|
|||||||
NodePtr create_node_from_it(const It &it)
|
NodePtr create_node_from_it(const It &it)
|
||||||
{
|
{
|
||||||
NodePtr p = this->allocate_one();
|
NodePtr p = this->allocate_one();
|
||||||
Deallocator node_deallocator(p, this->node_alloc());
|
BOOST_TRY{
|
||||||
::boost::container::construct_in_place(this->node_alloc(), dtl::addressof(p->m_data), it);
|
::new(boost::movelib::iterator_to_raw_pointer(p), boost_container_new_t()) Node;
|
||||||
node_deallocator.release();
|
::boost::container::construct_in_place(this->node_alloc(), p->get_real_data_ptr(), it);
|
||||||
//This does not throw
|
}
|
||||||
typedef typename Node::hook_type hook_type;
|
BOOST_CATCH(...) {
|
||||||
::new(static_cast<hook_type*>(boost::movelib::to_raw_pointer(p)), boost_container_new_t()) hook_type;
|
p->destroy_header();
|
||||||
|
this->node_alloc().deallocate(p, 1);
|
||||||
|
BOOST_RETHROW
|
||||||
|
}
|
||||||
|
BOOST_CATCH_END
|
||||||
return (p);
|
return (p);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -278,22 +291,26 @@ struct node_alloc_holder
|
|||||||
NodePtr create_node_from_key(BOOST_FWD_REF(KeyConvertible) key)
|
NodePtr create_node_from_key(BOOST_FWD_REF(KeyConvertible) key)
|
||||||
{
|
{
|
||||||
NodePtr p = this->allocate_one();
|
NodePtr p = this->allocate_one();
|
||||||
NodeAlloc &na = this->node_alloc();
|
|
||||||
Deallocator node_deallocator(p, this->node_alloc());
|
|
||||||
node_allocator_traits_type::construct
|
|
||||||
(na, dtl::addressof(p->m_data.first), boost::forward<KeyConvertible>(key));
|
|
||||||
BOOST_TRY{
|
BOOST_TRY{
|
||||||
node_allocator_traits_type::construct(na, dtl::addressof(p->m_data.second));
|
::new(boost::movelib::iterator_to_raw_pointer(p), boost_container_new_t()) Node;
|
||||||
|
NodeAlloc &na = this->node_alloc();
|
||||||
|
node_allocator_traits_type::construct
|
||||||
|
(na, dtl::addressof(p->get_real_data().first), boost::forward<KeyConvertible>(key));
|
||||||
|
BOOST_TRY{
|
||||||
|
node_allocator_traits_type::construct(na, dtl::addressof(p->get_real_data().second));
|
||||||
|
}
|
||||||
|
BOOST_CATCH(...){
|
||||||
|
node_allocator_traits_type::destroy(na, dtl::addressof(p->get_real_data().first));
|
||||||
|
BOOST_RETHROW;
|
||||||
|
}
|
||||||
|
BOOST_CATCH_END
|
||||||
}
|
}
|
||||||
BOOST_CATCH(...){
|
BOOST_CATCH(...) {
|
||||||
node_allocator_traits_type::destroy(na, dtl::addressof(p->m_data.first));
|
p->destroy_header();
|
||||||
BOOST_RETHROW;
|
this->node_alloc().deallocate(p, 1);
|
||||||
|
BOOST_RETHROW
|
||||||
}
|
}
|
||||||
BOOST_CATCH_END
|
BOOST_CATCH_END
|
||||||
node_deallocator.release();
|
|
||||||
//This does not throw
|
|
||||||
typedef typename Node::hook_type hook_type;
|
|
||||||
::new(static_cast<hook_type*>(boost::movelib::to_raw_pointer(p)), boost_container_new_t()) hook_type;
|
|
||||||
return (p);
|
return (p);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -315,30 +332,31 @@ struct node_alloc_holder
|
|||||||
(FwdIterator beg, difference_type n, Inserter inserter)
|
(FwdIterator beg, difference_type n, Inserter inserter)
|
||||||
{
|
{
|
||||||
if(n){
|
if(n){
|
||||||
typedef typename node_allocator_version_traits_type::multiallocation_chain multiallocation_chain;
|
typedef typename node_allocator_version_traits_type::multiallocation_chain multiallocation_chain_t;
|
||||||
|
|
||||||
//Try to allocate memory in a single block
|
//Try to allocate memory in a single block
|
||||||
typedef typename multiallocation_chain::iterator multialloc_iterator;
|
typedef typename multiallocation_chain_t::iterator multialloc_iterator_t;
|
||||||
multiallocation_chain mem;
|
multiallocation_chain_t chain;
|
||||||
NodeAlloc &nalloc = this->node_alloc();
|
NodeAlloc &nalloc = this->node_alloc();
|
||||||
node_allocator_version_traits_type::allocate_individual(nalloc, n, mem);
|
node_allocator_version_traits_type::allocate_individual(nalloc, n, chain);
|
||||||
multialloc_iterator itbeg(mem.begin()), itlast(mem.last());
|
multialloc_iterator_t itbeg = chain.begin();
|
||||||
mem.clear();
|
multialloc_iterator_t itlast = chain.last();
|
||||||
|
chain.clear();
|
||||||
|
|
||||||
Node *p = 0;
|
Node *p = 0;
|
||||||
BOOST_TRY{
|
BOOST_TRY{
|
||||||
Deallocator node_deallocator(NodePtr(), nalloc);
|
Deallocator node_deallocator(NodePtr(), nalloc);
|
||||||
dtl::scoped_destructor<NodeAlloc> sdestructor(nalloc, 0);
|
dtl::scoped_destructor<NodeAlloc> sdestructor(nalloc, 0);
|
||||||
while(n--){
|
while(n){
|
||||||
p = boost::movelib::iterator_to_raw_pointer(itbeg);
|
--n;
|
||||||
|
//This does not throw
|
||||||
|
p = ::new(boost::movelib::iterator_to_raw_pointer(itbeg), boost_container_new_t()) Node;
|
||||||
node_deallocator.set(p);
|
node_deallocator.set(p);
|
||||||
++itbeg;
|
++itbeg;
|
||||||
//This can throw
|
//This can throw
|
||||||
boost::container::construct_in_place(nalloc, dtl::addressof(p->m_data), beg);
|
boost::container::construct_in_place(nalloc, p->get_real_data_ptr(), beg);
|
||||||
sdestructor.set(p);
|
sdestructor.set(p);
|
||||||
++beg;
|
++beg;
|
||||||
//This does not throw
|
|
||||||
typedef typename Node::hook_type hook_type;
|
|
||||||
::new(static_cast<hook_type*>(p), boost_container_new_t()) hook_type;
|
|
||||||
//This can throw in some containers (predicate might throw).
|
//This can throw in some containers (predicate might throw).
|
||||||
//(sdestructor will destruct the node and node_deallocator will deallocate it in case of exception)
|
//(sdestructor will destruct the node and node_deallocator will deallocate it in case of exception)
|
||||||
inserter(*p);
|
inserter(*p);
|
||||||
@@ -348,8 +366,9 @@ struct node_alloc_holder
|
|||||||
node_deallocator.release();
|
node_deallocator.release();
|
||||||
}
|
}
|
||||||
BOOST_CATCH(...){
|
BOOST_CATCH(...){
|
||||||
mem.incorporate_after(mem.last(), &*itbeg, &*itlast, n);
|
p->destroy_header();
|
||||||
node_allocator_version_traits_type::deallocate_individual(this->node_alloc(), mem);
|
chain.incorporate_after(chain.last(), &*itbeg, &*itlast, n);
|
||||||
|
node_allocator_version_traits_type::deallocate_individual(this->node_alloc(), chain);
|
||||||
BOOST_RETHROW
|
BOOST_RETHROW
|
||||||
}
|
}
|
||||||
BOOST_CATCH_END
|
BOOST_CATCH_END
|
||||||
@@ -402,7 +421,7 @@ struct node_alloc_holder
|
|||||||
{}
|
{}
|
||||||
|
|
||||||
NodePtr operator()(const Node &other) const
|
NodePtr operator()(const Node &other) const
|
||||||
{ return m_holder.create_node(other.m_data); }
|
{ return m_holder.create_node(other.get_real_data()); }
|
||||||
|
|
||||||
node_alloc_holder &m_holder;
|
node_alloc_holder &m_holder;
|
||||||
};
|
};
|
||||||
@@ -414,8 +433,8 @@ struct node_alloc_holder
|
|||||||
{}
|
{}
|
||||||
|
|
||||||
NodePtr operator()(Node &other)
|
NodePtr operator()(Node &other)
|
||||||
{ //Use m_data instead of get_data to allow moving const key in [multi]map
|
{ //Use get_real_data() instead of get_real_data to allow moving const key in [multi]map
|
||||||
return m_holder.create_node(::boost::move(other.m_data));
|
return m_holder.create_node(::boost::move(other.get_real_data()));
|
||||||
}
|
}
|
||||||
|
|
||||||
node_alloc_holder &m_holder;
|
node_alloc_holder &m_holder;
|
||||||
|
@@ -125,10 +125,6 @@ template <class T, class VoidPointer, boost::container::tree_type_enum tree_type
|
|||||||
struct tree_node
|
struct tree_node
|
||||||
: public intrusive_tree_hook<VoidPointer, tree_type_value, OptimizeSize>::type
|
: public intrusive_tree_hook<VoidPointer, tree_type_value, OptimizeSize>::type
|
||||||
{
|
{
|
||||||
private:
|
|
||||||
//BOOST_COPYABLE_AND_MOVABLE(tree_node)
|
|
||||||
tree_node();
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
typedef typename intrusive_tree_hook
|
typedef typename intrusive_tree_hook
|
||||||
<VoidPointer, tree_type_value, OptimizeSize>::type hook_type;
|
<VoidPointer, tree_type_value, OptimizeSize>::type hook_type;
|
||||||
@@ -138,55 +134,86 @@ struct tree_node
|
|||||||
typedef tree_node< T, VoidPointer
|
typedef tree_node< T, VoidPointer
|
||||||
, tree_type_value, OptimizeSize> node_t;
|
, tree_type_value, OptimizeSize> node_t;
|
||||||
|
|
||||||
|
typedef typename boost::container::dtl::aligned_storage
|
||||||
|
<sizeof(T), boost::container::dtl::alignment_of<T>::value>::type storage_t;
|
||||||
|
storage_t m_storage;
|
||||||
|
|
||||||
|
#if defined(BOOST_GCC) && (BOOST_GCC >= 40600) && (BOOST_GCC < 80000)
|
||||||
|
#pragma GCC diagnostic push
|
||||||
|
#pragma GCC diagnostic ignored "-Wstrict-aliasing"
|
||||||
|
#define BOOST_CONTAINER_DISABLE_ALIASING_WARNING
|
||||||
|
# endif
|
||||||
|
|
||||||
BOOST_CONTAINER_FORCEINLINE T &get_data()
|
BOOST_CONTAINER_FORCEINLINE T &get_data()
|
||||||
{
|
{ return *reinterpret_cast<T*>(this->m_storage.data); }
|
||||||
T* ptr = reinterpret_cast<T*>(&this->m_data);
|
|
||||||
return *ptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOST_CONTAINER_FORCEINLINE const T &get_data() const
|
BOOST_CONTAINER_FORCEINLINE const T &get_data() const
|
||||||
{
|
{ return *reinterpret_cast<const T*>(this->m_storage.data); }
|
||||||
const T* ptr = reinterpret_cast<const T*>(&this->m_data);
|
|
||||||
return *ptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
internal_type m_data;
|
BOOST_CONTAINER_FORCEINLINE T *get_data_ptr()
|
||||||
|
{ return reinterpret_cast<T*>(this->m_storage.data); }
|
||||||
|
|
||||||
|
BOOST_CONTAINER_FORCEINLINE const T *get_data_ptr() const
|
||||||
|
{ return reinterpret_cast<T*>(this->m_storage.data); }
|
||||||
|
|
||||||
|
BOOST_CONTAINER_FORCEINLINE internal_type &get_real_data()
|
||||||
|
{ return *reinterpret_cast<internal_type*>(this->m_storage.data); }
|
||||||
|
|
||||||
|
BOOST_CONTAINER_FORCEINLINE const internal_type &get_real_data() const
|
||||||
|
{ return *reinterpret_cast<const internal_type*>(this->m_storage.data); }
|
||||||
|
|
||||||
|
BOOST_CONTAINER_FORCEINLINE internal_type *get_real_data_ptr()
|
||||||
|
{ return reinterpret_cast<internal_type*>(this->m_storage.data); }
|
||||||
|
|
||||||
|
BOOST_CONTAINER_FORCEINLINE const internal_type *get_real_data_ptr() const
|
||||||
|
{ return reinterpret_cast<internal_type*>(this->m_storage.data); }
|
||||||
|
|
||||||
|
BOOST_CONTAINER_FORCEINLINE ~tree_node()
|
||||||
|
{ reinterpret_cast<internal_type*>(this->m_storage.data)->~internal_type(); }
|
||||||
|
|
||||||
|
#if defined(BOOST_CONTAINER_DISABLE_ALIASING_WARNING)
|
||||||
|
#pragma GCC diagnostic pop
|
||||||
|
#undef BOOST_CONTAINER_DISABLE_ALIASING_WARNING
|
||||||
|
# endif
|
||||||
|
|
||||||
|
BOOST_CONTAINER_FORCEINLINE void destroy_header()
|
||||||
|
{ static_cast<hook_type*>(this)->~hook_type(); }
|
||||||
|
|
||||||
template<class T1, class T2>
|
template<class T1, class T2>
|
||||||
BOOST_CONTAINER_FORCEINLINE void do_assign(const std::pair<const T1, T2> &p)
|
BOOST_CONTAINER_FORCEINLINE void do_assign(const std::pair<const T1, T2> &p)
|
||||||
{
|
{
|
||||||
const_cast<T1&>(m_data.first) = p.first;
|
const_cast<T1&>(this->get_real_data().first) = p.first;
|
||||||
m_data.second = p.second;
|
this->get_real_data().second = p.second;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class T1, class T2>
|
template<class T1, class T2>
|
||||||
BOOST_CONTAINER_FORCEINLINE void do_assign(const pair<const T1, T2> &p)
|
BOOST_CONTAINER_FORCEINLINE void do_assign(const pair<const T1, T2> &p)
|
||||||
{
|
{
|
||||||
const_cast<T1&>(m_data.first) = p.first;
|
const_cast<T1&>(this->get_real_data().first) = p.first;
|
||||||
m_data.second = p.second;
|
this->get_real_data().second = p.second;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class V>
|
template<class V>
|
||||||
BOOST_CONTAINER_FORCEINLINE void do_assign(const V &v)
|
BOOST_CONTAINER_FORCEINLINE void do_assign(const V &v)
|
||||||
{ m_data = v; }
|
{ this->get_real_data() = v; }
|
||||||
|
|
||||||
template<class T1, class T2>
|
template<class T1, class T2>
|
||||||
BOOST_CONTAINER_FORCEINLINE void do_move_assign(std::pair<const T1, T2> &p)
|
BOOST_CONTAINER_FORCEINLINE void do_move_assign(std::pair<const T1, T2> &p)
|
||||||
{
|
{
|
||||||
const_cast<T1&>(m_data.first) = ::boost::move(p.first);
|
const_cast<T1&>(this->get_real_data().first) = ::boost::move(p.first);
|
||||||
m_data.second = ::boost::move(p.second);
|
this->get_real_data().second = ::boost::move(p.second);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class T1, class T2>
|
template<class T1, class T2>
|
||||||
BOOST_CONTAINER_FORCEINLINE void do_move_assign(pair<const T1, T2> &p)
|
BOOST_CONTAINER_FORCEINLINE void do_move_assign(pair<const T1, T2> &p)
|
||||||
{
|
{
|
||||||
const_cast<T1&>(m_data.first) = ::boost::move(p.first);
|
const_cast<T1&>(this->get_real_data().first) = ::boost::move(p.first);
|
||||||
m_data.second = ::boost::move(p.second);
|
this->get_real_data().second = ::boost::move(p.second);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class V>
|
template<class V>
|
||||||
BOOST_CONTAINER_FORCEINLINE void do_move_assign(V &v)
|
BOOST_CONTAINER_FORCEINLINE void do_move_assign(V &v)
|
||||||
{ m_data = ::boost::move(v); }
|
{ this->get_real_data() = ::boost::move(v); }
|
||||||
};
|
};
|
||||||
|
|
||||||
template <class T, class VoidPointer, boost::container::tree_type_enum tree_type_value, bool OptimizeSize>
|
template <class T, class VoidPointer, boost::container::tree_type_enum tree_type_value, bool OptimizeSize>
|
||||||
@@ -361,10 +388,10 @@ class RecyclingCloner
|
|||||||
{}
|
{}
|
||||||
|
|
||||||
BOOST_CONTAINER_FORCEINLINE static void do_assign(node_ptr_type &p, const node_t &other, bool_<true>)
|
BOOST_CONTAINER_FORCEINLINE static void do_assign(node_ptr_type &p, const node_t &other, bool_<true>)
|
||||||
{ p->do_move_assign(const_cast<node_t &>(other).m_data); }
|
{ p->do_move_assign(const_cast<node_t &>(other).get_real_data()); }
|
||||||
|
|
||||||
BOOST_CONTAINER_FORCEINLINE static void do_assign(node_ptr_type &p, const node_t &other, bool_<false>)
|
BOOST_CONTAINER_FORCEINLINE static void do_assign(node_ptr_type &p, const node_t &other, bool_<false>)
|
||||||
{ p->do_assign(other.m_data); }
|
{ p->do_assign(other.get_real_data()); }
|
||||||
|
|
||||||
node_ptr_type operator()(const node_t &other) const
|
node_ptr_type operator()(const node_t &other) const
|
||||||
{
|
{
|
||||||
@@ -386,7 +413,7 @@ class RecyclingCloner
|
|||||||
BOOST_CATCH_END
|
BOOST_CATCH_END
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
return m_holder.create_node(other.m_data);
|
return m_holder.create_node(other.get_real_data());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -71,20 +71,54 @@ template <class T, class VoidPointer>
|
|||||||
struct list_node
|
struct list_node
|
||||||
: public list_hook<VoidPointer>::type
|
: public list_hook<VoidPointer>::type
|
||||||
{
|
{
|
||||||
private:
|
|
||||||
list_node();
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
typedef T value_type;
|
typedef T value_type;
|
||||||
|
typedef T internal_type;
|
||||||
typedef typename list_hook<VoidPointer>::type hook_type;
|
typedef typename list_hook<VoidPointer>::type hook_type;
|
||||||
|
|
||||||
T m_data;
|
typedef typename aligned_storage<sizeof(T), alignment_of<T>::value>::type storage_t;
|
||||||
|
storage_t m_storage;
|
||||||
|
|
||||||
T &get_data()
|
#if defined(BOOST_GCC) && (BOOST_GCC >= 40600) && (BOOST_GCC < 80000)
|
||||||
{ return this->m_data; }
|
#pragma GCC diagnostic push
|
||||||
|
#pragma GCC diagnostic ignored "-Wstrict-aliasing"
|
||||||
|
#define BOOST_CONTAINER_DISABLE_ALIASING_WARNING
|
||||||
|
# endif
|
||||||
|
|
||||||
const T &get_data() const
|
BOOST_CONTAINER_FORCEINLINE T &get_data()
|
||||||
{ return this->m_data; }
|
{ return *reinterpret_cast<T*>(this->m_storage.data); }
|
||||||
|
|
||||||
|
BOOST_CONTAINER_FORCEINLINE const T &get_data() const
|
||||||
|
{ return *reinterpret_cast<const T*>(this->m_storage.data); }
|
||||||
|
|
||||||
|
BOOST_CONTAINER_FORCEINLINE T *get_data_ptr()
|
||||||
|
{ return reinterpret_cast<T*>(this->m_storage.data); }
|
||||||
|
|
||||||
|
BOOST_CONTAINER_FORCEINLINE const T *get_data_ptr() const
|
||||||
|
{ return reinterpret_cast<T*>(this->m_storage.data); }
|
||||||
|
|
||||||
|
BOOST_CONTAINER_FORCEINLINE internal_type &get_real_data()
|
||||||
|
{ return *reinterpret_cast<internal_type*>(this->m_storage.data); }
|
||||||
|
|
||||||
|
BOOST_CONTAINER_FORCEINLINE const internal_type &get_real_data() const
|
||||||
|
{ return *reinterpret_cast<const internal_type*>(this->m_storage.data); }
|
||||||
|
|
||||||
|
BOOST_CONTAINER_FORCEINLINE internal_type *get_real_data_ptr()
|
||||||
|
{ return reinterpret_cast<internal_type*>(this->m_storage.data); }
|
||||||
|
|
||||||
|
BOOST_CONTAINER_FORCEINLINE const internal_type *get_real_data_ptr() const
|
||||||
|
{ return reinterpret_cast<internal_type*>(this->m_storage.data); }
|
||||||
|
|
||||||
|
BOOST_CONTAINER_FORCEINLINE ~list_node()
|
||||||
|
{ reinterpret_cast<T*>(this->m_storage.data)->~T(); }
|
||||||
|
|
||||||
|
#if defined(BOOST_CONTAINER_DISABLE_ALIASING_WARNING)
|
||||||
|
#pragma GCC diagnostic pop
|
||||||
|
#undef BOOST_CONTAINER_DISABLE_ALIASING_WARNING
|
||||||
|
# endif
|
||||||
|
|
||||||
|
BOOST_CONTAINER_FORCEINLINE void destroy_header()
|
||||||
|
{ static_cast<hook_type*>(this)->~hook_type(); }
|
||||||
};
|
};
|
||||||
|
|
||||||
template <class T, class VoidPointer>
|
template <class T, class VoidPointer>
|
||||||
|
@@ -71,26 +71,62 @@ struct slist_hook
|
|||||||
<dtl::bi::void_pointer<VoidPointer>, dtl::bi::link_mode<dtl::bi::normal_link> >::type type;
|
<dtl::bi::void_pointer<VoidPointer>, dtl::bi::link_mode<dtl::bi::normal_link> >::type type;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
template <class T, class VoidPointer>
|
template <class T, class VoidPointer>
|
||||||
struct slist_node
|
struct slist_node
|
||||||
: public slist_hook<VoidPointer>::type
|
: public slist_hook<VoidPointer>::type
|
||||||
{
|
{
|
||||||
private:
|
|
||||||
slist_node();
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
typedef T value_type;
|
typedef T value_type;
|
||||||
|
typedef T internal_type;
|
||||||
typedef typename slist_hook<VoidPointer>::type hook_type;
|
typedef typename slist_hook<VoidPointer>::type hook_type;
|
||||||
|
|
||||||
T m_data;
|
typedef typename aligned_storage<sizeof(T), alignment_of<T>::value>::type storage_t;
|
||||||
|
storage_t m_storage;
|
||||||
|
|
||||||
T &get_data()
|
#if defined(BOOST_GCC) && (BOOST_GCC >= 40600) && (BOOST_GCC < 80000)
|
||||||
{ return this->m_data; }
|
#pragma GCC diagnostic push
|
||||||
|
#pragma GCC diagnostic ignored "-Wstrict-aliasing"
|
||||||
|
#define BOOST_CONTAINER_DISABLE_ALIASING_WARNING
|
||||||
|
# endif
|
||||||
|
|
||||||
const T &get_data() const
|
BOOST_CONTAINER_FORCEINLINE T &get_data()
|
||||||
{ return this->m_data; }
|
{ return *reinterpret_cast<T*>(this->m_storage.data); }
|
||||||
|
|
||||||
|
BOOST_CONTAINER_FORCEINLINE const T &get_data() const
|
||||||
|
{ return *reinterpret_cast<const T*>(this->m_storage.data); }
|
||||||
|
|
||||||
|
BOOST_CONTAINER_FORCEINLINE T *get_data_ptr()
|
||||||
|
{ return reinterpret_cast<T*>(this->m_storage.data); }
|
||||||
|
|
||||||
|
BOOST_CONTAINER_FORCEINLINE const T *get_data_ptr() const
|
||||||
|
{ return reinterpret_cast<T*>(this->m_storage.data); }
|
||||||
|
|
||||||
|
BOOST_CONTAINER_FORCEINLINE internal_type &get_real_data()
|
||||||
|
{ return *reinterpret_cast<internal_type*>(this->m_storage.data); }
|
||||||
|
|
||||||
|
BOOST_CONTAINER_FORCEINLINE const internal_type &get_real_data() const
|
||||||
|
{ return *reinterpret_cast<const internal_type*>(this->m_storage.data); }
|
||||||
|
|
||||||
|
BOOST_CONTAINER_FORCEINLINE internal_type *get_real_data_ptr()
|
||||||
|
{ return reinterpret_cast<internal_type*>(this->m_storage.data); }
|
||||||
|
|
||||||
|
BOOST_CONTAINER_FORCEINLINE const internal_type *get_real_data_ptr() const
|
||||||
|
{ return reinterpret_cast<internal_type*>(this->m_storage.data); }
|
||||||
|
|
||||||
|
BOOST_CONTAINER_FORCEINLINE ~slist_node()
|
||||||
|
{ reinterpret_cast<T*>(this->m_storage.data)->~T(); }
|
||||||
|
|
||||||
|
#if defined(BOOST_CONTAINER_DISABLE_ALIASING_WARNING)
|
||||||
|
#pragma GCC diagnostic pop
|
||||||
|
#undef BOOST_CONTAINER_DISABLE_ALIASING_WARNING
|
||||||
|
# endif
|
||||||
|
|
||||||
|
BOOST_CONTAINER_FORCEINLINE void destroy_header()
|
||||||
|
{ static_cast<hook_type*>(this)->~hook_type(); }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
template <class T, class VoidPointer>
|
template <class T, class VoidPointer>
|
||||||
struct iiterator_node_value_type< slist_node<T,VoidPointer> > {
|
struct iiterator_node_value_type< slist_node<T,VoidPointer> > {
|
||||||
typedef T type;
|
typedef T type;
|
||||||
|
@@ -114,12 +114,14 @@ struct node_base
|
|||||||
typedef typename void_ptr_traits::
|
typedef typename void_ptr_traits::
|
||||||
template rebind_pointer
|
template rebind_pointer
|
||||||
<node_base>::type node_base_ptr;
|
<node_base>::type node_base_ptr;
|
||||||
|
|
||||||
|
public:
|
||||||
typedef typename void_ptr_traits::
|
typedef typename void_ptr_traits::
|
||||||
template rebind_pointer
|
template rebind_pointer
|
||||||
<node_base_ptr>::type node_base_ptr_ptr;
|
<node_base_ptr>::type node_base_ptr_ptr;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
node_base(const node_base_ptr_ptr &n)
|
explicit node_base(const node_base_ptr_ptr &n)
|
||||||
: up(n)
|
: up(n)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
@@ -130,6 +132,7 @@ struct node_base
|
|||||||
node_base_ptr_ptr up;
|
node_base_ptr_ptr up;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
template<typename Pointer>
|
template<typename Pointer>
|
||||||
struct node
|
struct node
|
||||||
: public node_base
|
: public node_base
|
||||||
@@ -137,11 +140,52 @@ struct node
|
|||||||
rebind_pointer<void>::type
|
rebind_pointer<void>::type
|
||||||
>
|
>
|
||||||
{
|
{
|
||||||
private:
|
|
||||||
node();
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
typename ::boost::intrusive::pointer_traits<Pointer>::element_type value;
|
typedef typename ::boost::intrusive::pointer_traits<Pointer>::element_type T;
|
||||||
|
typedef node_base
|
||||||
|
<typename ::boost::intrusive::pointer_traits<Pointer>::template
|
||||||
|
rebind_pointer<void>::type
|
||||||
|
> hook_type;
|
||||||
|
|
||||||
|
typedef typename boost::container::dtl::aligned_storage
|
||||||
|
<sizeof(T), boost::container::dtl::alignment_of<T>::value>::type storage_t;
|
||||||
|
storage_t m_storage;
|
||||||
|
|
||||||
|
BOOST_CONTAINER_FORCEINLINE explicit node(const typename hook_type::node_base_ptr_ptr &n)
|
||||||
|
: hook_type(n)
|
||||||
|
{}
|
||||||
|
|
||||||
|
BOOST_CONTAINER_FORCEINLINE node()
|
||||||
|
{}
|
||||||
|
|
||||||
|
#if defined(BOOST_GCC) && (BOOST_GCC >= 40600) && (BOOST_GCC < 80000)
|
||||||
|
#pragma GCC diagnostic push
|
||||||
|
#pragma GCC diagnostic ignored "-Wstrict-aliasing"
|
||||||
|
#define BOOST_CONTAINER_DISABLE_ALIASING_WARNING
|
||||||
|
# endif
|
||||||
|
|
||||||
|
BOOST_CONTAINER_FORCEINLINE T &get_data()
|
||||||
|
{ return *reinterpret_cast<T*>(this->m_storage.data); }
|
||||||
|
|
||||||
|
BOOST_CONTAINER_FORCEINLINE const T &get_data() const
|
||||||
|
{ return *reinterpret_cast<const T*>(this->m_storage.data); }
|
||||||
|
|
||||||
|
BOOST_CONTAINER_FORCEINLINE T *get_data_ptr()
|
||||||
|
{ return reinterpret_cast<T*>(this->m_storage.data); }
|
||||||
|
|
||||||
|
BOOST_CONTAINER_FORCEINLINE const T *get_data_ptr() const
|
||||||
|
{ return reinterpret_cast<T*>(this->m_storage.data); }
|
||||||
|
|
||||||
|
BOOST_CONTAINER_FORCEINLINE ~node()
|
||||||
|
{ reinterpret_cast<T*>(this->m_storage.data)->~T(); }
|
||||||
|
|
||||||
|
#if defined(BOOST_CONTAINER_DISABLE_ALIASING_WARNING)
|
||||||
|
#pragma GCC diagnostic pop
|
||||||
|
#undef BOOST_CONTAINER_DISABLE_ALIASING_WARNING
|
||||||
|
# endif
|
||||||
|
|
||||||
|
BOOST_CONTAINER_FORCEINLINE void destroy_header()
|
||||||
|
{ static_cast<hook_type*>(this)->~hook_type(); }
|
||||||
};
|
};
|
||||||
|
|
||||||
template<class VoidPtr, class VoidAllocator>
|
template<class VoidPtr, class VoidAllocator>
|
||||||
@@ -290,7 +334,7 @@ class stable_vector_iterator
|
|||||||
public:
|
public:
|
||||||
//Pointer like operators
|
//Pointer like operators
|
||||||
reference operator*() const BOOST_NOEXCEPT_OR_NOTHROW
|
reference operator*() const BOOST_NOEXCEPT_OR_NOTHROW
|
||||||
{ return node_pointer()->value; }
|
{ return node_pointer()->get_data(); }
|
||||||
|
|
||||||
pointer operator->() const BOOST_NOEXCEPT_OR_NOTHROW
|
pointer operator->() const BOOST_NOEXCEPT_OR_NOTHROW
|
||||||
{ return ptr_traits::pointer_to(this->operator*()); }
|
{ return ptr_traits::pointer_to(this->operator*()); }
|
||||||
@@ -317,7 +361,7 @@ class stable_vector_iterator
|
|||||||
{ stable_vector_iterator tmp(*this); --*this; return stable_vector_iterator(tmp); }
|
{ stable_vector_iterator tmp(*this); --*this; return stable_vector_iterator(tmp); }
|
||||||
|
|
||||||
reference operator[](difference_type off) const BOOST_NOEXCEPT_OR_NOTHROW
|
reference operator[](difference_type off) const BOOST_NOEXCEPT_OR_NOTHROW
|
||||||
{ return node_ptr_traits::static_cast_from(this->m_pn->up[off])->value; }
|
{ return node_ptr_traits::static_cast_from(this->m_pn->up[off])->get_data(); }
|
||||||
|
|
||||||
stable_vector_iterator& operator+=(difference_type off) BOOST_NOEXCEPT_OR_NOTHROW
|
stable_vector_iterator& operator+=(difference_type off) BOOST_NOEXCEPT_OR_NOTHROW
|
||||||
{
|
{
|
||||||
@@ -1198,7 +1242,7 @@ class stable_vector
|
|||||||
reference front() BOOST_NOEXCEPT_OR_NOTHROW
|
reference front() BOOST_NOEXCEPT_OR_NOTHROW
|
||||||
{
|
{
|
||||||
BOOST_ASSERT(!this->empty());
|
BOOST_ASSERT(!this->empty());
|
||||||
return static_cast<node_reference>(*this->index.front()).value;
|
return static_cast<node_reference>(*this->index.front()).get_data();
|
||||||
}
|
}
|
||||||
|
|
||||||
//! <b>Requires</b>: !empty()
|
//! <b>Requires</b>: !empty()
|
||||||
@@ -1212,7 +1256,7 @@ class stable_vector
|
|||||||
const_reference front() const BOOST_NOEXCEPT_OR_NOTHROW
|
const_reference front() const BOOST_NOEXCEPT_OR_NOTHROW
|
||||||
{
|
{
|
||||||
BOOST_ASSERT(!this->empty());
|
BOOST_ASSERT(!this->empty());
|
||||||
return static_cast<const_node_reference>(*this->index.front()).value;
|
return static_cast<const_node_reference>(*this->index.front()).get_data();
|
||||||
}
|
}
|
||||||
|
|
||||||
//! <b>Requires</b>: !empty()
|
//! <b>Requires</b>: !empty()
|
||||||
@@ -1226,7 +1270,7 @@ class stable_vector
|
|||||||
reference back() BOOST_NOEXCEPT_OR_NOTHROW
|
reference back() BOOST_NOEXCEPT_OR_NOTHROW
|
||||||
{
|
{
|
||||||
BOOST_ASSERT(!this->empty());
|
BOOST_ASSERT(!this->empty());
|
||||||
return static_cast<node_reference>(*this->index[this->size()-1u]).value;
|
return static_cast<node_reference>(*this->index[this->size()-1u]).get_data();
|
||||||
}
|
}
|
||||||
|
|
||||||
//! <b>Requires</b>: !empty()
|
//! <b>Requires</b>: !empty()
|
||||||
@@ -1240,7 +1284,7 @@ class stable_vector
|
|||||||
const_reference back() const BOOST_NOEXCEPT_OR_NOTHROW
|
const_reference back() const BOOST_NOEXCEPT_OR_NOTHROW
|
||||||
{
|
{
|
||||||
BOOST_ASSERT(!this->empty());
|
BOOST_ASSERT(!this->empty());
|
||||||
return static_cast<const_node_reference>(*this->index[this->size()-1u]).value;
|
return static_cast<const_node_reference>(*this->index[this->size()-1u]).get_data();
|
||||||
}
|
}
|
||||||
|
|
||||||
//! <b>Requires</b>: size() > n.
|
//! <b>Requires</b>: size() > n.
|
||||||
@@ -1254,7 +1298,7 @@ class stable_vector
|
|||||||
reference operator[](size_type n) BOOST_NOEXCEPT_OR_NOTHROW
|
reference operator[](size_type n) BOOST_NOEXCEPT_OR_NOTHROW
|
||||||
{
|
{
|
||||||
BOOST_ASSERT(this->size() > n);
|
BOOST_ASSERT(this->size() > n);
|
||||||
return static_cast<node_reference>(*this->index[n]).value;
|
return static_cast<node_reference>(*this->index[n]).get_data();
|
||||||
}
|
}
|
||||||
|
|
||||||
//! <b>Requires</b>: size() > n.
|
//! <b>Requires</b>: size() > n.
|
||||||
@@ -1268,7 +1312,7 @@ class stable_vector
|
|||||||
const_reference operator[](size_type n) const BOOST_NOEXCEPT_OR_NOTHROW
|
const_reference operator[](size_type n) const BOOST_NOEXCEPT_OR_NOTHROW
|
||||||
{
|
{
|
||||||
BOOST_ASSERT(this->size() > n);
|
BOOST_ASSERT(this->size() > n);
|
||||||
return static_cast<const_node_reference>(*this->index[n]).value;
|
return static_cast<const_node_reference>(*this->index[n]).get_data();
|
||||||
}
|
}
|
||||||
|
|
||||||
//! <b>Requires</b>: size() >= n.
|
//! <b>Requires</b>: size() >= n.
|
||||||
@@ -1956,8 +2000,7 @@ class stable_vector
|
|||||||
void priv_destroy_node(const node_type &n)
|
void priv_destroy_node(const node_type &n)
|
||||||
{
|
{
|
||||||
allocator_traits<node_allocator_type>::
|
allocator_traits<node_allocator_type>::
|
||||||
destroy(this->priv_node_alloc(), dtl::addressof(n.value));
|
destroy(this->priv_node_alloc(), &n);
|
||||||
static_cast<const node_base_type*>(&n)->~node_base_type();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void priv_delete_node(const node_ptr &n)
|
void priv_delete_node(const node_ptr &n)
|
||||||
@@ -1969,26 +2012,40 @@ class stable_vector
|
|||||||
template<class Iterator>
|
template<class Iterator>
|
||||||
void priv_build_node_from_it(const node_ptr &p, const index_iterator &up_index, const Iterator &it)
|
void priv_build_node_from_it(const node_ptr &p, const index_iterator &up_index, const Iterator &it)
|
||||||
{
|
{
|
||||||
//This can throw
|
node_type *praw = ::new(boost::movelib::iterator_to_raw_pointer(p), boost_container_new_t())
|
||||||
boost::container::construct_in_place
|
node_type(index_traits_type::ptr_to_node_base_ptr(*up_index));
|
||||||
( this->priv_node_alloc()
|
BOOST_TRY{
|
||||||
, dtl::addressof(p->value)
|
//This can throw
|
||||||
, it);
|
boost::container::construct_in_place
|
||||||
//This does not throw
|
( this->priv_node_alloc()
|
||||||
::new(static_cast<node_base_type*>(boost::movelib::to_raw_pointer(p)), boost_container_new_t())
|
, praw->get_data_ptr()
|
||||||
node_base_type(index_traits_type::ptr_to_node_base_ptr(*up_index));
|
, it);
|
||||||
|
}
|
||||||
|
BOOST_CATCH(...) {
|
||||||
|
praw->destroy_header();
|
||||||
|
this->priv_node_alloc().deallocate(p, 1);
|
||||||
|
BOOST_RETHROW
|
||||||
|
}
|
||||||
|
BOOST_CATCH_END
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class ValueConvertible>
|
template<class ValueConvertible>
|
||||||
void priv_build_node_from_convertible(const node_ptr &p, BOOST_FWD_REF(ValueConvertible) value_convertible)
|
void priv_build_node_from_convertible(const node_ptr &p, BOOST_FWD_REF(ValueConvertible) value_convertible)
|
||||||
{
|
{
|
||||||
//This can throw
|
node_type *praw = ::new(boost::movelib::iterator_to_raw_pointer(p), boost_container_new_t()) node_type;
|
||||||
boost::container::allocator_traits<node_allocator_type>::construct
|
BOOST_TRY{
|
||||||
( this->priv_node_alloc()
|
//This can throw
|
||||||
, dtl::addressof(p->value)
|
boost::container::allocator_traits<node_allocator_type>::construct
|
||||||
, ::boost::forward<ValueConvertible>(value_convertible));
|
( this->priv_node_alloc()
|
||||||
//This does not throw
|
, p->get_data_ptr()
|
||||||
::new(static_cast<node_base_type*>(boost::movelib::to_raw_pointer(p)), boost_container_new_t()) node_base_type;
|
, ::boost::forward<ValueConvertible>(value_convertible));
|
||||||
|
}
|
||||||
|
BOOST_CATCH(...) {
|
||||||
|
praw->destroy_header();
|
||||||
|
this->priv_node_alloc().deallocate(p, 1);
|
||||||
|
BOOST_RETHROW
|
||||||
|
}
|
||||||
|
BOOST_CATCH_END
|
||||||
}
|
}
|
||||||
|
|
||||||
void priv_swap_members(stable_vector &x)
|
void priv_swap_members(stable_vector &x)
|
||||||
|
@@ -1352,7 +1352,11 @@ class vector
|
|||||||
//!
|
//!
|
||||||
//! <b>Complexity</b>: Constant.
|
//! <b>Complexity</b>: Constant.
|
||||||
BOOST_CONTAINER_FORCEINLINE iterator end() BOOST_NOEXCEPT_OR_NOTHROW
|
BOOST_CONTAINER_FORCEINLINE iterator end() BOOST_NOEXCEPT_OR_NOTHROW
|
||||||
{ return iterator(this->m_holder.start() + this->m_holder.m_size); }
|
{
|
||||||
|
pointer const bg = this->m_holder.start();
|
||||||
|
size_type const sz = this->m_holder.m_size;
|
||||||
|
return iterator(BOOST_LIKELY(sz) ? bg + sz : bg); //Avoid UB on null-pointer arithmetic
|
||||||
|
}
|
||||||
|
|
||||||
//! <b>Effects</b>: Returns a const_iterator to the end of the vector.
|
//! <b>Effects</b>: Returns a const_iterator to the end of the vector.
|
||||||
//!
|
//!
|
||||||
@@ -1412,7 +1416,12 @@ class vector
|
|||||||
//!
|
//!
|
||||||
//! <b>Complexity</b>: Constant.
|
//! <b>Complexity</b>: Constant.
|
||||||
BOOST_CONTAINER_FORCEINLINE const_iterator cend() const BOOST_NOEXCEPT_OR_NOTHROW
|
BOOST_CONTAINER_FORCEINLINE const_iterator cend() const BOOST_NOEXCEPT_OR_NOTHROW
|
||||||
{ return const_iterator(this->m_holder.start() + this->m_holder.m_size); }
|
{
|
||||||
|
pointer const bg = this->m_holder.start();
|
||||||
|
size_type const sz = this->m_holder.m_size;
|
||||||
|
return const_iterator(BOOST_LIKELY(sz) ? bg + sz : bg); //Avoid UB on null-pointer arithmetic
|
||||||
|
}
|
||||||
|
//{ return const_iterator(this->m_holder.start() + this->m_holder.m_size); }
|
||||||
|
|
||||||
//! <b>Effects</b>: Returns a const_reverse_iterator pointing to the beginning
|
//! <b>Effects</b>: Returns a const_reverse_iterator pointing to the beginning
|
||||||
//! of the reversed vector.
|
//! of the reversed vector.
|
||||||
@@ -2037,9 +2046,10 @@ class vector
|
|||||||
//! plus linear to the elements between pos and the last element.
|
//! plus linear to the elements between pos and the last element.
|
||||||
iterator erase(const_iterator first, const_iterator last)
|
iterator erase(const_iterator first, const_iterator last)
|
||||||
{
|
{
|
||||||
BOOST_ASSERT(first == last ||
|
|
||||||
(first < last && this->priv_in_range(first) && this->priv_in_range_or_end(last)));
|
|
||||||
if (first != last){
|
if (first != last){
|
||||||
|
BOOST_ASSERT(this->priv_in_range(first));
|
||||||
|
BOOST_ASSERT(this->priv_in_range_or_end(last));
|
||||||
|
BOOST_ASSERT(first < last);
|
||||||
T* const old_end_ptr = this->priv_raw_end();
|
T* const old_end_ptr = this->priv_raw_end();
|
||||||
T* const first_ptr = boost::movelib::to_raw_pointer(vector_iterator_get_ptr(first));
|
T* const first_ptr = boost::movelib::to_raw_pointer(vector_iterator_get_ptr(first));
|
||||||
T* const last_ptr = boost::movelib::to_raw_pointer(vector_iterator_get_ptr(last));
|
T* const last_ptr = boost::movelib::to_raw_pointer(vector_iterator_get_ptr(last));
|
||||||
|
Reference in New Issue
Block a user