* Improved vector's insertion performance.

*  Changed again experimental multiallocation interface for better performance (still experimental).
*  Added no exception support for those willing to disable exceptions in their compilers.
*  Fixed GCC -Wshadow warnings.
*  Replaced deprecated BOOST_NO_XXXX with newer BOOST_NO_CXX11_XXX macros.


[SVN r81518]
This commit is contained in:
Ion Gaztañaga
2012-11-24 21:08:18 +00:00
parent a75d72d03c
commit bc5c91bb79
28 changed files with 2449 additions and 1892 deletions
+107 -146
View File
@@ -1,4 +1,4 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2008-2012. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
@@ -29,15 +29,16 @@
#include <boost/mpl/bool.hpp>
#include <boost/mpl/not.hpp>
#include <boost/assert.hpp>
#include <boost/type_traits/is_integral.hpp>
#include <boost/container/detail/version_type.hpp>
#include <boost/container/detail/multiallocation_chain.hpp>
#include <boost/container/detail/allocator_version_traits.hpp>
#include <boost/container/detail/utilities.hpp>
#include <boost/container/detail/iterators.hpp>
#include <boost/container/detail/algorithms.hpp>
#include <boost/container/allocator_traits.hpp>
#include <boost/intrusive/pointer_traits.hpp>
#include <boost/aligned_storage.hpp>
#include <boost/move/utility.hpp>
#include <boost/move/iterator.hpp>
#include <boost/move/detail/move_helpers.hpp>
#include <algorithm> //max
#include <stdexcept>
#include <memory>
@@ -303,7 +304,7 @@ struct index_traits
static const size_type ExtraPointers = 3;
//Stable vector stores metadata at the end of the index (node_base_ptr vector) with additional 3 pointers:
// back() is this->index.back() - ExtraPointers;
// end node index is *(this->index.end() -3)
// end node index is *(this->index.end() - 3)
// Node cache first is *(this->index.end() - 2);
// Node cache last is this->index.back();
@@ -366,89 +367,6 @@ struct index_traits
#endif //STABLE_VECTOR_ENABLE_INVARIANT_CHECKING
};
template<class Allocator, unsigned Version = boost::container::container_detail::version<Allocator>::value>
struct allocator_version_wrapper
{
typedef ::boost::container::container_detail::integral_constant
<unsigned, Version> alloc_version;
typedef typename Allocator::multiallocation_chain multiallocation_chain;
typedef typename boost::container::allocator_traits<Allocator>::pointer pointer;
typedef typename boost::container::allocator_traits<Allocator>::size_type size_type;
static pointer allocate_one(Allocator &a)
{ return a.allocate_one(); }
static void deallocate_one(Allocator &a, const pointer &p)
{ a.deallocate_one(p); }
static multiallocation_chain allocate_individual(Allocator &a, size_type n)
{ return a.allocate_individual(n); }
static void deallocate_individual(Allocator &a, multiallocation_chain &holder)
{ a.deallocate_individual(::boost::move(holder)); }
};
template<class Allocator>
struct allocator_version_wrapper<Allocator, 1>
{
typedef ::boost::container::container_detail::integral_constant
<unsigned, 1> alloc_version;
typedef typename boost::container::allocator_traits<Allocator>::pointer pointer;
typedef typename boost::container::allocator_traits<Allocator>::size_type size_type;
typedef typename boost::container::allocator_traits<Allocator>::value_type value_type;
typedef typename boost::intrusive::pointer_traits<pointer>::
template rebind_pointer<void>::type void_ptr;
typedef container_detail::basic_multiallocation_chain
<void_ptr> multialloc_cached_counted;
typedef boost::container::container_detail::
transform_multiallocation_chain
< multialloc_cached_counted, value_type> multiallocation_chain;
static pointer allocate_one(Allocator &a)
{ return a.allocate(1); }
static void deallocate_one(Allocator &a, const pointer &p)
{ a.deallocate(p, 1); }
static void deallocate_individual(Allocator &a, multiallocation_chain &holder)
{
while(!holder.empty()){
a.deallocate(holder.pop_front(), 1);
}
}
struct allocate_individual_rollback
{
allocate_individual_rollback(Allocator &a, multiallocation_chain &chain)
: mr_a(a), mr_chain(chain)
{}
~allocate_individual_rollback()
{
allocator_version_wrapper::deallocate_individual(mr_a, mr_chain);
}
Allocator &mr_a;
multiallocation_chain &mr_chain;
};
static multiallocation_chain allocate_individual(Allocator &a, size_type n)
{
multiallocation_chain m;
multiallocation_chain m_ret;
allocate_individual_rollback rollback(a, m);
while(n--){
m.push_front(a.allocate(1));
}
m.swap(m_ret);
return ::boost::move(m_ret);
}
};
} //namespace stable_vector_detail
#if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
@@ -555,20 +473,21 @@ class stable_vector
template portable_rebind_alloc
<node_type>::type node_allocator_type;
typedef stable_vector_detail::allocator_version_wrapper<node_allocator_type> allocator_version_wrapper_t;
typedef typename allocator_version_wrapper_t::multiallocation_chain multiallocation_chain;
typedef ::boost::container::container_detail::
allocator_version_traits<node_allocator_type> allocator_version_traits_t;
typedef typename allocator_version_traits_t::multiallocation_chain multiallocation_chain;
node_ptr allocate_one()
{ return allocator_version_wrapper_t::allocate_one(this->priv_node_alloc()); }
{ return allocator_version_traits_t::allocate_one(this->priv_node_alloc()); }
void deallocate_one(const node_ptr &p)
{ allocator_version_wrapper_t::deallocate_one(this->priv_node_alloc(), p); }
{ allocator_version_traits_t::deallocate_one(this->priv_node_alloc(), p); }
multiallocation_chain allocate_individual(typename allocator_traits_type::size_type n)
{ return allocator_version_wrapper_t::allocate_individual(this->priv_node_alloc(), n); }
void allocate_individual(typename allocator_traits_type::size_type n, multiallocation_chain &m)
{ allocator_version_traits_t::allocate_individual(this->priv_node_alloc(), n, m); }
void deallocate_individual(multiallocation_chain &holder)
{ allocator_version_wrapper_t::deallocate_individual(this->priv_node_alloc(), holder); }
{ allocator_version_traits_t::deallocate_individual(this->priv_node_alloc(), holder); }
friend class stable_vector_detail::clear_on_destroy<stable_vector>;
typedef stable_vector_detail::iterator
@@ -633,10 +552,10 @@ class stable_vector
//! <b>Effects</b>: Constructs a stable_vector taking the allocator as parameter.
//!
//! <b>Throws</b>: If allocator_type's copy constructor throws.
//! <b>Throws</b>: Nothing
//!
//! <b>Complexity</b>: Constant.
explicit stable_vector(const allocator_type& al)
explicit stable_vector(const allocator_type& al) BOOST_CONTAINER_NOEXCEPT
: internal_data(al), index(al)
{
STABLE_VECTOR_CHECK_INVARIANT;
@@ -904,7 +823,7 @@ class stable_vector
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
iterator begin()
iterator begin() BOOST_CONTAINER_NOEXCEPT
{ return (this->index.empty()) ? this->end(): iterator(node_ptr_traits::static_cast_from(this->index.front())); }
//! <b>Effects</b>: Returns a const_iterator to the first element contained in the stable_vector.
@@ -912,7 +831,7 @@ class stable_vector
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
const_iterator begin()const
const_iterator begin() const BOOST_CONTAINER_NOEXCEPT
{ return (this->index.empty()) ? this->cend() : const_iterator(node_ptr_traits::static_cast_from(this->index.front())) ; }
//! <b>Effects</b>: Returns an iterator to the end of the stable_vector.
@@ -920,7 +839,7 @@ class stable_vector
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
iterator end()
iterator end() BOOST_CONTAINER_NOEXCEPT
{ return iterator(this->priv_get_end_node()); }
//! <b>Effects</b>: Returns a const_iterator to the end of the stable_vector.
@@ -928,7 +847,7 @@ class stable_vector
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
const_iterator end() const
const_iterator end() const BOOST_CONTAINER_NOEXCEPT
{ return const_iterator(this->priv_get_end_node()); }
//! <b>Effects</b>: Returns a reverse_iterator pointing to the beginning
@@ -937,7 +856,7 @@ class stable_vector
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
reverse_iterator rbegin()
reverse_iterator rbegin() BOOST_CONTAINER_NOEXCEPT
{ return reverse_iterator(this->end()); }
//! <b>Effects</b>: Returns a const_reverse_iterator pointing to the beginning
@@ -946,7 +865,7 @@ class stable_vector
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
const_reverse_iterator rbegin() const
const_reverse_iterator rbegin() const BOOST_CONTAINER_NOEXCEPT
{ return const_reverse_iterator(this->end()); }
//! <b>Effects</b>: Returns a reverse_iterator pointing to the end
@@ -955,7 +874,7 @@ class stable_vector
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
reverse_iterator rend()
reverse_iterator rend() BOOST_CONTAINER_NOEXCEPT
{ return reverse_iterator(this->begin()); }
//! <b>Effects</b>: Returns a const_reverse_iterator pointing to the end
@@ -964,7 +883,7 @@ class stable_vector
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
const_reverse_iterator rend()const
const_reverse_iterator rend() const BOOST_CONTAINER_NOEXCEPT
{ return const_reverse_iterator(this->begin()); }
//! <b>Effects</b>: Returns a const_iterator to the first element contained in the stable_vector.
@@ -972,7 +891,7 @@ class stable_vector
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
const_iterator cbegin() const
const_iterator cbegin() const BOOST_CONTAINER_NOEXCEPT
{ return this->begin(); }
//! <b>Effects</b>: Returns a const_iterator to the end of the stable_vector.
@@ -980,7 +899,7 @@ class stable_vector
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
const_iterator cend()const
const_iterator cend() const BOOST_CONTAINER_NOEXCEPT
{ return this->end(); }
//! <b>Effects</b>: Returns a const_reverse_iterator pointing to the beginning
@@ -989,7 +908,7 @@ class stable_vector
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
const_reverse_iterator crbegin() const
const_reverse_iterator crbegin() const BOOST_CONTAINER_NOEXCEPT
{ return this->rbegin(); }
//! <b>Effects</b>: Returns a const_reverse_iterator pointing to the end
@@ -998,7 +917,7 @@ class stable_vector
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
const_reverse_iterator crend()const
const_reverse_iterator crend()const BOOST_CONTAINER_NOEXCEPT
{ return this->rend(); }
//////////////////////////////////////////////
@@ -1012,7 +931,7 @@ class stable_vector
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
bool empty() const
bool empty() const BOOST_CONTAINER_NOEXCEPT
{ return this->index.size() <= ExtraPointers; }
//! <b>Effects</b>: Returns the number of the elements contained in the stable_vector.
@@ -1020,7 +939,7 @@ class stable_vector
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
size_type size() const
size_type size() const BOOST_CONTAINER_NOEXCEPT
{
const size_type index_size = this->index.size();
return index_size ? (index_size - ExtraPointers) : 0;
@@ -1031,7 +950,7 @@ class stable_vector
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
size_type max_size() const
size_type max_size() const BOOST_CONTAINER_NOEXCEPT
{ return this->index.max_size() - ExtraPointers; }
//! <b>Effects</b>: Inserts or erases elements at the end such that
@@ -1071,7 +990,7 @@ class stable_vector
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
size_type capacity() const
size_type capacity() const BOOST_CONTAINER_NOEXCEPT
{
const size_type index_size = this->index.size();
BOOST_ASSERT(!index_size || index_size >= ExtraPointers);
@@ -1094,7 +1013,7 @@ class stable_vector
if(n > this->max_size())
throw std::bad_alloc();
size_type size_ = this->size();
size_type sz = this->size();
size_type old_capacity = this->capacity();
if(n > old_capacity){
index_traits_type::initialize_end_node(this->index, this->internal_data.end_node, n);
@@ -1106,8 +1025,8 @@ class stable_vector
index_traits_type::fix_up_pointers_from(this->index, this->index.begin());
}
//Now fill pool if data is not enough
if((n - size_) > this->internal_data.pool_size){
this->priv_increase_pool((n - size_) - this->internal_data.pool_size);
if((n - sz) > this->internal_data.pool_size){
this->priv_increase_pool((n - sz) - this->internal_data.pool_size);
}
}
}
@@ -1156,7 +1075,7 @@ class stable_vector
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
reference front()
reference front() BOOST_CONTAINER_NOEXCEPT
{ return static_cast<node_reference>(*this->index.front()).value; }
//! <b>Requires</b>: !empty()
@@ -1167,7 +1086,7 @@ class stable_vector
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
const_reference front() const
const_reference front() const BOOST_CONTAINER_NOEXCEPT
{ return static_cast<const_node_reference>(*this->index.front()).value; }
//! <b>Requires</b>: !empty()
@@ -1178,7 +1097,7 @@ class stable_vector
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
reference back()
reference back() BOOST_CONTAINER_NOEXCEPT
{ return static_cast<node_reference>(*this->index[this->size() - ExtraPointers]).value; }
//! <b>Requires</b>: !empty()
@@ -1189,7 +1108,7 @@ class stable_vector
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
const_reference back()const
const_reference back() const BOOST_CONTAINER_NOEXCEPT
{ return static_cast<const_node_reference>(*this->index[this->size() - ExtraPointers]).value; }
//! <b>Requires</b>: size() > n.
@@ -1200,7 +1119,7 @@ class stable_vector
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
reference operator[](size_type n)
reference operator[](size_type n) BOOST_CONTAINER_NOEXCEPT
{ return static_cast<node_reference>(*this->index[n]).value; }
//! <b>Requires</b>: size() > n.
@@ -1211,7 +1130,7 @@ class stable_vector
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
const_reference operator[](size_type n)const
const_reference operator[](size_type n) const BOOST_CONTAINER_NOEXCEPT
{ return static_cast<const_node_reference>(*this->index[n]).value; }
//! <b>Requires</b>: size() > n.
@@ -1400,7 +1319,7 @@ class stable_vector
//!
//! <b>Complexity</b>: Linear to std::distance [first, last).
template <class InputIterator>
iterator insert(const_iterator position,InputIterator first, InputIterator last
iterator insert(const_iterator position, InputIterator first, InputIterator last
#if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
, typename container_detail::enable_if_c
< !container_detail::is_convertible<InputIterator, size_type>::value
@@ -1426,8 +1345,8 @@ class stable_vector
>::type * = 0
)
{
const size_type num_new = (size_type)std::distance(first,last);
const size_type pos = static_cast<size_type>(position - this->cbegin());
const size_type num_new = static_cast<size_type>(std::distance(first, last));
const size_type pos = static_cast<size_type>(position - this->cbegin());
if(num_new){
//Fills the node pool and inserts num_new null pointers in pos.
//If a new buffer was needed fixes up pointers up to pos so
@@ -1463,7 +1382,7 @@ class stable_vector
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant time.
void pop_back()
void pop_back() BOOST_CONTAINER_NOEXCEPT
{ this->erase(--this->cend()); }
//! <b>Effects</b>: Erases the element at position pos.
@@ -1472,15 +1391,15 @@ class stable_vector
//!
//! <b>Complexity</b>: Linear to the elements between pos and the
//! last element. Constant if pos is the last element.
iterator erase(const_iterator position)
iterator erase(const_iterator position) BOOST_CONTAINER_NOEXCEPT
{
STABLE_VECTOR_CHECK_INVARIANT;
difference_type d = position - this->cbegin();
index_iterator it = this->index.begin() + d;
const size_type d = position - this->cbegin();
index_iterator it = this->index.begin() + d;
this->priv_delete_node(position.node_pointer());
it = this->index.erase(it);
index_traits_type::fix_up_pointers_from(this->index, it);
return this->begin()+d;
return iterator(node_ptr_traits::static_cast_from(*it));
}
//! <b>Effects</b>: Erases the elements pointed by [first, last).
@@ -1489,19 +1408,30 @@ class stable_vector
//!
//! <b>Complexity</b>: Linear to the distance between first and last
//! 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_CONTAINER_NOEXCEPT
{
STABLE_VECTOR_CHECK_INVARIANT;
difference_type d1 = first - this->cbegin(), d2 = last - this->cbegin();
if(d1 != d2){
index_iterator it1(this->index.begin() + d1), it2(it1 + (d2 - d1));
for(index_iterator it = it1; it != it2; ++it){
this->priv_delete_node(node_ptr_traits::static_cast_from(*it));
const const_iterator cbeg(this->cbegin());
const size_type d1 = static_cast<size_type>(first - cbeg),
d2 = static_cast<size_type>(last - cbeg);
size_type d_dif = d2 - d1;
if(d_dif){
multiallocation_chain holder;
const index_iterator it1(this->index.begin() + d1);
const index_iterator it2(it1 + d_dif);
index_iterator it(it1);
while(d_dif--){
node_base_ptr &nb = *it;
++it;
node_type &n = *node_ptr_traits::static_cast_from(nb);
this->priv_destroy_node(n);
holder.push_back(node_ptr_traits::pointer_to(n));
}
this->priv_put_in_pool(holder);
const index_iterator e = this->index.erase(it1, it2);
index_traits_type::fix_up_pointers_from(this->index, e);
}
return iterator(this->begin() + d1);
return iterator(last.node_pointer());
}
//! <b>Effects</b>: Swaps the contents of *this and x.
@@ -1524,7 +1454,7 @@ class stable_vector
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Linear to the number of elements in the stable_vector.
void clear()
void clear() BOOST_CONTAINER_NOEXCEPT
{ this->erase(this->cbegin(),this->cend()); }
/// @cond
@@ -1666,7 +1596,8 @@ class stable_vector
, node_ptr_traits::static_cast_from(pool_first_ref)
, node_ptr_traits::static_cast_from(pool_last_ref)
, internal_data.pool_size);
multiallocation_chain m (this->allocate_individual(n));
multiallocation_chain m;
this->allocate_individual(n, m);
holder.splice_after(holder.before_begin(), m, m.before_begin(), m.last(), n);
this->internal_data.pool_size += n;
std::pair<node_ptr, node_ptr> data(holder.extract_data());
@@ -1690,11 +1621,25 @@ class stable_vector
pool_last_ref = ret.second;
}
void priv_put_in_pool(multiallocation_chain &ch)
{
node_base_ptr &pool_first_ref = *(this->index.end()-(ExtraPointers-1));
node_base_ptr &pool_last_ref = this->index.back();
ch.incorporate_after( ch.before_begin()
, node_ptr_traits::static_cast_from(pool_first_ref)
, node_ptr_traits::static_cast_from(pool_last_ref)
, internal_data.pool_size);
this->internal_data.pool_size = ch.size();
const std::pair<node_ptr, node_ptr> ret(ch.extract_data());
pool_first_ref = ret.first;
pool_last_ref = ret.second;
}
node_ptr priv_get_from_pool()
{
//Precondition: index is not empty
BOOST_ASSERT(!this->index.empty());
node_base_ptr &pool_first_ref = *(this->index.end() - 2);
node_base_ptr &pool_first_ref = *(this->index.end() - (ExtraPointers-1));
node_base_ptr &pool_last_ref = this->index.back();
multiallocation_chain holder;
holder.incorporate_after( holder.before_begin()
@@ -1707,9 +1652,9 @@ class stable_vector
pool_first_ref = pool_last_ref = node_ptr();
}
else{
std::pair<node_ptr, node_ptr> data(holder.extract_data());
const std::pair<node_ptr, node_ptr> data(holder.extract_data());
pool_first_ref = data.first;
pool_last_ref = data.second;
pool_last_ref = data.second;
}
return ret;
}
@@ -1720,11 +1665,16 @@ class stable_vector
(static_cast<node_type&>(const_cast<node_base_type&>(this->internal_data.end_node)));
}
void priv_delete_node(const node_ptr &n)
void priv_destroy_node(const node_type &n)
{
allocator_traits<node_allocator_type>::
destroy(this->priv_node_alloc(), container_detail::addressof(n->value));
static_cast<node_base_type*>(container_detail::to_raw_pointer(n))->~node_base_type();
destroy(this->priv_node_alloc(), container_detail::addressof(n.value));
static_cast<const node_base_type*>(&n)->~node_base_type();
}
void priv_delete_node(const node_ptr &n)
{
this->priv_destroy_node(*n);
this->priv_put_in_pool(n);
}
@@ -1776,7 +1726,7 @@ class stable_vector
}
size_type n = this->capacity() - this->size();
node_base_ptr &pool_first_ref = *(index_ref.end() - 2);
node_base_ptr &pool_first_ref = *(index_ref.end() - (ExtraPointers-1));
node_base_ptr &pool_last_ref = index_ref.back();
multiallocation_chain holder;
holder.incorporate_after( holder.before_begin()
@@ -1886,6 +1836,17 @@ void swap(stable_vector<T,Allocator>& x,stable_vector<T,Allocator>& y)
/// @endcond
/*
//!has_trivial_destructor_after_move<> == true_type
//!specialization for optimizations
template <class T, class Allocator>
struct has_trivial_destructor_after_move<boost::container::stable_vector<T, Allocator> >
: public has_trivial_destructor_after_move<Allocator>::value
{};
*/
}}
#include <boost/container/detail/config_end.hpp>