|
Boost-Commit : |
Subject: [Boost-commit] svn:boost r84341 - in branches/release/boost: container container/detail interprocess interprocess/detail interprocess/ipc interprocess/smart_ptr interprocess/smart_ptr/detail interprocess/sync/shm interprocess/sync/windows intrusive intrusive/detail move
From: igaztanaga_at_[hidden]
Date: 2013-05-18 06:41:00
Author: igaztanaga
Date: 2013-05-18 06:40:55 EDT (Sat, 18 May 2013)
New Revision: 84341
URL: http://svn.boost.org/trac/boost/changeset/84341
Log:
Container, Interprocess, Intrusive, Move merge for 1.54
Added:
branches/release/boost/container/static_vector.hpp
- copied unchanged from r84340, /trunk/boost/container/static_vector.hpp
branches/release/boost/container/throw_exception.hpp
- copied unchanged from r82583, /trunk/boost/container/throw_exception.hpp
Properties modified:
branches/release/boost/container/ (props changed)
branches/release/boost/interprocess/ (props changed)
branches/release/boost/intrusive/ (props changed)
branches/release/boost/move/ (props changed)
Text files modified:
branches/release/boost/container/allocator_traits.hpp | 21
branches/release/boost/container/deque.hpp | 34
branches/release/boost/container/detail/adaptive_node_pool_impl.hpp | 5
branches/release/boost/container/detail/advanced_insert_int.hpp | 70 +
branches/release/boost/container/detail/allocator_version_traits.hpp | 4
branches/release/boost/container/detail/flat_tree.hpp | 20
branches/release/boost/container/detail/iterators.hpp | 4
branches/release/boost/container/detail/memory_util.hpp | 6
branches/release/boost/container/detail/node_pool_impl.hpp | 2
branches/release/boost/container/detail/utilities.hpp | 818 +++++++++++++++++---
branches/release/boost/container/flat_map.hpp | 7
branches/release/boost/container/list.hpp | 3
branches/release/boost/container/map.hpp | 7
branches/release/boost/container/scoped_allocator.hpp | 6
branches/release/boost/container/slist.hpp | 4
branches/release/boost/container/stable_vector.hpp | 47
branches/release/boost/container/string.hpp | 84 -
branches/release/boost/container/vector.hpp | 1567 +++++++++++++++++++++++++++------------
branches/release/boost/interprocess/detail/os_file_functions.hpp | 24
branches/release/boost/interprocess/detail/win32_api.hpp | 337 ++++---
branches/release/boost/interprocess/detail/workaround.hpp | 4
branches/release/boost/interprocess/file_mapping.hpp | 6
branches/release/boost/interprocess/ipc/message_queue.hpp | 13
branches/release/boost/interprocess/mapped_region.hpp | 49
branches/release/boost/interprocess/offset_ptr.hpp | 35
branches/release/boost/interprocess/shared_memory_object.hpp | 24
branches/release/boost/interprocess/smart_ptr/detail/shared_count.hpp | 1
branches/release/boost/interprocess/smart_ptr/unique_ptr.hpp | 14
branches/release/boost/interprocess/sync/shm/named_condition.hpp | 57 -
branches/release/boost/interprocess/sync/windows/mutex.hpp | 4
branches/release/boost/interprocess/sync/windows/named_sync.hpp | 4
branches/release/boost/interprocess/sync/windows/semaphore.hpp | 5
branches/release/boost/intrusive/detail/parent_from_member.hpp | 16
branches/release/boost/intrusive/detail/utilities.hpp | 20
branches/release/boost/intrusive/list.hpp | 16
branches/release/boost/intrusive/options.hpp | 4
branches/release/boost/intrusive/pointer_plus_bits.hpp | 6
branches/release/boost/intrusive/slist.hpp | 29
branches/release/boost/intrusive/treap_algorithms.hpp | 1
branches/release/boost/move/core.hpp | 29
40 files changed, 2342 insertions(+), 1065 deletions(-)
Modified: branches/release/boost/container/allocator_traits.hpp
==============================================================================
--- branches/release/boost/container/allocator_traits.hpp (original)
+++ branches/release/boost/container/allocator_traits.hpp 2013-05-18 06:40:55 EDT (Sat, 18 May 2013)
@@ -32,7 +32,10 @@
#include <limits> //numeric_limits<>::max()
#include <new> //placement new
#include <memory> //std::allocator
+
+#if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
#include <boost/container/detail/preprocessor.hpp>
+#endif
///@cond
@@ -211,7 +214,7 @@
//!
//! <b>Throws</b>: Nothing
static void deallocate(Alloc &a, pointer p, size_type n)
- { return a.deallocate(p, n); }
+ { a.deallocate(p, n); }
//! <b>Effects</b>: calls `a.allocate(n, p)` if that call is well-formed;
//! otherwise, invokes `a.allocate(n)`
@@ -250,7 +253,19 @@
//! <b>Returns</b>: `a.select_on_container_copy_construction()` if that expression is well-formed;
//! otherwise, a.
- static Alloc select_on_container_copy_construction(const Alloc &a)
+ static
+ #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+ typename container_detail::if_c
+ < boost::container::container_detail::
+ has_member_function_callable_with_select_on_container_copy_construction
+ <const Alloc>::value
+ , Alloc
+ , const Alloc &
+ >::type
+ #else
+ Alloc
+ #endif
+ select_on_container_copy_construction(const Alloc &a)
{
const bool value = boost::container::container_detail::
has_member_function_callable_with_select_on_container_copy_construction
@@ -295,7 +310,7 @@
static Alloc priv_select_on_container_copy_construction(boost::true_type, const Alloc &a)
{ return a.select_on_container_copy_construction(); }
- static Alloc priv_select_on_container_copy_construction(boost::false_type, const Alloc &a)
+ static const Alloc &priv_select_on_container_copy_construction(boost::false_type, const Alloc &a)
{ return a; }
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
Modified: branches/release/boost/container/deque.hpp
==============================================================================
--- branches/release/boost/container/deque.hpp (original)
+++ branches/release/boost/container/deque.hpp 2013-05-18 06:40:55 EDT (Sat, 18 May 2013)
@@ -46,12 +46,12 @@
#include <boost/container/detail/mpl.hpp>
#include <boost/container/allocator_traits.hpp>
#include <boost/container/container_fwd.hpp>
+#include <boost/container/throw_exception.hpp>
#include <cstddef>
#include <iterator>
#include <boost/assert.hpp>
#include <memory>
#include <algorithm>
-#include <stdexcept>
#include <boost/detail/no_exceptions_support.hpp>
#include <boost/type_traits/has_trivial_destructor.hpp>
#include <boost/type_traits/has_trivial_copy.hpp>
@@ -830,11 +830,11 @@
if (len > size()) {
FwdIt mid = first;
std::advance(mid, this->size());
- boost::copy_or_move(first, mid, begin());
+ boost::container::copy(first, mid, begin());
this->insert(this->cend(), mid, last);
}
else{
- this->erase(boost::copy_or_move(first, last, this->begin()), cend());
+ this->erase(boost::container::copy(first, last, this->begin()), cend());
}
}
#endif
@@ -1575,7 +1575,7 @@
}
void priv_range_check(size_type n) const
- { if (n >= this->size()) BOOST_RETHROW std::out_of_range("deque"); }
+ { if (n >= this->size()) throw_out_of_range("deque::at out of range"); }
template <class U>
iterator priv_insert(const_iterator position, BOOST_FWD_REF(U) x)
@@ -1721,11 +1721,11 @@
this->members_.m_finish = new_finish;
}
else{
- pos = this->members_.m_finish - elemsafter;
+ pos = old_finish - elemsafter;
if (elemsafter >= n) {
- iterator finish_n = this->members_.m_finish - difference_type(n);
+ iterator finish_n = old_finish - difference_type(n);
::boost::container::uninitialized_move_alloc
- (this->alloc(), finish_n, this->members_.m_finish, this->members_.m_finish);
+ (this->alloc(), finish_n, old_finish, old_finish);
this->members_.m_finish = new_finish;
boost::move_backward(pos, finish_n, old_finish);
interf.copy_n_and_update(pos, n);
@@ -1733,25 +1733,17 @@
else {
const size_type raw_gap = n - elemsafter;
::boost::container::uninitialized_move_alloc
- (this->alloc(), pos, old_finish, this->members_.m_finish + raw_gap);
+ (this->alloc(), pos, old_finish, old_finish + raw_gap);
BOOST_TRY{
+ interf.copy_n_and_update(pos, elemsafter);
interf.uninitialized_copy_n_and_update(old_finish, raw_gap);
}
BOOST_CATCH(...){
- this->priv_destroy_range(this->members_.m_finish, this->members_.m_finish + (old_finish - pos));
+ this->priv_destroy_range(old_finish, old_finish + elemsafter);
BOOST_RETHROW
}
BOOST_CATCH_END
this->members_.m_finish = new_finish;
- interf.copy_n_and_update(pos, elemsafter);
- /*
- interf.uninitialized_copy_some_and_update(old_finish, elemsafter, false);
- this->members_.m_finish += n-elemsafter;
- ::boost::container::uninitialized_move_alloc
- (this->alloc(), pos, old_finish, this->members_.m_finish);
- this->members_.m_finish = new_finish;
- interf.copy_remaining_to(pos);
- */
}
}
}
@@ -1840,12 +1832,10 @@
++cur_node) {
FwdIt mid = first;
std::advance(mid, this->s_buffer_size());
- ::boost::container::uninitialized_copy_or_move_alloc
- (this->alloc(), first, mid, *cur_node);
+ ::boost::container::uninitialized_copy_alloc(this->alloc(), first, mid, *cur_node);
first = mid;
}
- ::boost::container::uninitialized_copy_or_move_alloc
- (this->alloc(), first, last, this->members_.m_finish.m_first);
+ ::boost::container::uninitialized_copy_alloc(this->alloc(), first, last, this->members_.m_finish.m_first);
}
BOOST_CATCH(...){
this->priv_destroy_range(this->members_.m_start, iterator(*cur_node, cur_node));
Modified: branches/release/boost/container/detail/adaptive_node_pool_impl.hpp
==============================================================================
--- branches/release/boost/container/detail/adaptive_node_pool_impl.hpp (original)
+++ branches/release/boost/container/detail/adaptive_node_pool_impl.hpp 2013-05-18 06:40:55 EDT (Sat, 18 May 2013)
@@ -27,6 +27,7 @@
#include <boost/container/detail/math_functions.hpp>
#include <boost/container/detail/mpl.hpp>
#include <boost/container/detail/pool_common.hpp>
+#include <boost/container/throw_exception.hpp>
#include <boost/assert.hpp>
#include <boost/detail/no_exceptions_support.hpp>
#include <cstddef>
@@ -780,7 +781,7 @@
//In case of error, free memory deallocating all nodes (the new ones allocated
//in this function plus previously stored nodes in chain).
this->deallocate_nodes(chain);
- throw std::bad_alloc();
+ throw_bad_alloc();
}
block_info_t &c_info = *new(mem_address)block_info_t();
mem_address += HdrSize;
@@ -812,7 +813,7 @@
//In case of error, free memory deallocating all nodes (the new ones allocated
//in this function plus previously stored nodes in chain).
this->deallocate_nodes(chain);
- throw std::bad_alloc();
+ throw_bad_alloc();
}
//First initialize header information on the last subblock
char *hdr_addr = mem_address + m_real_block_alignment*(m_num_subblocks-1);
Modified: branches/release/boost/container/detail/advanced_insert_int.hpp
==============================================================================
--- branches/release/boost/container/detail/advanced_insert_int.hpp (original)
+++ branches/release/boost/container/detail/advanced_insert_int.hpp 2013-05-18 06:40:55 EDT (Sat, 18 May 2013)
@@ -28,6 +28,32 @@
namespace boost { namespace container { namespace container_detail {
template<class A, class FwdIt, class Iterator>
+struct move_insert_range_proxy
+{
+ typedef typename allocator_traits<A>::size_type size_type;
+ typedef typename allocator_traits<A>::value_type value_type;
+
+ move_insert_range_proxy(A& a, FwdIt first)
+ : a_(a), first_(first)
+ {}
+
+ void uninitialized_copy_n_and_update(Iterator p, size_type n)
+ {
+ this->first_ = ::boost::container::uninitialized_move_alloc_n_source
+ (this->a_, this->first_, n, p);
+ }
+
+ void copy_n_and_update(Iterator p, size_type n)
+ {
+ this->first_ = ::boost::container::move_n_source(this->first_, n, p);
+ }
+
+ A &a_;
+ FwdIt first_;
+};
+
+
+template<class A, class FwdIt, class Iterator>
struct insert_range_proxy
{
typedef typename allocator_traits<A>::size_type size_type;
@@ -37,15 +63,14 @@
: a_(a), first_(first)
{}
- void uninitialized_copy_n_and_update(Iterator pos, size_type n)
+ void uninitialized_copy_n_and_update(Iterator p, size_type n)
{
- this->first_ = ::boost::container::uninitialized_copy_or_move_alloc_n_source
- (this->a_, this->first_, n, pos);
+ this->first_ = ::boost::container::uninitialized_copy_alloc_n_source(this->a_, this->first_, n, p);
}
- void copy_n_and_update(Iterator pos, size_type n)
+ void copy_n_and_update(Iterator p, size_type n)
{
- this->first_ = ::boost::container::copy_or_move_n_source(this->first_, n, pos);
+ this->first_ = ::boost::container::copy_n_source(this->first_, n, p);
}
A &a_;
@@ -63,10 +88,10 @@
: a_(a), v_(v)
{}
- void uninitialized_copy_n_and_update(Iterator p, size_type n)
- { std::uninitialized_fill_n(p, n, v_); }
+ void uninitialized_copy_n_and_update(Iterator p, size_type n) const
+ { boost::container::uninitialized_fill_alloc_n(this->a_, v_, n, p); }
- void copy_n_and_update(Iterator p, size_type n)
+ void copy_n_and_update(Iterator p, size_type n) const
{ std::fill_n(p, n, v_); }
A &a_;
@@ -85,25 +110,10 @@
: a_(a)
{}
- void uninitialized_copy_n_and_update(Iterator p, size_type n)
- {
- Iterator orig_p = p;
- size_type n_left = n;
- BOOST_TRY{
- for(; n_left--; ++p){
- alloc_traits::construct(this->a_, container_detail::to_raw_pointer(&*p));
- }
- }
- BOOST_CATCH(...){
- for(; orig_p != p; ++orig_p){
- alloc_traits::destroy(this->a_, container_detail::to_raw_pointer(&*orig_p++));
- }
- BOOST_RETHROW
- }
- BOOST_CATCH_END
- }
+ void uninitialized_copy_n_and_update(Iterator p, size_type n) const
+ { boost::container::uninitialized_default_alloc_n(this->a_, n, p); }
- void copy_n_and_update(Iterator, size_type)
+ void copy_n_and_update(Iterator, size_type) const
{
BOOST_ASSERT(false);
}
@@ -123,7 +133,7 @@
: a_(a), v_(v)
{}
- void uninitialized_copy_n_and_update(Iterator p, size_type n)
+ void uninitialized_copy_n_and_update(Iterator p, size_type n) const
{
BOOST_ASSERT(n == 1); (void)n;
alloc_traits::construct( this->a_
@@ -132,7 +142,7 @@
);
}
- void copy_n_and_update(Iterator p, size_type n)
+ void copy_n_and_update(Iterator p, size_type n) const
{
BOOST_ASSERT(n == 1); (void)n;
*p =v_;
@@ -154,7 +164,7 @@
: a_(a), v_(v)
{}
- void uninitialized_copy_n_and_update(Iterator p, size_type n)
+ void uninitialized_copy_n_and_update(Iterator p, size_type n) const
{
BOOST_ASSERT(n == 1); (void)n;
alloc_traits::construct( this->a_
@@ -163,7 +173,7 @@
);
}
- void copy_n_and_update(Iterator p, size_type n)
+ void copy_n_and_update(Iterator p, size_type n) const
{
BOOST_ASSERT(n == 1); (void)n;
*p = ::boost::move(v_);
Modified: branches/release/boost/container/detail/allocator_version_traits.hpp
==============================================================================
--- branches/release/boost/container/detail/allocator_version_traits.hpp (original)
+++ branches/release/boost/container/detail/allocator_version_traits.hpp 2013-05-18 06:40:55 EDT (Sat, 18 May 2013)
@@ -18,13 +18,13 @@
#include <boost/container/detail/config_begin.hpp>
#include <boost/container/detail/workaround.hpp>
#include <boost/container/allocator_traits.hpp> //allocator_traits
+#include <boost/container/throw_exception.hpp>
#include <boost/container/detail/multiallocation_chain.hpp> //multiallocation_chain
#include <boost/container/detail/version_type.hpp> //version_type
#include <boost/container/detail/allocation_type.hpp> //allocation_type
#include <boost/container/detail/mpl.hpp> //integral_constant
#include <boost/intrusive/pointer_traits.hpp> //pointer_traits
#include <utility> //pair
-#include <stdexcept> //runtime_error
#include <boost/detail/no_exceptions_support.hpp> //BOOST_TRY
namespace boost {
@@ -135,7 +135,7 @@
std::pair<pointer, bool> ret(pointer(), false);
if(!(command & allocate_new)){
if(!(command & nothrow_allocation)){
- throw std::runtime_error("version 1 allocator without allocate_new flag");
+ throw_logic_error("version 1 allocator without allocate_new flag");
}
}
else{
Modified: branches/release/boost/container/detail/flat_tree.hpp
==============================================================================
--- branches/release/boost/container/detail/flat_tree.hpp (original)
+++ branches/release/boost/container/detail/flat_tree.hpp 2013-05-18 06:40:55 EDT (Sat, 18 May 2013)
@@ -33,6 +33,9 @@
#include <boost/container/detail/value_init.hpp>
#include <boost/container/detail/destroyers.hpp>
#include <boost/container/allocator_traits.hpp>
+#ifdef BOOST_CONTAINER_VECTOR_ITERATOR_IS_POINTER
+#include <boost/intrusive/pointer_traits.hpp>
+#endif
#include <boost/aligned_storage.hpp>
namespace boost {
@@ -73,10 +76,19 @@
template<class Pointer>
struct get_flat_tree_iterators
{
+ #ifdef BOOST_CONTAINER_VECTOR_ITERATOR_IS_POINTER
+ typedef Pointer iterator;
+ typedef typename boost::intrusive::
+ pointer_traits<Pointer>::element_type iterator_element_type;
+ typedef typename boost::intrusive::
+ pointer_traits<Pointer>:: template
+ rebind_pointer<const iterator_element_type>::type const_iterator;
+ #else //BOOST_CONTAINER_VECTOR_ITERATOR_IS_POINTER
typedef typename container_detail::
vector_iterator<Pointer> iterator;
typedef typename container_detail::
vector_const_iterator<Pointer> const_iterator;
+ #endif //BOOST_CONTAINER_VECTOR_ITERATOR_IS_POINTER
typedef std::reverse_iterator<iterator> reverse_iterator;
typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
};
@@ -145,7 +157,7 @@
void swap(Data &d)
{
value_compare& mycomp = *this, & othercomp = d;
- container_detail::do_swap(mycomp, othercomp);
+ boost::container::swap_dispatch(mycomp, othercomp);
this->m_vect.swap(d.m_vect);
}
@@ -785,7 +797,7 @@
const value_compare &value_comp = this->m_data;
commit_data.position = this->priv_lower_bound(b, e, KeyOfValue()(val));
return std::pair<iterator,bool>
- ( *reinterpret_cast<iterator*>(&commit_data.position)
+ ( iterator(vector_iterator_get_ptr(commit_data.position))
, commit_data.position == e || value_comp(val, *commit_data.position));
}
@@ -813,10 +825,10 @@
if(pos != this->cbegin() && !value_comp(val, pos[-1])){
if(value_comp(pos[-1], val)){
commit_data.position = pos;
- return std::pair<iterator,bool>(*reinterpret_cast<iterator*>(&pos), true);
+ return std::pair<iterator,bool>(iterator(vector_iterator_get_ptr(pos)), true);
}
else{
- return std::pair<iterator,bool>(*reinterpret_cast<iterator*>(&pos), false);
+ return std::pair<iterator,bool>(iterator(vector_iterator_get_ptr(pos)), false);
}
}
return this->priv_insert_unique_prepare(this->cbegin(), pos, val, commit_data);
Modified: branches/release/boost/container/detail/iterators.hpp
==============================================================================
--- branches/release/boost/container/detail/iterators.hpp (original)
+++ branches/release/boost/container/detail/iterators.hpp 2013-05-18 06:40:55 EDT (Sat, 18 May 2013)
@@ -114,7 +114,7 @@
const T& operator*() const
{ return dereference(); }
- const T& operator[] (Difference n) const
+ const T& operator[] (Difference ) const
{ return dereference(); }
const T* operator->() const
@@ -335,7 +335,7 @@
T& operator*() const
{ return dereference(); }
- T& operator[] (Difference n) const
+ T& operator[] (Difference ) const
{ return dereference(); }
T *operator->() const
Modified: branches/release/boost/container/detail/memory_util.hpp
==============================================================================
--- branches/release/boost/container/detail/memory_util.hpp (original)
+++ branches/release/boost/container/detail/memory_util.hpp 2013-05-18 06:40:55 EDT (Sat, 18 May 2013)
@@ -51,6 +51,12 @@
#define BOOST_PP_ITERATION_PARAMS_1 (3, (0, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS+1, <boost/intrusive/detail/has_member_function_callable_with.hpp>))
#include BOOST_PP_ITERATE()
+#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME swap
+#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_BEGIN namespace boost { namespace container { namespace container_detail {
+#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_END }}}
+#define BOOST_PP_ITERATION_PARAMS_1 (3, (0, 1, <boost/intrusive/detail/has_member_function_callable_with.hpp>))
+#include BOOST_PP_ITERATE()
+
namespace boost {
namespace container {
namespace container_detail {
Modified: branches/release/boost/container/detail/node_pool_impl.hpp
==============================================================================
--- branches/release/boost/container/detail/node_pool_impl.hpp (original)
+++ branches/release/boost/container/detail/node_pool_impl.hpp 2013-05-18 06:40:55 EDT (Sat, 18 May 2013)
@@ -208,8 +208,6 @@
BOOST_ASSERT(m_allocated==0);
size_type blocksize = get_rounded_size
(m_real_node_size*m_nodes_per_block, (size_type)alignment_of<node_t>::value);
- typename blockslist_t::iterator
- it(m_blocklist.begin()), itend(m_blocklist.end()), aux;
//We iterate though the NodeBlock list to free the memory
while(!m_blocklist.empty()){
Modified: branches/release/boost/container/detail/utilities.hpp
==============================================================================
--- branches/release/boost/container/detail/utilities.hpp (original)
+++ branches/release/boost/container/detail/utilities.hpp 2013-05-18 06:40:55 EDT (Sat, 18 May 2013)
@@ -13,22 +13,81 @@
#include "config_begin.hpp"
#include <cstdio>
+#include <cstring> //for ::memcpy
#include <boost/type_traits/is_fundamental.hpp>
#include <boost/type_traits/is_pointer.hpp>
#include <boost/type_traits/is_enum.hpp>
#include <boost/type_traits/is_member_pointer.hpp>
#include <boost/type_traits/is_class.hpp>
+#include <boost/type_traits/has_trivial_destructor.hpp>
+#include <boost/move/core.hpp>
#include <boost/move/utility.hpp>
#include <boost/move/iterator.hpp>
#include <boost/container/detail/mpl.hpp>
#include <boost/container/detail/type_traits.hpp>
#include <boost/container/allocator_traits.hpp>
#include <boost/detail/no_exceptions_support.hpp>
+#include <boost/type_traits/has_trivial_copy.hpp>
+#include <boost/type_traits/has_trivial_assign.hpp>
+#include <boost/container/detail/memory_util.hpp>
+#include <boost/aligned_storage.hpp>
#include <algorithm>
#include <iterator>
+#include <utility> //std::distance
namespace boost {
namespace container {
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// swap
+//
+//////////////////////////////////////////////////////////////////////////////
+
+namespace container_swap {
+
+template<class T, bool IsClass = boost::is_class<T>::value >
+struct has_member_swap
+{
+ static const bool value = boost::container::container_detail::
+ has_member_function_callable_with_swap<T, T &>::value;
+};
+
+template<class T>
+struct has_member_swap<T, false>
+{
+ static const bool value = false;
+};
+
+} //namespace container_swap {
+
+template<class T> inline
+typename container_detail::enable_if_c
+ <container_swap::has_member_swap<T>::value, void>::type
+swap_dispatch(T &left, T &right) //swap using member swap
+{
+ left.swap(right); // may throw
+}
+
+template<class T> inline
+typename container_detail::enable_if_c
+ <!container_swap::has_member_swap<T>::value && boost::has_move_emulation_enabled<T>::value, void>::type
+ swap_dispatch(T &left, T &right)
+{
+ T temp(boost::move(left)); // may throw
+ left = boost::move(right); // may throw
+ right = boost::move(temp); // may throw
+}
+
+template<class T> inline
+typename container_detail::enable_if_c
+ <!container_swap::has_member_swap<T>::value && !boost::has_move_emulation_enabled<T>::value, void>::type
+ swap_dispatch(T &left, T &right)
+{
+ using std::swap;
+ swap(left, right); // may throw
+}
+
namespace container_detail {
template <typename T>
@@ -78,13 +137,6 @@
to_raw_pointer(const Pointer &p)
{ return boost::container::container_detail::to_raw_pointer(p.operator->()); }
-//!To avoid ADL problems with swap
-template <class T>
-inline void do_swap(T& x, T& y)
-{
- using std::swap;
- swap(x, y);
-}
template<class AllocatorType>
inline void swap_alloc(AllocatorType &, AllocatorType &, container_detail::false_type)
@@ -93,7 +145,7 @@
template<class AllocatorType>
inline void swap_alloc(AllocatorType &l, AllocatorType &r, container_detail::true_type)
-{ container_detail::do_swap(l, r); }
+{ boost::container::swap_dispatch(l, r); }
template<class AllocatorType>
inline void assign_alloc(AllocatorType &, const AllocatorType &, container_detail::false_type)
@@ -126,26 +178,196 @@
enum { value = ((OrigSize-1)/RoundTo+1)*RoundTo };
};
+template<class I>
+struct are_elements_contiguous
+{
+ static const bool value = false;
+};
+
+/////////////////////////
+// raw pointers
+/////////////////////////
+
+template<class T>
+struct are_elements_contiguous<T*>
+{
+ static const bool value = true;
+};
+
+/////////////////////////
+// predeclarations
+/////////////////////////
+
+#ifndef BOOST_CONTAINER_VECTOR_ITERATOR_IS_POINTER
+
+template<class Pointer>
+class vector_iterator;
+
+template<class Pointer>
+class vector_const_iterator;
+
+#endif //BOOST_CONTAINER_VECTOR_ITERATOR_IS_POINTER
+
+} //namespace container_detail {
+} //namespace container {
+
+namespace interprocess {
+
+template <class PointedType, class DifferenceType, class OffsetType, std::size_t OffsetAlignment>
+class offset_ptr;
+
+} //namespace interprocess {
+
+namespace container {
+
+namespace container_detail {
+
+/////////////////////////
+//vector_[const_]iterator
+/////////////////////////
+
+#ifndef BOOST_CONTAINER_VECTOR_ITERATOR_IS_POINTER
+
+template<class Pointer>
+struct are_elements_contiguous<boost::container::container_detail::vector_iterator<Pointer> >
+{
+ static const bool value = true;
+};
+
+template<class Pointer>
+struct are_elements_contiguous<boost::container::container_detail::vector_const_iterator<Pointer> >
+{
+ static const bool value = true;
+};
+
+#endif //BOOST_CONTAINER_VECTOR_ITERATOR_IS_POINTER
+
+/////////////////////////
+// offset_ptr
+/////////////////////////
+
+template <class PointedType, class DifferenceType, class OffsetType, std::size_t OffsetAlignment>
+struct are_elements_contiguous< ::boost::interprocess::offset_ptr<PointedType, DifferenceType, OffsetType, OffsetAlignment> >
+{
+ static const bool value = true;
+};
+
+template <typename I, typename O>
+struct are_contiguous_and_same
+{
+ static const bool is_same_io =
+ is_same< typename remove_const< typename ::std::iterator_traits<I>::value_type >::type
+ , typename ::std::iterator_traits<O>::value_type
+ >::value;
+ static const bool value = is_same_io &&
+ are_elements_contiguous<I>::value &&
+ are_elements_contiguous<O>::value;
+};
+
+template <typename I, typename O>
+struct is_memcpy_copy_assignable
+{
+ static const bool value = are_contiguous_and_same<I, O>::value &&
+ boost::has_trivial_assign< typename ::std::iterator_traits<I>::value_type >::value;
+};
+
+template <typename I, typename O>
+struct is_memcpy_copy_constructible
+{
+ static const bool value = are_contiguous_and_same<I, O>::value &&
+ boost::has_trivial_copy< typename ::std::iterator_traits<I>::value_type >::value;
+};
+
+template <typename I, typename O, typename R>
+struct enable_if_memcpy_copy_constructible
+ : public enable_if_c<container_detail::is_memcpy_copy_constructible<I, O>::value, R>
+{};
+
+template <typename I, typename O, typename R>
+struct disable_if_memcpy_copy_constructible
+ : public enable_if_c<!container_detail::is_memcpy_copy_constructible<I, O>::value, R>
+{};
+
+template <typename I, typename O, typename R>
+struct enable_if_memcpy_copy_assignable
+ : public enable_if_c<container_detail::is_memcpy_copy_assignable<I, O>::value, R>
+{};
+
+template <typename I, typename O, typename R>
+struct disable_if_memcpy_copy_assignable
+ : public enable_if_c<!container_detail::is_memcpy_copy_assignable<I, O>::value, R>
+{};
+
+template
+ <typename I, // I models InputIterator
+ typename F> // F models ForwardIterator
+inline F memcpy(I f, I l, F r) BOOST_CONTAINER_NOEXCEPT
+{
+ typedef typename std::iterator_traits<I>::value_type value_type;
+ typename std::iterator_traits<I>::difference_type n = std::distance(f, l);
+ ::memcpy(container_detail::addressof(*r), container_detail::addressof(*f), sizeof(value_type)*n);
+ std::advance(r, n);
+ return r;
+}
+
+template
+ <typename I, // I models InputIterator
+ typename F> // F models ForwardIterator
+F memcpy_n(I f, typename std::iterator_traits<I>::difference_type n, F r) BOOST_CONTAINER_NOEXCEPT
+{
+ typedef typename std::iterator_traits<I>::value_type value_type;
+ ::memcpy(container_detail::addressof(*r), container_detail::addressof(*f), sizeof(value_type)*n);
+ std::advance(r, n);
+ return r;
+}
+
+template
+ <typename I, // I models InputIterator
+ typename F> // F models ForwardIterator
+I memcpy_n_source(I f, typename std::iterator_traits<I>::difference_type n, F r) BOOST_CONTAINER_NOEXCEPT
+{
+ typedef typename std::iterator_traits<I>::value_type value_type;
+ ::memcpy(container_detail::addressof(*r), container_detail::addressof(*f), sizeof(value_type)*n);
+ std::advance(f, n);
+ return f;
+}
+
+template
+ <typename I, // I models InputIterator
+ typename F> // F models ForwardIterator
+I memcpy_n_source_dest(I f, typename std::iterator_traits<I>::difference_type n, F &r) BOOST_CONTAINER_NOEXCEPT
+{
+ typedef typename std::iterator_traits<I>::value_type value_type;
+ ::memcpy(container_detail::addressof(*r), container_detail::addressof(*f), sizeof(value_type)*n);
+ std::advance(f, n);
+ std::advance(r, n);
+ return f;
+}
+
+
} //namespace container_detail {
+
//////////////////////////////////////////////////////////////////////////////
//
// uninitialized_move_alloc
//
//////////////////////////////////////////////////////////////////////////////
+
//! <b>Effects</b>:
//! \code
-//! for (; first != last; ++result, ++first)
-//! allocator_traits::construct(a, &*result, boost::move(*first));
+//! for (; f != l; ++r, ++f)
+//! allocator_traits::construct(a, &*r, boost::move(*f));
//! \endcode
//!
-//! <b>Returns</b>: result
+//! <b>Returns</b>: r
template
<typename A,
typename I, // I models InputIterator
typename F> // F models ForwardIterator
-F uninitialized_move_alloc(A &a, I f, I l, F r)
+inline typename container_detail::disable_if_memcpy_copy_constructible<I, F, F>::type
+ uninitialized_move_alloc(A &a, I f, I l, F r)
{
F back = r;
BOOST_TRY{
@@ -164,6 +386,14 @@
return r;
}
+template
+ <typename A,
+ typename I, // I models InputIterator
+ typename F> // F models ForwardIterator
+inline typename container_detail::enable_if_memcpy_copy_constructible<I, F, F>::type
+ uninitialized_move_alloc(A &, I f, I l, F r) BOOST_CONTAINER_NOEXCEPT
+{ return container_detail::memcpy(f, l, r); }
+
//////////////////////////////////////////////////////////////////////////////
//
// uninitialized_move_alloc_n
@@ -172,16 +402,17 @@
//! <b>Effects</b>:
//! \code
-//! for (; n--; ++result, ++first)
-//! allocator_traits::construct(a, &*result, boost::move(*first));
+//! for (; n--; ++r, ++f)
+//! allocator_traits::construct(a, &*r, boost::move(*f));
//! \endcode
//!
-//! <b>Returns</b>: result
+//! <b>Returns</b>: r
template
<typename A,
typename I, // I models InputIterator
typename F> // F models ForwardIterator
-F uninitialized_move_alloc_n(A &a, I f, typename std::iterator_traits<I>::difference_type n, F r)
+inline typename container_detail::disable_if_memcpy_copy_constructible<I, F, F>::type
+ uninitialized_move_alloc_n(A &a, I f, typename std::iterator_traits<I>::difference_type n, F r)
{
F back = r;
BOOST_TRY{
@@ -200,6 +431,14 @@
return r;
}
+template
+ <typename A,
+ typename I, // I models InputIterator
+ typename F> // F models ForwardIterator
+inline typename container_detail::enable_if_memcpy_copy_constructible<I, F, F>::type
+ uninitialized_move_alloc_n(A &, I f, typename std::iterator_traits<I>::difference_type n, F r) BOOST_CONTAINER_NOEXCEPT
+{ return container_detail::memcpy_n(f, n, r); }
+
//////////////////////////////////////////////////////////////////////////////
//
// uninitialized_move_alloc_n_source
@@ -208,16 +447,17 @@
//! <b>Effects</b>:
//! \code
-//! for (; n--; ++result, ++first)
-//! allocator_traits::construct(a, &*result, boost::move(*first));
+//! for (; n--; ++r, ++f)
+//! allocator_traits::construct(a, &*r, boost::move(*f));
//! \endcode
//!
-//! <b>Returns</b>: first (after incremented)
+//! <b>Returns</b>: f (after incremented)
template
<typename A,
typename I, // I models InputIterator
typename F> // F models ForwardIterator
-I uninitialized_move_alloc_n_source(A &a, I f, typename std::iterator_traits<I>::difference_type n, F r)
+inline typename container_detail::disable_if_memcpy_copy_constructible<I, F, I>::type
+ uninitialized_move_alloc_n_source(A &a, I f, typename std::iterator_traits<I>::difference_type n, F r)
{
F back = r;
BOOST_TRY{
@@ -236,6 +476,14 @@
return f;
}
+template
+ <typename A,
+ typename I, // I models InputIterator
+ typename F> // F models ForwardIterator
+inline typename container_detail::enable_if_memcpy_copy_constructible<I, F, I>::type
+ uninitialized_move_alloc_n_source(A &, I f, typename std::iterator_traits<I>::difference_type n, F r) BOOST_CONTAINER_NOEXCEPT
+{ return container_detail::memcpy_n_source(f, n, r); }
+
//////////////////////////////////////////////////////////////////////////////
//
// uninitialized_copy_alloc
@@ -244,16 +492,17 @@
//! <b>Effects</b>:
//! \code
-//! for (; first != last; ++result, ++first)
-//! allocator_traits::construct(a, &*result, *first);
+//! for (; f != l; ++r, ++f)
+//! allocator_traits::construct(a, &*r, *f);
//! \endcode
//!
-//! <b>Returns</b>: result
+//! <b>Returns</b>: r
template
<typename A,
typename I, // I models InputIterator
typename F> // F models ForwardIterator
-F uninitialized_copy_alloc(A &a, I f, I l, F r)
+inline typename container_detail::disable_if_memcpy_copy_constructible<I, F, F>::type
+ uninitialized_copy_alloc(A &a, I f, I l, F r)
{
F back = r;
BOOST_TRY{
@@ -272,6 +521,14 @@
return r;
}
+template
+ <typename A,
+ typename I, // I models InputIterator
+ typename F> // F models ForwardIterator
+inline typename container_detail::enable_if_memcpy_copy_constructible<I, F, F>::type
+ uninitialized_copy_alloc(A &, I f, I l, F r) BOOST_CONTAINER_NOEXCEPT
+{ return container_detail::memcpy(f, l, r); }
+
//////////////////////////////////////////////////////////////////////////////
//
// uninitialized_copy_alloc_n
@@ -280,16 +537,17 @@
//! <b>Effects</b>:
//! \code
-//! for (; n--; ++result, ++first)
-//! allocator_traits::construct(a, &*result, *first);
+//! for (; n--; ++r, ++f)
+//! allocator_traits::construct(a, &*r, *f);
//! \endcode
//!
-//! <b>Returns</b>: result
+//! <b>Returns</b>: r
template
<typename A,
typename I, // I models InputIterator
typename F> // F models ForwardIterator
-F uninitialized_copy_alloc_n(A &a, I f, typename std::iterator_traits<I>::difference_type n, F r)
+inline typename container_detail::disable_if_memcpy_copy_constructible<I, F, F>::type
+ uninitialized_copy_alloc_n(A &a, I f, typename std::iterator_traits<I>::difference_type n, F r)
{
F back = r;
BOOST_TRY{
@@ -308,6 +566,14 @@
return r;
}
+template
+ <typename A,
+ typename I, // I models InputIterator
+ typename F> // F models ForwardIterator
+inline typename container_detail::enable_if_memcpy_copy_constructible<I, F, F>::type
+ uninitialized_copy_alloc_n(A &, I f, typename std::iterator_traits<I>::difference_type n, F r) BOOST_CONTAINER_NOEXCEPT
+{ return container_detail::memcpy_n(f, n, r); }
+
//////////////////////////////////////////////////////////////////////////////
//
// uninitialized_copy_alloc_n_source
@@ -316,16 +582,17 @@
//! <b>Effects</b>:
//! \code
-//! for (; n--; ++result, ++first)
-//! allocator_traits::construct(a, &*result, *first);
+//! for (; n--; ++r, ++f)
+//! allocator_traits::construct(a, &*r, *f);
//! \endcode
//!
-//! <b>Returns</b>: first (after incremented)
+//! <b>Returns</b>: f (after incremented)
template
<typename A,
typename I, // I models InputIterator
typename F> // F models ForwardIterator
-I uninitialized_copy_alloc_n_source(A &a, I f, typename std::iterator_traits<I>::difference_type n, F r)
+inline typename container_detail::disable_if_memcpy_copy_constructible<I, F, I>::type
+ uninitialized_copy_alloc_n_source(A &a, I f, typename std::iterator_traits<I>::difference_type n, F r)
{
F back = r;
BOOST_TRY{
@@ -344,24 +611,67 @@
return f;
}
+template
+ <typename A,
+ typename I, // I models InputIterator
+ typename F> // F models ForwardIterator
+inline typename container_detail::enable_if_memcpy_copy_constructible<I, F, I>::type
+ uninitialized_copy_alloc_n_source(A &, I f, typename std::iterator_traits<I>::difference_type n, F r) BOOST_CONTAINER_NOEXCEPT
+{ return container_detail::memcpy_n_source(f, n, r); }
+
//////////////////////////////////////////////////////////////////////////////
//
-// uninitialized_copy_alloc
+// uninitialized_default_alloc_n
//
//////////////////////////////////////////////////////////////////////////////
//! <b>Effects</b>:
//! \code
-//! for (; first != last; ++result, ++first)
-//! allocator_traits::construct(a, &*result, *first);
+//! for (; n--; ++r, ++f)
+//! allocator_traits::construct(a, &*r);
//! \endcode
//!
-//! <b>Returns</b>: result
+//! <b>Returns</b>: r
+template
+ <typename A,
+ typename F> // F models ForwardIterator
+inline F uninitialized_default_alloc_n(A &a, typename allocator_traits<A>::difference_type n, F r)
+{
+ F back = r;
+ BOOST_TRY{
+ while (n--) {
+ allocator_traits<A>::construct(a, container_detail::to_raw_pointer(&*r));
+ ++r;
+ }
+ }
+ BOOST_CATCH(...){
+ for (; back != r; ++back){
+ allocator_traits<A>::destroy(a, container_detail::to_raw_pointer(&*back));
+ }
+ BOOST_RETHROW;
+ }
+ BOOST_CATCH_END
+ return r;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// uninitialized_fill_alloc
+//
+//////////////////////////////////////////////////////////////////////////////
+
+//! <b>Effects</b>:
+//! \code
+//! for (; f != l; ++r, ++f)
+//! allocator_traits::construct(a, &*r, *f);
+//! \endcode
+//!
+//! <b>Returns</b>: r
template
<typename A,
typename F, // F models ForwardIterator
typename T>
-void uninitialized_fill_alloc(A &a, F f, F l, const T &t)
+inline void uninitialized_fill_alloc(A &a, F f, F l, const T &t)
{
F back = f;
BOOST_TRY{
@@ -379,143 +689,184 @@
BOOST_CATCH_END
}
+
//////////////////////////////////////////////////////////////////////////////
//
-// uninitialized_copy_or_move_alloc
+// uninitialized_fill_alloc_n
//
//////////////////////////////////////////////////////////////////////////////
+//! <b>Effects</b>:
+//! \code
+//! for (; n--; ++r, ++f)
+//! allocator_traits::construct(a, &*r, v);
+//! \endcode
+//!
+//! <b>Returns</b>: r
template
-<typename A
-,typename I // I models InputIterator
-,typename F> // F models ForwardIterator
-F uninitialized_copy_or_move_alloc
- (A &a, I f, I l, F r
- ,typename boost::container::container_detail::enable_if
- < boost::move_detail::is_move_iterator<I> >::type* = 0)
+ <typename A,
+ typename T,
+ typename F> // F models ForwardIterator
+inline F uninitialized_fill_alloc_n(A &a, const T &v, typename allocator_traits<A>::difference_type n, F r)
{
- return ::boost::container::uninitialized_move_alloc(a, f, l, r);
+ F back = r;
+ BOOST_TRY{
+ while (n--) {
+ allocator_traits<A>::construct(a, container_detail::to_raw_pointer(&*r), v);
+ ++r;
+ }
+ }
+ BOOST_CATCH(...){
+ for (; back != r; ++back){
+ allocator_traits<A>::destroy(a, container_detail::to_raw_pointer(&*back));
+ }
+ BOOST_RETHROW;
+ }
+ BOOST_CATCH_END
+ return r;
}
+//////////////////////////////////////////////////////////////////////////////
+//
+// copy
+//
+//////////////////////////////////////////////////////////////////////////////
+
template
-<typename A
-,typename I // I models InputIterator
-,typename F> // F models ForwardIterator
-F uninitialized_copy_or_move_alloc
- (A &a, I f, I l, F r
- ,typename boost::container::container_detail::disable_if
- < boost::move_detail::is_move_iterator<I> >::type* = 0)
+<typename I, // I models InputIterator
+typename F> // F models ForwardIterator
+inline typename container_detail::disable_if_memcpy_copy_assignable<I, F, F>::type
+ copy(I f, I l, F r)
{
- return ::boost::container::uninitialized_copy_alloc(a, f, l, r);
+ while (f != l) {
+ *r = *f;
+ ++f; ++r;
+ }
+ return r;
}
+template
+<typename I, // I models InputIterator
+typename F> // F models ForwardIterator
+inline typename container_detail::enable_if_memcpy_copy_assignable<I, F, F>::type
+ copy(I f, I l, F r) BOOST_CONTAINER_NOEXCEPT
+{ return container_detail::memcpy(f, l, r); }
+
//////////////////////////////////////////////////////////////////////////////
//
-// uninitialized_copy_or_move_alloc_n
+// copy_n
//
//////////////////////////////////////////////////////////////////////////////
template
-<typename A
-,typename I // I models InputIterator
-,typename F> // F models ForwardIterator
-F uninitialized_copy_or_move_alloc_n
- (A &a, I f, typename std::iterator_traits<I>::difference_type n, F r
- ,typename boost::container::container_detail::enable_if
- < boost::move_detail::is_move_iterator<I> >::type* = 0)
+<typename I, // I models InputIterator
+typename F> // F models ForwardIterator
+inline typename container_detail::disable_if_memcpy_copy_assignable<I, F, F>::type
+ copy_n(I f, typename std::iterator_traits<I>::difference_type n, F r)
{
- return ::boost::container::uninitialized_move_alloc_n(a, f, n, r);
+ while (n--) {
+ *r = *f;
+ ++f; ++r;
+ }
+ return r;
}
template
-<typename A
-,typename I // I models InputIterator
-,typename F> // F models ForwardIterator
-F uninitialized_copy_or_move_alloc_n
- (A &a, I f, typename std::iterator_traits<I>::difference_type n, F r
- ,typename boost::container::container_detail::disable_if
- < boost::move_detail::is_move_iterator<I> >::type* = 0)
-{
- return ::boost::container::uninitialized_copy_alloc_n(a, f, n, r);
-}
-
+<typename I, // I models InputIterator
+typename F> // F models ForwardIterator
+inline typename container_detail::enable_if_memcpy_copy_assignable<I, F, F>::type
+ copy_n(I f, typename std::iterator_traits<I>::difference_type n, F r) BOOST_CONTAINER_NOEXCEPT
+{ return container_detail::memcpy_n(f, n, r); }
//////////////////////////////////////////////////////////////////////////////
//
-// uninitialized_copy_or_move_alloc_n_source
+// copy_n_source
//
//////////////////////////////////////////////////////////////////////////////
template
-<typename A
-,typename I // I models InputIterator
-,typename F> // F models ForwardIterator
-I uninitialized_copy_or_move_alloc_n_source
- (A &a, I f, typename std::iterator_traits<I>::difference_type n, F r
- ,typename boost::container::container_detail::enable_if
- < boost::move_detail::is_move_iterator<I> >::type* = 0)
+<typename I, // I models InputIterator
+typename F> // F models ForwardIterator
+inline typename container_detail::disable_if_memcpy_copy_assignable<I, F, I>::type
+ copy_n_source(I f, typename std::iterator_traits<I>::difference_type n, F r)
{
- return ::boost::container::uninitialized_move_alloc_n_source(a, f, n, r);
+ while (n--) {
+ *r = *f;
+ ++f; ++r;
+ }
+ return f;
}
template
-<typename A
-,typename I // I models InputIterator
-,typename F> // F models ForwardIterator
-I uninitialized_copy_or_move_alloc_n_source
- (A &a, I f, typename std::iterator_traits<I>::difference_type n, F r
- ,typename boost::container::container_detail::disable_if
- < boost::move_detail::is_move_iterator<I> >::type* = 0)
-{
- return ::boost::container::uninitialized_copy_alloc_n_source(a, f, n, r);
-}
+<typename I, // I models InputIterator
+typename F> // F models ForwardIterator
+inline typename container_detail::enable_if_memcpy_copy_assignable<I, F, I>::type
+ copy_n_source(I f, typename std::iterator_traits<I>::difference_type n, F r) BOOST_CONTAINER_NOEXCEPT
+{ return container_detail::memcpy_n_source(f, n, r); }
//////////////////////////////////////////////////////////////////////////////
//
-// copy_or_move
+// copy_n_source_dest
//
//////////////////////////////////////////////////////////////////////////////
template
<typename I, // I models InputIterator
typename F> // F models ForwardIterator
-inline F copy_or_move(I f, I l, F r
- ,typename boost::container::container_detail::enable_if
- < boost::move_detail::is_move_iterator<I> >::type* = 0)
+inline typename container_detail::disable_if_memcpy_copy_assignable<I, F, I>::type
+ copy_n_source_dest(I f, typename std::iterator_traits<I>::difference_type n, F &r)
{
- while (f != l) {
- *r = ::boost::move(*f);
+ while (n--) {
+ *r = *f;
++f; ++r;
}
- return r;
+ return f;
}
template
<typename I, // I models InputIterator
typename F> // F models ForwardIterator
-inline F copy_or_move(I f, I l, F r
- ,typename boost::container::container_detail::disable_if
- < boost::move_detail::is_move_iterator<I> >::type* = 0)
+inline typename container_detail::enable_if_memcpy_copy_assignable<I, F, I>::type
+ copy_n_source_dest(I f, typename std::iterator_traits<I>::difference_type n, F &r) BOOST_CONTAINER_NOEXCEPT
+{ return container_detail::memcpy_n_source_dest(f, n, r); }
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// move
+//
+//////////////////////////////////////////////////////////////////////////////
+
+template
+<typename I, // I models InputIterator
+typename F> // F models ForwardIterator
+inline typename container_detail::disable_if_memcpy_copy_assignable<I, F, F>::type
+ move(I f, I l, F r)
{
while (f != l) {
- *r = *f;
+ *r = ::boost::move(*f);
++f; ++r;
}
return r;
}
+template
+<typename I, // I models InputIterator
+typename F> // F models ForwardIterator
+inline typename container_detail::enable_if_memcpy_copy_assignable<I, F, F>::type
+ move(I f, I l, F r) BOOST_CONTAINER_NOEXCEPT
+{ return container_detail::memcpy(f, l, r); }
+
//////////////////////////////////////////////////////////////////////////////
//
-// copy_or_move_n
+// move_n
//
//////////////////////////////////////////////////////////////////////////////
template
<typename I, // I models InputIterator
typename F> // F models ForwardIterator
-inline F copy_or_move_n(I f, typename std::iterator_traits<I>::difference_type n, F r
- ,typename boost::container::container_detail::enable_if
- < boost::move_detail::is_move_iterator<I> >::type* = 0)
+inline typename container_detail::disable_if_memcpy_copy_assignable<I, F, F>::type
+ move_n(I f, typename std::iterator_traits<I>::difference_type n, F r)
{
while (n--) {
*r = ::boost::move(*f);
@@ -527,29 +878,47 @@
template
<typename I, // I models InputIterator
typename F> // F models ForwardIterator
-inline F copy_or_move_n(I f, typename std::iterator_traits<I>::difference_type n, F r
- ,typename boost::container::container_detail::disable_if
- < boost::move_detail::is_move_iterator<I> >::type* = 0)
+inline typename container_detail::enable_if_memcpy_copy_assignable<I, F, F>::type
+ move_n(I f, typename std::iterator_traits<I>::difference_type n, F r) BOOST_CONTAINER_NOEXCEPT
+{ return container_detail::memcpy_n(f, n, r); }
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// move_n_source
+//
+//////////////////////////////////////////////////////////////////////////////
+
+template
+<typename I // I models InputIterator
+,typename F> // F models ForwardIterator
+inline typename container_detail::disable_if_memcpy_copy_assignable<I, F, I>::type
+ move_n_source(I f, typename std::iterator_traits<I>::difference_type n, F r)
{
while (n--) {
- *r = *f;
+ *r = ::boost::move(*f);
++f; ++r;
}
- return r;
+ return f;
}
+template
+<typename I // I models InputIterator
+,typename F> // F models ForwardIterator
+inline typename container_detail::enable_if_memcpy_copy_assignable<I, F, I>::type
+ move_n_source(I f, typename std::iterator_traits<I>::difference_type n, F r) BOOST_CONTAINER_NOEXCEPT
+{ return container_detail::memcpy_n_source(f, n, r); }
+
//////////////////////////////////////////////////////////////////////////////
//
-// copy_or_move_n_source
+// move_n_source_dest
//
//////////////////////////////////////////////////////////////////////////////
template
-<typename I, // I models InputIterator
-typename F> // F models ForwardIterator
-inline I copy_or_move_n_source(I f, typename std::iterator_traits<I>::difference_type n, F r
- ,typename boost::container::container_detail::enable_if
- < boost::move_detail::is_move_iterator<I> >::type* = 0)
+<typename I // I models InputIterator
+,typename F> // F models ForwardIterator
+inline typename container_detail::disable_if_memcpy_copy_assignable<I, F, I>::type
+ move_n_source_dest(I f, typename std::iterator_traits<I>::difference_type n, F &r)
{
while (n--) {
*r = ::boost::move(*f);
@@ -559,23 +928,214 @@
}
template
-<typename I, // I models InputIterator
-typename F> // F models ForwardIterator
-inline I copy_or_move_n_source(I f, typename std::iterator_traits<I>::difference_type n, F r
- ,typename boost::container::container_detail::disable_if
- < boost::move_detail::is_move_iterator<I> >::type* = 0)
+<typename I // I models InputIterator
+,typename F> // F models ForwardIterator
+inline typename container_detail::enable_if_memcpy_copy_assignable<I, F, I>::type
+ move_n_source_dest(I f, typename std::iterator_traits<I>::difference_type n, F &r) BOOST_CONTAINER_NOEXCEPT
+{ return container_detail::memcpy_n_source_dest(f, n, r); }
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// destroy_n
+//
+//////////////////////////////////////////////////////////////////////////////
+
+template
+ <typename A
+ ,typename I> // I models InputIterator
+inline void destroy_alloc_n(A &a, I f, typename std::iterator_traits<I>::difference_type n
+ ,typename boost::container::container_detail::enable_if_c
+ < !boost::has_trivial_destructor<typename std::iterator_traits<I>::value_type>::value >::type* = 0)
{
- while (n--) {
- *r = *f;
- ++f; ++r;
+ while(n--){
+ allocator_traits<A>::destroy(a, container_detail::addressof(*f++));
+ }
+}
+
+template
+ <typename A
+ ,typename I> // I models InputIterator
+inline void destroy_alloc_n(A &, I, typename std::iterator_traits<I>::difference_type
+ ,typename boost::container::container_detail::enable_if_c
+ < boost::has_trivial_destructor<typename std::iterator_traits<I>::value_type>::value >::type* = 0)
+{}
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// deep_swap_alloc_n
+//
+//////////////////////////////////////////////////////////////////////////////
+
+template
+ <std::size_t MaxTmpBytes
+ ,typename A
+ ,typename F // F models ForwardIterator
+ ,typename G // G models ForwardIterator
+ >
+inline typename container_detail::disable_if_memcpy_copy_assignable<F, G, void>::type
+ deep_swap_alloc_n( A &a, F short_range_f, typename allocator_traits<A>::size_type n_i
+ , G large_range_f, typename allocator_traits<A>::size_type n_j)
+{
+ typename allocator_traits<A>::size_type n = 0;
+ for (; n != n_i ; ++short_range_f, ++large_range_f, ++n){
+ boost::container::swap_dispatch(*short_range_f, *large_range_f);
+ }
+ boost::container::uninitialized_move_alloc_n(a, large_range_f, n_j - n_i, short_range_f); // may throw
+ boost::container::destroy_alloc_n(a, large_range_f, n_j - n_i);
+}
+
+static const std::size_t DeepSwapAllocNMaxStorage = std::size_t(1) << std::size_t(11); //2K bytes
+
+template
+ <std::size_t MaxTmpBytes
+ ,typename A
+ ,typename F // F models ForwardIterator
+ ,typename G // G models ForwardIterator
+ >
+inline typename container_detail::enable_if_c
+ < container_detail::is_memcpy_copy_assignable<F, G>::value && (MaxTmpBytes <= DeepSwapAllocNMaxStorage) && false
+ , void>::type
+ deep_swap_alloc_n( A &a, F short_range_f, typename allocator_traits<A>::size_type n_i
+ , G large_range_f, typename allocator_traits<A>::size_type n_j)
+{
+ typedef typename allocator_traits<A>::value_type value_type;
+ typedef typename boost::aligned_storage
+ <MaxTmpBytes, container_detail::alignment_of<value_type>::value>::type storage_type;
+ storage_type storage;
+
+ const std::size_t n_i_bytes = sizeof(value_type)*n_i;
+ unsigned char *const large_ptr = static_cast<unsigned char*>(static_cast<void*>(container_detail::addressof(*large_range_f)));
+ unsigned char *const short_ptr = static_cast<unsigned char*>(static_cast<void*>(container_detail::addressof(*short_range_f)));
+ unsigned char *const stora_ptr = static_cast<unsigned char*>(static_cast<void*>(container_detail::addressof(storage)));
+ ::memcpy(stora_ptr, large_ptr, n_i_bytes);
+ ::memcpy(large_ptr, short_ptr, n_i_bytes);
+ ::memcpy(short_ptr, stora_ptr, n_i_bytes);
+ std::advance(large_range_f, n_i);
+ std::advance(short_range_f, n_i);
+ boost::container::uninitialized_move_alloc_n(a, large_range_f, n_j - n_i, short_range_f); // may throw
+ boost::container::destroy_alloc_n(a, large_range_f, n_j - n_i);
+}
+
+template
+ <std::size_t MaxTmpBytes
+ ,typename A
+ ,typename F // F models ForwardIterator
+ ,typename G // G models ForwardIterator
+ >
+inline typename container_detail::enable_if_c
+ < container_detail::is_memcpy_copy_assignable<F, G>::value && true//(MaxTmpBytes > DeepSwapAllocNMaxStorage)
+ , void>::type
+ deep_swap_alloc_n( A &a, F short_range_f, typename allocator_traits<A>::size_type n_i
+ , G large_range_f, typename allocator_traits<A>::size_type n_j)
+{
+ typedef typename allocator_traits<A>::value_type value_type;
+ typedef typename boost::aligned_storage
+ <DeepSwapAllocNMaxStorage, container_detail::alignment_of<value_type>::value>::type storage_type;
+ storage_type storage;
+ const std::size_t sizeof_storage = sizeof(storage);
+
+ std::size_t n_i_bytes = sizeof(value_type)*n_i;
+ char *large_ptr = static_cast<char*>(static_cast<void*>(container_detail::addressof(*large_range_f)));
+ char *short_ptr = static_cast<char*>(static_cast<void*>(container_detail::addressof(*short_range_f)));
+ char *stora_ptr = static_cast<char*>(static_cast<void*>(container_detail::addressof(storage)));
+
+ std::size_t szt_times = n_i_bytes/sizeof_storage;
+ const std::size_t szt_rem = n_i_bytes%sizeof_storage;
+
+ //Loop unrolling using Duff's device, as it seems it helps on some architectures
+ const std::size_t Unroll = 4;
+ std::size_t n = (szt_times + (Unroll-1))/Unroll;
+ const std::size_t branch_number = ((!szt_times)*Unroll) + (szt_times % Unroll);
+ switch(branch_number){
+ case 4:
+ break;
+ case 0: do{
+ ::memcpy(stora_ptr, large_ptr, sizeof_storage);
+ ::memcpy(large_ptr, short_ptr, sizeof_storage);
+ ::memcpy(short_ptr, stora_ptr, sizeof_storage);
+ large_ptr += sizeof_storage;
+ short_ptr += sizeof_storage;
+ case 3:
+ ::memcpy(stora_ptr, large_ptr, sizeof_storage);
+ ::memcpy(large_ptr, short_ptr, sizeof_storage);
+ ::memcpy(short_ptr, stora_ptr, sizeof_storage);
+ large_ptr += sizeof_storage;
+ short_ptr += sizeof_storage;
+ case 2:
+ ::memcpy(stora_ptr, large_ptr, sizeof_storage);
+ ::memcpy(large_ptr, short_ptr, sizeof_storage);
+ ::memcpy(short_ptr, stora_ptr, sizeof_storage);
+ large_ptr += sizeof_storage;
+ short_ptr += sizeof_storage;
+ case 1:
+ ::memcpy(stora_ptr, large_ptr, sizeof_storage);
+ ::memcpy(large_ptr, short_ptr, sizeof_storage);
+ ::memcpy(short_ptr, stora_ptr, sizeof_storage);
+ large_ptr += sizeof_storage;
+ short_ptr += sizeof_storage;
+ } while(--n);
+ }
+ ::memcpy(stora_ptr, large_ptr, szt_rem);
+ ::memcpy(large_ptr, short_ptr, szt_rem);
+ ::memcpy(short_ptr, stora_ptr, szt_rem);
+ std::advance(large_range_f, n_i);
+ std::advance(short_range_f, n_i);
+ boost::container::uninitialized_move_alloc_n(a, large_range_f, n_j - n_i, short_range_f); // may throw
+ boost::container::destroy_alloc_n(a, large_range_f, n_j - n_i);
+}
+
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// copy_assign_range_alloc_n
+//
+//////////////////////////////////////////////////////////////////////////////
+
+template
+ <typename A
+ ,typename I // F models InputIterator
+ ,typename O // G models OutputIterator
+ >
+void copy_assign_range_alloc_n( A &a, I inp_start, typename allocator_traits<A>::size_type n_i
+ , O out_start, typename allocator_traits<A>::size_type n_o )
+{
+ if (n_o < n_i){
+ inp_start = boost::container::copy_n_source_dest(inp_start, n_o, out_start); // may throw
+ boost::container::uninitialized_copy_alloc_n(a, inp_start, n_i - n_o, out_start);// may throw
+ }
+ else{
+ out_start = boost::container::copy_n(inp_start, n_i, out_start); // may throw
+ boost::container::destroy_alloc_n(a, out_start, n_o - n_i);
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// move_assign_range_alloc_n
+//
+//////////////////////////////////////////////////////////////////////////////
+
+template
+ <typename A
+ ,typename I // F models InputIterator
+ ,typename O // G models OutputIterator
+ >
+void move_assign_range_alloc_n( A &a, I inp_start, typename allocator_traits<A>::size_type n_i
+ , O out_start, typename allocator_traits<A>::size_type n_o )
+{
+ if (n_o < n_i){
+ inp_start = boost::container::move_n_source_dest(inp_start, n_o, out_start); // may throw
+ boost::container::uninitialized_move_alloc_n(a, inp_start, n_i - n_o, out_start); // may throw
+ }
+ else{
+ out_start = boost::container::move_n(inp_start, n_i, out_start); // may throw
+ boost::container::destroy_alloc_n(a, out_start, n_o - n_i);
}
- return f;
}
} //namespace container {
} //namespace boost {
-
#include <boost/container/detail/config_end.hpp>
#endif //#ifndef BOOST_CONTAINER_DETAIL_UTILITIES_HPP
Modified: branches/release/boost/container/flat_map.hpp
==============================================================================
--- branches/release/boost/container/flat_map.hpp (original)
+++ branches/release/boost/container/flat_map.hpp 2013-05-18 06:40:55 EDT (Sat, 18 May 2013)
@@ -22,13 +22,14 @@
#include <utility>
#include <functional>
#include <memory>
-#include <stdexcept>
#include <boost/container/detail/flat_tree.hpp>
#include <boost/type_traits/has_trivial_destructor.hpp>
#include <boost/container/detail/mpl.hpp>
#include <boost/container/allocator_traits.hpp>
+#include <boost/container/throw_exception.hpp>
#include <boost/move/utility.hpp>
#include <boost/move/detail/move_helpers.hpp>
+#include <boost/detail/no_exceptions_support.hpp>
namespace boost {
namespace container {
@@ -478,7 +479,7 @@
{
iterator i = this->find(k);
if(i == this->end()){
- throw std::out_of_range("key not found");
+ throw_out_of_range("flat_map::at key not found");
}
return i->second;
}
@@ -492,7 +493,7 @@
{
const_iterator i = this->find(k);
if(i == this->end()){
- throw std::out_of_range("key not found");
+ throw_out_of_range("flat_map::at key not found");
}
return i->second;
}
Modified: branches/release/boost/container/list.hpp
==============================================================================
--- branches/release/boost/container/list.hpp (original)
+++ branches/release/boost/container/list.hpp 2013-05-18 06:40:55 EDT (Sat, 18 May 2013)
@@ -18,6 +18,7 @@
#include <boost/container/detail/workaround.hpp>
#include <boost/container/container_fwd.hpp>
#include <boost/container/detail/version_type.hpp>
+#include <boost/container/throw_exception.hpp>
#include <boost/move/utility.hpp>
#include <boost/move/iterator.hpp>
#include <boost/move/detail/move_helpers.hpp>
@@ -36,13 +37,11 @@
#include <boost/container/detail/preprocessor.hpp>
#endif
-#include <stdexcept>
#include <iterator>
#include <utility>
#include <memory>
#include <functional>
#include <algorithm>
-#include <stdexcept>
namespace boost {
namespace container {
Modified: branches/release/boost/container/map.hpp
==============================================================================
--- branches/release/boost/container/map.hpp (original)
+++ branches/release/boost/container/map.hpp 2013-05-18 06:40:55 EDT (Sat, 18 May 2013)
@@ -22,7 +22,6 @@
#include <utility>
#include <functional>
#include <memory>
-#include <stdexcept>
#include <boost/container/detail/tree.hpp>
#include <boost/container/detail/value_init.hpp>
#include <boost/type_traits/has_trivial_destructor.hpp>
@@ -30,10 +29,12 @@
#include <boost/container/detail/utilities.hpp>
#include <boost/container/detail/pair.hpp>
#include <boost/container/detail/type_traits.hpp>
+#include <boost/container/throw_exception.hpp>
#include <boost/move/utility.hpp>
#include <boost/move/detail/move_helpers.hpp>
#include <boost/static_assert.hpp>
#include <boost/container/detail/value_init.hpp>
+#include <boost/detail/no_exceptions_support.hpp>
namespace boost {
namespace container {
@@ -423,7 +424,7 @@
{
iterator i = this->find(k);
if(i == this->end()){
- throw std::out_of_range("key not found");
+ throw_out_of_range("map::at key not found");
}
return i->second;
}
@@ -435,7 +436,7 @@
{
const_iterator i = this->find(k);
if(i == this->end()){
- throw std::out_of_range("key not found");
+ throw_out_of_range("map::at key not found");
}
return i->second;
}
Modified: branches/release/boost/container/scoped_allocator.hpp
==============================================================================
--- branches/release/boost/container/scoped_allocator.hpp (original)
+++ branches/release/boost/container/scoped_allocator.hpp 2013-05-18 06:40:55 EDT (Sat, 18 May 2013)
@@ -584,6 +584,7 @@
typedef OuterAlloc outer_allocator_type;
typedef scoped_allocator_adaptor<InnerAllocs...> inner_allocator_type;
+ typedef allocator_traits<inner_allocator_type> inner_traits_type;
typedef boost::integral_constant<
bool,
outer_traits_type::propagate_on_container_copy_assignment::value ||
@@ -723,6 +724,7 @@
( BOOST_PP_SUB(BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS, n) \
, BOOST_CONTAINER_PP_IDENTITY, nat) \
> inner_allocator_type; \
+ typedef allocator_traits<inner_allocator_type> inner_traits_type; \
typedef boost::integral_constant< \
bool, \
outer_traits_type::propagate_on_container_copy_assignment::value || \
@@ -860,6 +862,7 @@
typedef OuterAlloc outer_allocator_type;
typedef allocator_traits<OuterAlloc> outer_traits_type;
typedef scoped_allocator_adaptor<OuterAlloc> inner_allocator_type;
+ typedef allocator_traits<inner_allocator_type> inner_traits_type;
typedef typename outer_traits_type::
propagate_on_container_copy_assignment propagate_on_container_copy_assignment;
typedef typename outer_traits_type::
@@ -1029,6 +1032,7 @@
//! Type: `scoped_allocator_adaptor<OuterAlloc>` if `sizeof...(InnerAllocs)` is zero; otherwise,
//! `scoped_allocator_adaptor<InnerAllocs...>`.
typedef typename base_type::inner_allocator_type inner_allocator_type;
+ typedef allocator_traits<inner_allocator_type> inner_traits_type;
typedef typename outer_traits_type::value_type value_type;
typedef typename outer_traits_type::size_type size_type;
typedef typename outer_traits_type::difference_type difference_type;
@@ -1220,7 +1224,7 @@
return scoped_allocator_adaptor
(internal_type_t()
,outer_traits_type::select_on_container_copy_construction(this->outer_allocator())
- ,outer_traits_type::select_on_container_copy_construction(this->inner_allocator())
+ ,inner_traits_type::select_on_container_copy_construction(this->inner_allocator())
);
}
/// @cond
Modified: branches/release/boost/container/slist.hpp
==============================================================================
--- branches/release/boost/container/slist.hpp (original)
+++ branches/release/boost/container/slist.hpp 2013-05-18 06:40:55 EDT (Sat, 18 May 2013)
@@ -19,6 +19,7 @@
#include <boost/container/detail/workaround.hpp>
#include <boost/container/container_fwd.hpp>
+#include <boost/container/throw_exception.hpp>
#include <boost/move/utility.hpp>
#include <boost/move/detail/move_helpers.hpp>
#include <boost/intrusive/pointer_traits.hpp>
@@ -37,7 +38,6 @@
#include <boost/container/detail/preprocessor.hpp>
#endif
-#include <stdexcept>
#include <iterator>
#include <utility>
#include <memory>
@@ -169,7 +169,7 @@
{ return this->m_it->m_data; }
pointer operator->() const
- { return ::boost::intrusive::pointer_traits<pointer>::to_pointer(this->m_it->m_data); }
+ { return ::boost::intrusive::pointer_traits<pointer>::pointer_to(this->m_it->m_data); }
//Increment / Decrement
slist_iterator& operator++()
Modified: branches/release/boost/container/stable_vector.hpp
==============================================================================
--- branches/release/boost/container/stable_vector.hpp (original)
+++ branches/release/boost/container/stable_vector.hpp 2013-05-18 06:40:55 EDT (Sat, 18 May 2013)
@@ -1,4 +1,4 @@
-
+//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2008-2012. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
@@ -29,18 +29,21 @@
#include <boost/mpl/bool.hpp>
#include <boost/mpl/not.hpp>
#include <boost/assert.hpp>
+#include <boost/container/throw_exception.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/container/throw_exception.hpp>
#include <boost/intrusive/pointer_traits.hpp>
+#include <boost/detail/no_exceptions_support.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>
#include <new> //placement new
@@ -330,7 +333,8 @@
static void readjust_end_node(index_type &index, node_base_type &end_node)
{
if(!index.empty()){
- node_base_ptr &end_node_idx_ref = *(--index_traits::get_fix_up_end(index));
+ index_iterator end_node_it(index_traits::get_fix_up_end(index));
+ node_base_ptr &end_node_idx_ref = *(--end_node_it);
end_node_idx_ref = node_base_ptr_traits::pointer_to(end_node);
end_node.up = node_base_ptr_ptr_traits::pointer_to(end_node_idx_ref);
}
@@ -942,7 +946,7 @@
size_type size() const BOOST_CONTAINER_NOEXCEPT
{
const size_type index_size = this->index.size();
- return index_size ? (index_size - ExtraPointers) : 0;
+ return (index_size - ExtraPointers) & (std::size_t(0u) -std::size_t(index_size != 0));
}
//! <b>Effects</b>: Returns the largest possible size of the stable_vector.
@@ -998,7 +1002,9 @@
const size_type node_extra_capacity = this->internal_data.pool_size;
const size_type extra_capacity = (bucket_extra_capacity < node_extra_capacity)
? bucket_extra_capacity : node_extra_capacity;
- return (index_size ? (index_size - ExtraPointers + extra_capacity) : index_size);
+ const size_type index_offset =
+ (ExtraPointers + extra_capacity) & (size_type(0u) - size_type(index_size != 0));
+ return index_size - index_offset;
}
//! <b>Effects</b>: If n is less than or equal to capacity(), this call has no
@@ -1010,8 +1016,9 @@
void reserve(size_type n)
{
STABLE_VECTOR_CHECK_INVARIANT;
- if(n > this->max_size())
- throw std::bad_alloc();
+ if(n > this->max_size()){
+ throw_length_error("stable_vector::reserve max_size() exceeded");
+ }
size_type sz = this->size();
size_type old_capacity = this->capacity();
@@ -1098,7 +1105,7 @@
//!
//! <b>Complexity</b>: Constant.
reference back() BOOST_CONTAINER_NOEXCEPT
- { return static_cast<node_reference>(*this->index[this->size() - ExtraPointers]).value; }
+ { return static_cast<node_reference>(*this->index[this->size()-1u]).value; }
//! <b>Requires</b>: !empty()
//!
@@ -1109,7 +1116,7 @@
//!
//! <b>Complexity</b>: Constant.
const_reference back() const BOOST_CONTAINER_NOEXCEPT
- { return static_cast<const_node_reference>(*this->index[this->size() - ExtraPointers]).value; }
+ { return static_cast<const_node_reference>(*this->index[this->size()-1u]).value; }
//! <b>Requires</b>: size() > n.
//!
@@ -1120,7 +1127,10 @@
//!
//! <b>Complexity</b>: Constant.
reference operator[](size_type n) BOOST_CONTAINER_NOEXCEPT
- { return static_cast<node_reference>(*this->index[n]).value; }
+ {
+ BOOST_ASSERT(n < this->size());
+ return static_cast<node_reference>(*this->index[n]).value;
+ }
//! <b>Requires</b>: size() > n.
//!
@@ -1131,7 +1141,10 @@
//!
//! <b>Complexity</b>: Constant.
const_reference operator[](size_type n) const BOOST_CONTAINER_NOEXCEPT
- { return static_cast<const_node_reference>(*this->index[n]).value; }
+ {
+ BOOST_ASSERT(n < this->size());
+ return static_cast<const_node_reference>(*this->index[n]).value;
+ }
//! <b>Requires</b>: size() > n.
//!
@@ -1143,8 +1156,9 @@
//! <b>Complexity</b>: Constant.
reference at(size_type n)
{
- if(n>=this->size())
- throw std::out_of_range("invalid subscript at stable_vector::at");
+ if(n >= this->size()){
+ throw_out_of_range("vector::at invalid subscript");
+ }
return operator[](n);
}
@@ -1158,8 +1172,9 @@
//! <b>Complexity</b>: Constant.
const_reference at(size_type n)const
{
- if(n>=this->size())
- throw std::out_of_range("invalid subscript at stable_vector::at");
+ if(n >= this->size()){
+ throw_out_of_range("vector::at invalid subscript");
+ }
return operator[](n);
}
@@ -1705,7 +1720,7 @@
void priv_swap_members(stable_vector &x)
{
- container_detail::do_swap(this->internal_data.pool_size, x.internal_data.pool_size);
+ boost::container::swap_dispatch(this->internal_data.pool_size, x.internal_data.pool_size);
index_traits_type::readjust_end_node(this->index, this->internal_data.end_node);
index_traits_type::readjust_end_node(x.index, x.internal_data.end_node);
}
Modified: branches/release/boost/container/string.hpp
==============================================================================
--- branches/release/boost/container/string.hpp (original)
+++ branches/release/boost/container/string.hpp 2013-05-18 06:40:55 EDT (Sat, 18 May 2013)
@@ -38,6 +38,7 @@
#include <boost/container/detail/workaround.hpp>
#include <boost/container/container_fwd.hpp>
+#include <boost/container/throw_exception.hpp>
#include <boost/container/detail/utilities.hpp>
#include <boost/container/detail/iterators.hpp>
#include <boost/container/detail/algorithms.hpp>
@@ -54,8 +55,7 @@
#include <functional>
#include <string>
-#include <stdexcept>
-#include <utility>
+#include <utility>
#include <iterator>
#include <memory>
#include <algorithm>
@@ -335,8 +335,9 @@
this->priv_storage(new_cap);
}
}
- else
- throw_length_error();
+ else{
+ throw_length_error("basic_string::allocate_initial_block max_size() exceeded");
+ }
}
void deallocate_block()
@@ -345,13 +346,6 @@
size_type max_size() const
{ return allocator_traits_type::max_size(this->alloc()) - 1; }
- // Helper functions for exception handling.
- void throw_length_error() const
- { throw(std::length_error("basic_string")); }
-
- void throw_out_of_range() const
- { throw(std::out_of_range("basic_string")); }
-
protected:
size_type priv_capacity() const
{ return this->priv_storage() - 1; }
@@ -432,7 +426,7 @@
{
if(this->is_short()){
if(other.is_short()){
- container_detail::do_swap(this->members_.m_repr, other.members_.m_repr);
+ std::swap(this->members_.m_repr, other.members_.m_repr);
}
else{
short_t short_backup(this->members_.m_repr.short_repr());
@@ -453,7 +447,7 @@
this->members_.m_repr.short_repr() = short_backup;
}
else{
- container_detail::do_swap(this->members_.m_repr.long_repr(), other.members_.m_repr.long_repr());
+ boost::container::swap_dispatch(this->members_.m_repr.long_repr(), other.members_.m_repr.long_repr());
}
}
}
@@ -663,7 +657,7 @@
{
this->priv_terminate_string();
if (pos > s.size())
- this->throw_out_of_range();
+ throw_out_of_range("basic_string::basic_string out of range position");
else
this->assign
(s.begin() + pos, s.begin() + pos + container_detail::min_value(n, s.size() - pos));
@@ -991,7 +985,7 @@
void reserve(size_type res_arg)
{
if (res_arg > this->max_size()){
- this->throw_length_error();
+ throw_length_error("basic_string::reserve max_size() exceeded");
}
if (this->capacity() < res_arg){
@@ -1083,7 +1077,7 @@
reference at(size_type n)
{
if (n >= this->size())
- this->throw_out_of_range();
+ throw_out_of_range("basic_string::at invalid subscript");
return *(this->priv_addr() + n);
}
@@ -1097,7 +1091,7 @@
//! <b>Complexity</b>: Constant.
const_reference at(size_type n) const {
if (n >= this->size())
- this->throw_out_of_range();
+ throw_out_of_range("basic_string::at invalid subscript");
return *(this->priv_addr() + n);
}
@@ -1142,7 +1136,7 @@
basic_string& append(const basic_string& s, size_type pos, size_type n)
{
if (pos > s.size())
- this->throw_out_of_range();
+ throw_out_of_range("basic_string::append out of range position");
return this->append(s.begin() + pos,
s.begin() + pos + container_detail::min_value(n, s.size() - pos));
}
@@ -1226,7 +1220,7 @@
basic_string& assign(const basic_string& s, size_type pos, size_type n)
{
if (pos > s.size())
- this->throw_out_of_range();
+ throw_out_of_range("basic_string::assign out of range position");
return this->assign(s.begin() + pos,
s.begin() + pos + container_detail::min_value(n, s.size() - pos));
}
@@ -1296,9 +1290,9 @@
{
const size_type sz = this->size();
if (pos > sz)
- this->throw_out_of_range();
+ throw_out_of_range("basic_string::insert out of range position");
if (sz > this->max_size() - s.size())
- this->throw_length_error();
+ throw_length_error("basic_string::insert max_size() exceeded");
this->insert(this->priv_addr() + pos, s.begin(), s.end());
return *this;
}
@@ -1316,10 +1310,10 @@
const size_type sz = this->size();
const size_type str_size = s.size();
if (pos1 > sz || pos2 > str_size)
- this->throw_out_of_range();
+ throw_out_of_range("basic_string::insert out of range position");
size_type len = container_detail::min_value(n, str_size - pos2);
if (sz > this->max_size() - len)
- this->throw_length_error();
+ throw_length_error("basic_string::insert max_size() exceeded");
const CharT *beg_ptr = container_detail::to_raw_pointer(s.begin()) + pos2;
const CharT *end_ptr = beg_ptr + len;
this->insert(this->priv_addr() + pos1, beg_ptr, end_ptr);
@@ -1340,9 +1334,9 @@
basic_string& insert(size_type pos, const CharT* s, size_type n)
{
if (pos > this->size())
- this->throw_out_of_range();
+ throw_out_of_range("basic_string::insert out of range position");
if (this->size() > this->max_size() - n)
- this->throw_length_error();
+ throw_length_error("basic_string::insert max_size() exceeded");
this->insert(this->priv_addr() + pos, s, s + n);
return *this;
}
@@ -1358,10 +1352,10 @@
basic_string& insert(size_type pos, const CharT* s)
{
if (pos > this->size())
- this->throw_out_of_range();
+ throw_out_of_range("basic_string::insert out of range position");
size_type len = Traits::length(s);
if (this->size() > this->max_size() - len)
- this->throw_length_error();
+ throw_length_error("basic_string::insert max_size() exceeded");
this->insert(this->priv_addr() + pos, s, s + len);
return *this;
}
@@ -1375,9 +1369,9 @@
basic_string& insert(size_type pos, size_type n, CharT c)
{
if (pos > this->size())
- this->throw_out_of_range();
+ throw_out_of_range("basic_string::insert out of range position");
if (this->size() > this->max_size() - n)
- this->throw_length_error();
+ throw_length_error("basic_string::insert max_size() exceeded");
this->insert(const_iterator(this->priv_addr() + pos), n, c);
return *this;
}
@@ -1551,7 +1545,7 @@
basic_string& erase(size_type pos = 0, size_type n = npos)
{
if (pos > this->size())
- this->throw_out_of_range();
+ throw_out_of_range("basic_string::erase out of range position");
const pointer addr = this->priv_addr();
erase(addr + pos, addr + pos + container_detail::min_value(n, this->size() - pos));
return *this;
@@ -1633,10 +1627,10 @@
basic_string& replace(size_type pos1, size_type n1, const basic_string& str)
{
if (pos1 > this->size())
- this->throw_out_of_range();
+ throw_out_of_range("basic_string::replace out of range position");
const size_type len = container_detail::min_value(n1, this->size() - pos1);
if (this->size() - len >= this->max_size() - str.size())
- this->throw_length_error();
+ throw_length_error("basic_string::replace max_size() exceeded");
const pointer addr = this->priv_addr();
return this->replace( const_iterator(addr + pos1)
, const_iterator(addr + pos1 + len)
@@ -1656,11 +1650,11 @@
const basic_string& str, size_type pos2, size_type n2)
{
if (pos1 > this->size() || pos2 > str.size())
- this->throw_out_of_range();
+ throw_out_of_range("basic_string::replace out of range position");
const size_type len1 = container_detail::min_value(n1, this->size() - pos1);
const size_type len2 = container_detail::min_value(n2, str.size() - pos2);
if (this->size() - len1 >= this->max_size() - len2)
- this->throw_length_error();
+ throw_length_error("basic_string::replace max_size() exceeded");
const pointer addr = this->priv_addr();
const pointer straddr = str.priv_addr();
return this->replace(addr + pos1, addr + pos1 + len1,
@@ -1684,10 +1678,10 @@
basic_string& replace(size_type pos1, size_type n1, const CharT* s, size_type n2)
{
if (pos1 > this->size())
- this->throw_out_of_range();
+ throw_out_of_range("basic_string::replace out of range position");
const size_type len = container_detail::min_value(n1, this->size() - pos1);
if (n2 > this->max_size() || size() - len >= this->max_size() - n2)
- this->throw_length_error();
+ throw_length_error("basic_string::replace max_size() exceeded");
const pointer addr = this->priv_addr();
return this->replace(addr + pos1, addr + pos1 + len, s, s + n2);
}
@@ -1709,11 +1703,11 @@
basic_string& replace(size_type pos, size_type n1, const CharT* s)
{
if (pos > this->size())
- this->throw_out_of_range();
+ throw_out_of_range("basic_string::replace out of range position");
const size_type len = container_detail::min_value(n1, this->size() - pos);
const size_type n2 = Traits::length(s);
if (n2 > this->max_size() || this->size() - len >= this->max_size() - n2)
- this->throw_length_error();
+ throw_length_error("basic_string::replace max_size() exceeded");
const pointer addr = this->priv_addr();
return this->replace(addr + pos, addr + pos + len,
s, s + Traits::length(s));
@@ -1730,10 +1724,10 @@
basic_string& replace(size_type pos1, size_type n1, size_type n2, CharT c)
{
if (pos1 > this->size())
- this->throw_out_of_range();
+ throw_out_of_range("basic_string::replace out of range position");
const size_type len = container_detail::min_value(n1, this->size() - pos1);
if (n2 > this->max_size() || this->size() - len >= this->max_size() - n2)
- this->throw_length_error();
+ throw_length_error("basic_string::replace max_size() exceeded");
const pointer addr = this->priv_addr();
return this->replace(addr + pos1, addr + pos1 + len, n2, c);
}
@@ -1858,7 +1852,7 @@
size_type copy(CharT* s, size_type n, size_type pos = 0) const
{
if (pos > this->size())
- this->throw_out_of_range();
+ throw_out_of_range("basic_string::copy out of range position");
const size_type len = container_detail::min_value(n, this->size() - pos);
Traits::copy(s, container_detail::to_raw_pointer(this->priv_addr() + pos), len);
return len;
@@ -2230,7 +2224,7 @@
basic_string substr(size_type pos = 0, size_type n = npos) const
{
if (pos > this->size())
- this->throw_out_of_range();
+ throw_out_of_range("basic_string::substr out of range position");
const pointer addr = this->priv_addr();
return basic_string(addr + pos,
addr + pos + container_detail::min_value(n, size() - pos), this->alloc());
@@ -2263,7 +2257,7 @@
int compare(size_type pos1, size_type n1, const basic_string& str) const
{
if (pos1 > this->size())
- this->throw_out_of_range();
+ throw_out_of_range("basic_string::compare out of range position");
const pointer addr = this->priv_addr();
const pointer str_addr = str.priv_addr();
return s_compare(addr + pos1,
@@ -2282,7 +2276,7 @@
int compare(size_type pos1, size_type n1, const basic_string& str, size_type pos2, size_type n2) const
{
if (pos1 > this->size() || pos2 > str.size())
- this->throw_out_of_range();
+ throw_out_of_range("basic_string::compare out of range position");
const pointer addr = this->priv_addr();
const pointer str_addr = str.priv_addr();
return s_compare(addr + pos1,
@@ -2309,7 +2303,7 @@
int compare(size_type pos1, size_type n1, const CharT* s, size_type n2) const
{
if (pos1 > this->size())
- this->throw_out_of_range();
+ throw_out_of_range("basic_string::compare out of range position");
const pointer addr = this->priv_addr();
return s_compare( addr + pos1,
addr + pos1 + container_detail::min_value(n1, this->size() - pos1),
Modified: branches/release/boost/container/vector.hpp
==============================================================================
--- branches/release/boost/container/vector.hpp (original)
+++ branches/release/boost/container/vector.hpp 2013-05-18 06:40:55 EDT (Sat, 18 May 2013)
@@ -22,7 +22,6 @@
#include <cstddef>
#include <memory>
#include <algorithm>
-#include <stdexcept>
#include <iterator>
#include <utility>
#include <boost/detail/no_exceptions_support.hpp>
@@ -41,6 +40,7 @@
#include <boost/container/detail/destroyers.hpp>
#include <boost/container/allocator_traits.hpp>
#include <boost/container/detail/allocator_version_traits.hpp>
+#include <boost/container/throw_exception.hpp>
#include <boost/move/utility.hpp>
#include <boost/move/iterator.hpp>
#include <boost/move/detail/move_helpers.hpp>
@@ -55,8 +55,12 @@
/// @cond
+//#define BOOST_CONTAINER_VECTOR_ITERATOR_IS_POINTER
+
namespace container_detail {
+#ifndef BOOST_CONTAINER_VECTOR_ITERATOR_IS_POINTER
+
//! Const vector_iterator used to iterate through a vector.
template <class Pointer>
class vector_const_iterator
@@ -74,75 +78,88 @@
Pointer m_ptr;
public:
- Pointer get_ptr() const { return m_ptr; }
- explicit vector_const_iterator(Pointer ptr) : m_ptr(ptr){}
+ const Pointer &get_ptr() const BOOST_CONTAINER_NOEXCEPT
+ { return m_ptr; }
+
+ Pointer &get_ptr() BOOST_CONTAINER_NOEXCEPT
+ { return m_ptr; }
+
+ explicit vector_const_iterator(Pointer ptr) BOOST_CONTAINER_NOEXCEPT
+ : m_ptr(ptr)
+ {}
/// @endcond
public:
//Constructors
- vector_const_iterator() : m_ptr(0){}
+ vector_const_iterator() BOOST_CONTAINER_NOEXCEPT
+ #ifndef NDEBUG
+ : m_ptr()
+ #else
+ // No value initialization of m_ptr() to speed up things a bit:
+ #endif
+ {}
//Pointer like operators
- reference operator*() const
+ reference operator*() const BOOST_CONTAINER_NOEXCEPT
{ return *m_ptr; }
- const value_type * operator->() const
+ const value_type * operator->() const BOOST_CONTAINER_NOEXCEPT
{ return container_detail::to_raw_pointer(m_ptr); }
- reference operator[](difference_type off) const
+ reference operator[](difference_type off) const BOOST_CONTAINER_NOEXCEPT
{ return m_ptr[off]; }
//Increment / Decrement
- vector_const_iterator& operator++()
+ vector_const_iterator& operator++() BOOST_CONTAINER_NOEXCEPT
{ ++m_ptr; return *this; }
- vector_const_iterator operator++(int)
- { Pointer tmp = m_ptr; ++*this; return vector_const_iterator(tmp); }
+ vector_const_iterator operator++(int) BOOST_CONTAINER_NOEXCEPT
+ { return vector_const_iterator(m_ptr++); }
- vector_const_iterator& operator--()
+ vector_const_iterator& operator--() BOOST_CONTAINER_NOEXCEPT
{ --m_ptr; return *this; }
- vector_const_iterator operator--(int)
- { Pointer tmp = m_ptr; --*this; return vector_const_iterator(tmp); }
+ vector_const_iterator operator--(int) BOOST_CONTAINER_NOEXCEPT
+ { return vector_const_iterator(m_ptr--); }
//Arithmetic
- vector_const_iterator& operator+=(difference_type off)
+ vector_const_iterator& operator+=(difference_type off) BOOST_CONTAINER_NOEXCEPT
{ m_ptr += off; return *this; }
- vector_const_iterator operator+(difference_type off) const
- { return vector_const_iterator(m_ptr+off); }
+ vector_const_iterator& operator-=(difference_type off) BOOST_CONTAINER_NOEXCEPT
+ { m_ptr -= off; return *this; }
- friend vector_const_iterator operator+(difference_type off, const vector_const_iterator& right)
- { return vector_const_iterator(off + right.m_ptr); }
+ friend vector_const_iterator operator+(const vector_const_iterator &x, difference_type off) BOOST_CONTAINER_NOEXCEPT
+ { return vector_const_iterator(x.m_ptr+off); }
- vector_const_iterator& operator-=(difference_type off)
- { m_ptr -= off; return *this; }
+ friend vector_const_iterator operator+(difference_type off, vector_const_iterator right) BOOST_CONTAINER_NOEXCEPT
+ { right.m_ptr += off; return right; }
- vector_const_iterator operator-(difference_type off) const
- { return vector_const_iterator(m_ptr-off); }
+ friend vector_const_iterator operator-(vector_const_iterator left, difference_type off) BOOST_CONTAINER_NOEXCEPT
+ { left.m_ptr -= off; return left; }
- difference_type operator-(const vector_const_iterator& right) const
- { return m_ptr - right.m_ptr; }
+ friend difference_type operator-(const vector_const_iterator &left, const vector_const_iterator& right) BOOST_CONTAINER_NOEXCEPT
+ { return left.m_ptr - right.m_ptr; }
//Comparison operators
- bool operator== (const vector_const_iterator& r) const
- { return m_ptr == r.m_ptr; }
+ friend bool operator== (const vector_const_iterator& l, const vector_const_iterator& r) BOOST_CONTAINER_NOEXCEPT
+ { return l.m_ptr == r.m_ptr; }
- bool operator!= (const vector_const_iterator& r) const
- { return m_ptr != r.m_ptr; }
+ friend bool operator!= (const vector_const_iterator& l, const vector_const_iterator& r) BOOST_CONTAINER_NOEXCEPT
+ { return l.m_ptr != r.m_ptr; }
- bool operator< (const vector_const_iterator& r) const
- { return m_ptr < r.m_ptr; }
+ friend bool operator< (const vector_const_iterator& l, const vector_const_iterator& r) BOOST_CONTAINER_NOEXCEPT
+ { return l.m_ptr < r.m_ptr; }
- bool operator<= (const vector_const_iterator& r) const
- { return m_ptr <= r.m_ptr; }
+ friend bool operator<= (const vector_const_iterator& l, const vector_const_iterator& r) BOOST_CONTAINER_NOEXCEPT
+ { return l.m_ptr <= r.m_ptr; }
- bool operator> (const vector_const_iterator& r) const
- { return m_ptr > r.m_ptr; }
+ friend bool operator> (const vector_const_iterator& l, const vector_const_iterator& r) BOOST_CONTAINER_NOEXCEPT
+ { return l.m_ptr > r.m_ptr; }
- bool operator>= (const vector_const_iterator& r) const
- { return m_ptr >= r.m_ptr; }
+ friend bool operator>= (const vector_const_iterator& l, const vector_const_iterator& r) BOOST_CONTAINER_NOEXCEPT
+ { return l.m_ptr >= r.m_ptr; }
};
//! Iterator used to iterate through a vector
@@ -150,9 +167,10 @@
class vector_iterator
: public vector_const_iterator<Pointer>
{
+ typedef vector_const_iterator<Pointer> base_t;
public:
- explicit vector_iterator(Pointer ptr)
- : vector_const_iterator<Pointer>(ptr)
+ explicit vector_iterator(Pointer ptr) BOOST_CONTAINER_NOEXCEPT
+ : base_t(ptr)
{}
public:
@@ -163,52 +181,101 @@
typedef value_type& reference;
//Constructors
- vector_iterator()
+ vector_iterator() BOOST_CONTAINER_NOEXCEPT
+ : base_t()
{}
//Pointer like operators
- reference operator*() const
+ reference operator*() const BOOST_CONTAINER_NOEXCEPT
{ return *this->m_ptr; }
- value_type* operator->() const
- { return container_detail::to_raw_pointer(this->m_ptr); }
+ value_type* operator->() const BOOST_CONTAINER_NOEXCEPT
+ { return container_detail::to_raw_pointer(this->m_ptr); }
- reference operator[](difference_type off) const
+ reference operator[](difference_type off) const BOOST_CONTAINER_NOEXCEPT
{ return this->m_ptr[off]; }
//Increment / Decrement
- vector_iterator& operator++()
+ vector_iterator& operator++() BOOST_CONTAINER_NOEXCEPT
{ ++this->m_ptr; return *this; }
- vector_iterator operator++(int)
- { pointer tmp = this->m_ptr; ++*this; return vector_iterator(tmp); }
+ vector_iterator operator++(int) BOOST_CONTAINER_NOEXCEPT
+ { return vector_iterator(this->m_ptr++); }
- vector_iterator& operator--()
+ vector_iterator& operator--() BOOST_CONTAINER_NOEXCEPT
{ --this->m_ptr; return *this; }
- vector_iterator operator--(int)
- { vector_iterator tmp = *this; --*this; return vector_iterator(tmp); }
+ vector_iterator operator--(int) BOOST_CONTAINER_NOEXCEPT
+ { return vector_iterator(this->m_ptr--); }
// Arithmetic
- vector_iterator& operator+=(difference_type off)
+ vector_iterator& operator+=(difference_type off) BOOST_CONTAINER_NOEXCEPT
{ this->m_ptr += off; return *this; }
- vector_iterator operator+(difference_type off) const
- { return vector_iterator(this->m_ptr+off); }
+ vector_iterator& operator-=(difference_type off) BOOST_CONTAINER_NOEXCEPT
+ { this->m_ptr -= off; return *this; }
- friend vector_iterator operator+(difference_type off, const vector_iterator& right)
- { return vector_iterator(off + right.m_ptr); }
+ friend vector_iterator operator+(vector_iterator left, difference_type off) BOOST_CONTAINER_NOEXCEPT
+ { left.m_ptr += off; return left; }
- vector_iterator& operator-=(difference_type off)
- { this->m_ptr -= off; return *this; }
+ friend vector_iterator operator+(difference_type off, vector_iterator right) BOOST_CONTAINER_NOEXCEPT
+ { right.m_ptr += off; return right; }
- vector_iterator operator-(difference_type off) const
- { return vector_iterator(this->m_ptr-off); }
+ friend vector_iterator operator-(vector_iterator left, difference_type off) BOOST_CONTAINER_NOEXCEPT
+ { left.m_ptr -= off; return left; }
+};
+
+} //namespace container_detail {
+
+template<class Pointer>
+const Pointer &vector_iterator_get_ptr(const container_detail::vector_const_iterator<Pointer> &it) BOOST_CONTAINER_NOEXCEPT
+{ return it.get_ptr(); }
+
+template<class Pointer>
+Pointer &get_ptr(container_detail::vector_const_iterator<Pointer> &it) BOOST_CONTAINER_NOEXCEPT
+{ return it.get_ptr(); }
+
+namespace container_detail {
- difference_type operator-(const vector_const_iterator<Pointer>& right) const
- { return static_cast<const vector_const_iterator<Pointer>&>(*this) - right; }
+#else //ifndef BOOST_CONTAINER_VECTOR_ITERATOR_IS_POINTER
+
+template< class MaybeConstPointer
+ , bool ElementTypeIsConst
+ = is_const< typename boost::intrusive::pointer_traits<MaybeConstPointer>::element_type>::value >
+struct vector_get_ptr_pointer_to_non_const
+{
+ typedef MaybeConstPointer const_pointer;
+ typedef boost::intrusive::pointer_traits<const_pointer> pointer_traits_t;
+ typedef typename pointer_traits_t::element_type element_type;
+ typedef typename remove_const<element_type>::type non_const_element_type;
+ typedef typename pointer_traits_t
+ ::template rebind_pointer<non_const_element_type>::type return_type;
+
+ static return_type get_ptr(const const_pointer &ptr)
+ { return boost::intrusive::pointer_traits<return_type>::const_cast_from(ptr); }
+};
+
+template<class Pointer>
+struct vector_get_ptr_pointer_to_non_const<Pointer, false>
+{
+ typedef const Pointer & return_type;
+ static return_type get_ptr(const Pointer &ptr)
+ { return ptr; }
};
+} //namespace container_detail {
+
+template<class MaybeConstPointer>
+typename container_detail::vector_get_ptr_pointer_to_non_const<MaybeConstPointer>::return_type
+ vector_iterator_get_ptr(const MaybeConstPointer &ptr) BOOST_CONTAINER_NOEXCEPT
+{
+ return container_detail::vector_get_ptr_pointer_to_non_const<MaybeConstPointer>::get_ptr(ptr);
+}
+
+namespace container_detail {
+
+#endif //#ifndef BOOST_CONTAINER_VECTOR_ITERATOR_IS_POINTER
+
template <class T, class Allocator>
struct vector_value_traits
{
@@ -216,15 +283,10 @@
typedef Allocator allocator_type;
static const bool trivial_dctr = boost::has_trivial_destructor<value_type>::value;
static const bool trivial_dctr_after_move = ::boost::has_trivial_destructor_after_move<value_type>::value;
- //static const bool trivial_copy = has_trivial_copy<value_type>::value;
- //static const bool nothrow_copy = has_nothrow_copy<value_type>::value;
- //static const bool trivial_assign = has_trivial_assign<value_type>::value;
- //static const bool nothrow_assign = has_nothrow_assign<value_type>::value;
-
static const bool trivial_copy = has_trivial_copy<value_type>::value;
- static const bool nothrow_copy = has_nothrow_copy<value_type>::value;
+ static const bool nothrow_copy = has_nothrow_copy<value_type>::value || trivial_copy;
static const bool trivial_assign = has_trivial_assign<value_type>::value;
- static const bool nothrow_assign = false;
+ static const bool nothrow_assign = has_nothrow_assign<value_type>::value || trivial_assign;
//This is the anti-exception array destructor
//to deallocate values already constructed
@@ -249,43 +311,85 @@
};
//!This struct deallocates and allocated memory
-template <class Allocator>
+template < class Allocator
+ , class AllocatorVersion = container_detail::integral_constant
+ < unsigned
+ , boost::container::container_detail::version<Allocator>::value
+ >
+ >
struct vector_alloc_holder
+ : public Allocator
{
+ private:
+ BOOST_MOVABLE_BUT_NOT_COPYABLE(vector_alloc_holder)
+
+ public:
typedef boost::container::allocator_traits<Allocator> allocator_traits_type;
typedef typename allocator_traits_type::pointer pointer;
typedef typename allocator_traits_type::size_type size_type;
typedef typename allocator_traits_type::value_type value_type;
- typedef vector_value_traits<value_type, Allocator> value_traits;
//Constructor, does not throw
vector_alloc_holder()
BOOST_CONTAINER_NOEXCEPT_IF(::boost::has_nothrow_default_constructor<Allocator>::value)
- : members_()
+ : Allocator(), m_start(), m_size(), m_capacity()
{}
//Constructor, does not throw
template<class AllocConvertible>
explicit vector_alloc_holder(BOOST_FWD_REF(AllocConvertible) a) BOOST_CONTAINER_NOEXCEPT
- : members_(boost::forward<AllocConvertible>(a))
+ : Allocator(boost::forward<AllocConvertible>(a)), m_start(), m_size(), m_capacity()
{}
- //Destructor
- ~vector_alloc_holder()
+ //Constructor, does not throw
+ template<class AllocConvertible>
+ explicit vector_alloc_holder(BOOST_FWD_REF(AllocConvertible) a, size_type initial_size)
+ : Allocator(boost::forward<AllocConvertible>(a))
+ , m_size(initial_size) //Size is initialized here so vector should only call uninitialized_xxx after this
+ {
+ m_start = this->allocation_command(allocate_new, initial_size, initial_size, m_capacity, m_start).first;
+ }
+
+ //Constructor, does not throw
+ explicit vector_alloc_holder(size_type initial_size)
+ : Allocator()
+ , m_size(initial_size) //Size is initialized here so vector should only call uninitialized_xxx after this
+ {
+ m_start = this->allocation_command
+ (allocate_new, initial_size, initial_size, m_capacity, m_start).first;
+ }
+
+ vector_alloc_holder(BOOST_RV_REF(vector_alloc_holder) holder) BOOST_CONTAINER_NOEXCEPT
+ : Allocator(boost::move(static_cast<Allocator&>(holder)))
+ , m_start(holder.m_start)
+ , m_size(holder.m_size)
+ , m_capacity(holder.m_capacity)
+ {
+ holder.m_start = pointer();
+ holder.m_size = holder.m_capacity = 0;
+ }
+
+ void first_allocation(size_type cap)
+ {
+ m_start = this->allocation_command
+ (allocate_new, cap, cap, m_capacity, m_start).first;
+ }
+
+ void first_allocation_same_allocator_type(size_type cap)
+ { this->first_allocation(cap); }
+
+ ~vector_alloc_holder() BOOST_CONTAINER_NOEXCEPT
{
- this->prot_destroy_all();
- this->prot_deallocate();
+ if(this->m_capacity){
+ this->alloc().deallocate(this->m_start, this->m_capacity);
+ }
}
- typedef container_detail::integral_constant<unsigned, 1> allocator_v1;
- typedef container_detail::integral_constant<unsigned, 2> allocator_v2;
- typedef container_detail::integral_constant<unsigned,
- boost::container::container_detail::version<Allocator>::value> alloc_version;
std::pair<pointer, bool>
allocation_command(allocation_type command,
size_type limit_size,
size_type preferred_size,
- size_type &received_size, const pointer &reuse = 0)
+ size_type &received_size, const pointer &reuse = pointer())
{
return allocator_version_traits<Allocator>::allocation_command
(this->alloc(), command, limit_size, preferred_size, received_size, reuse);
@@ -293,76 +397,170 @@
size_type next_capacity(size_type additional_objects) const
{
- std::size_t num_objects = this->members_.m_size + additional_objects;
- std::size_t next_cap = this->members_.m_capacity + this->members_.m_capacity/2;
+ std::size_t num_objects = this->m_size + additional_objects;
+ std::size_t next_cap = this->m_capacity + this->m_capacity/2;
return num_objects > next_cap ? num_objects : next_cap;/*
- return get_next_capacity( allocator_traits_type::max_size(this->alloc())
- , this->members_.m_capacity, additional_objects);*/
+ return get_next_capacity( allocator_traits_type::max_size(this->m_holder.alloc())
+ , this->m_capacity, additional_objects);*/
+ }
+
+ pointer m_start;
+ size_type m_size;
+ size_type m_capacity;
+
+ void swap(vector_alloc_holder &x) BOOST_CONTAINER_NOEXCEPT
+ {
+ boost::container::swap_dispatch(this->m_start, x.m_start);
+ boost::container::swap_dispatch(this->m_size, x.m_size);
+ boost::container::swap_dispatch(this->m_capacity, x.m_capacity);
}
- struct members_holder
- : public Allocator
+ void move_from_empty(vector_alloc_holder &x) BOOST_CONTAINER_NOEXCEPT
{
- private:
- members_holder(const members_holder&);
+ this->m_start = x.m_start;
+ this->m_size = x.m_size;
+ this->m_capacity = x.m_capacity;
+ x.m_start = pointer();
+ x.m_size = x.m_capacity = 0;
+ }
+
+ Allocator &alloc() BOOST_CONTAINER_NOEXCEPT
+ { return *this; }
+
+ const Allocator &alloc() const BOOST_CONTAINER_NOEXCEPT
+ { return *this; }
+
+ const pointer &start() const BOOST_CONTAINER_NOEXCEPT { return m_start; }
+ const size_type &capacity() const BOOST_CONTAINER_NOEXCEPT { return m_capacity; }
+ void start(const pointer &p) BOOST_CONTAINER_NOEXCEPT { m_start = p; }
+ void capacity(const size_type &c) BOOST_CONTAINER_NOEXCEPT { m_capacity = c; }
+};
+
+//!This struct deallocates and allocated memory
+template <class Allocator>
+struct vector_alloc_holder<Allocator, container_detail::integral_constant<unsigned, 0> >
+ : public Allocator
+{
+ private:
+ BOOST_MOVABLE_BUT_NOT_COPYABLE(vector_alloc_holder)
+
+ public:
+ typedef boost::container::allocator_traits<Allocator> allocator_traits_type;
+ typedef typename allocator_traits_type::pointer pointer;
+ typedef typename allocator_traits_type::size_type size_type;
+ typedef typename allocator_traits_type::value_type value_type;
- public:
- template<class Alloc>
- explicit members_holder(BOOST_FWD_REF(Alloc) alloc)
- : Allocator(boost::forward<Alloc>(alloc)), m_start(0), m_size(0), m_capacity(0)
- {}
+ template <class OtherAllocator, class OtherAllocatorVersion>
+ friend struct vector_alloc_holder;
- members_holder()
- : Allocator(), m_start(0), m_size(0), m_capacity(0)
- {}
+ //Constructor, does not throw
+ vector_alloc_holder()
+ BOOST_CONTAINER_NOEXCEPT_IF(::boost::has_nothrow_default_constructor<Allocator>::value)
+ : Allocator(), m_size()
+ {}
- pointer m_start;
- size_type m_size;
- size_type m_capacity;
- } members_;
+ //Constructor, does not throw
+ template<class AllocConvertible>
+ explicit vector_alloc_holder(BOOST_FWD_REF(AllocConvertible) a) BOOST_CONTAINER_NOEXCEPT
+ : Allocator(boost::forward<AllocConvertible>(a)), m_size()
+ {}
- void swap_members(vector_alloc_holder &x)
+ //Constructor, does not throw
+ template<class AllocConvertible>
+ explicit vector_alloc_holder(BOOST_FWD_REF(AllocConvertible) a, size_type initial_size)
+ : Allocator(boost::forward<AllocConvertible>(a))
+ , m_size(initial_size) //Size is initialized here so vector should only call uninitialized_xxx after this
{
- container_detail::do_swap(this->members_.m_start, x.members_.m_start);
- container_detail::do_swap(this->members_.m_size, x.members_.m_size);
- container_detail::do_swap(this->members_.m_capacity, x.members_.m_capacity);
+ this->first_allocation(initial_size);
}
- Allocator &alloc()
- { return members_; }
+ //Constructor, does not throw
+ explicit vector_alloc_holder(size_type initial_size)
+ : Allocator()
+ , m_size(initial_size) //Size is initialized here so vector should only call uninitialized_xxx after this
+ {
+ this->first_allocation(initial_size);
+ }
- const Allocator &alloc() const
- { return members_; }
+ vector_alloc_holder(BOOST_RV_REF(vector_alloc_holder) holder)
+ : Allocator(boost::move(static_cast<Allocator&>(holder)))
+ , m_size(holder.m_size) //Size is initialized here so vector should only call uninitialized_xxx after this
+ {
+ ::boost::container::uninitialized_move_alloc_n
+ (this->alloc(), container_detail::to_raw_pointer(holder.start()), m_size, container_detail::to_raw_pointer(this->start()));
+ }
- protected:
- void prot_deallocate()
+ template<class OtherAllocator, class OtherAllocatorVersion>
+ vector_alloc_holder(BOOST_RV_REF_BEG vector_alloc_holder<OtherAllocator, OtherAllocatorVersion> BOOST_RV_REF_END holder)
+ : Allocator()
+ , m_size(holder.m_size) //Initialize it to m_size as first_allocation can only succeed or abort
{
- if(!this->members_.m_capacity) return;
- this->alloc().deallocate(this->members_.m_start, this->members_.m_capacity);
- this->members_.m_start = 0;
- this->members_.m_size = 0;
- this->members_.m_capacity = 0;
+ //Different allocator type so we must check we have enough storage
+ const size_type n = holder.m_size;
+ this->first_allocation(n);
+ ::boost::container::uninitialized_move_alloc_n
+ (this->alloc(), container_detail::to_raw_pointer(holder.start()), n, container_detail::to_raw_pointer(this->start()));
}
- void destroy(value_type* p)
+ void first_allocation(size_type cap)
{
- if(!value_traits::trivial_dctr)
- allocator_traits_type::destroy(this->alloc(), p);
+ if(cap > Allocator::internal_capacity){
+ throw_bad_alloc();
+ }
}
- void destroy_n(value_type* p, size_type n)
+ void first_allocation_same_allocator_type(size_type) BOOST_CONTAINER_NOEXCEPT
+ {}
+
+ //Destructor
+ ~vector_alloc_holder() BOOST_CONTAINER_NOEXCEPT
+ {}
+
+ void swap(vector_alloc_holder &x)
{
- if(!value_traits::trivial_dctr){
- for(; n--; ++p){
- allocator_traits_type::destroy(this->alloc(), p);
- }
+ this->priv_swap_members_impl(x);
+ }
+
+ template<class OtherAllocator, class OtherAllocatorVersion>
+ void swap(vector_alloc_holder<OtherAllocator, OtherAllocatorVersion> &x)
+ {
+ if(this->m_size > OtherAllocator::internal_capacity || x.m_size > Allocator::internal_capacity){
+ throw_bad_alloc();
}
+ this->priv_swap_members_impl(x);
}
- void prot_destroy_all()
+ void move_from_empty(vector_alloc_holder &)
+ { //Containers with version 0 allocators can't be moved without move elements one by one
+ throw_bad_alloc();
+ }
+
+ Allocator &alloc() BOOST_CONTAINER_NOEXCEPT
+ { return *this; }
+
+ const Allocator &alloc() const BOOST_CONTAINER_NOEXCEPT
+ { return *this; }
+
+ pointer start() const BOOST_CONTAINER_NOEXCEPT { return Allocator::internal_storage(); }
+ size_type capacity() const BOOST_CONTAINER_NOEXCEPT { return Allocator::internal_capacity; }
+ size_type m_size;
+
+ private:
+
+ template<class OtherAllocator, class OtherAllocatorVersion>
+ void priv_swap_members_impl(vector_alloc_holder<OtherAllocator, OtherAllocatorVersion> &x)
{
- this->destroy_n(container_detail::to_raw_pointer(this->members_.m_start), this->members_.m_size);
- this->members_.m_size = 0;
+ const std::size_t MaxTmpStorage = sizeof(value_type)*Allocator::internal_capacity;
+ value_type *const first_this = container_detail::to_raw_pointer(this->start());
+ value_type *const first_x = container_detail::to_raw_pointer(x.start());
+
+ if(this->m_size < x.m_size){
+ boost::container::deep_swap_alloc_n<MaxTmpStorage>(this->alloc(), first_this, this->m_size, first_x, x.m_size);
+ }
+ else{
+ boost::container::deep_swap_alloc_n<MaxTmpStorage>(this->alloc(), first_x, x.m_size, first_this, this->m_size);
+ }
+ boost::container::swap_dispatch(this->m_size, x.m_size);
}
};
@@ -381,11 +579,17 @@
#else
template <class T, class Allocator>
#endif
-class vector : private container_detail::vector_alloc_holder<Allocator>
+class vector
{
/// @cond
+ typedef container_detail::integral_constant
+ <unsigned, boost::container::container_detail::version
+ <Allocator>::value > alloc_version;
+ boost::container::container_detail::vector_alloc_holder<Allocator, alloc_version> m_holder;
typedef container_detail::vector_alloc_holder<Allocator> base_t;
typedef allocator_traits<Allocator> allocator_traits_type;
+ template <class U, class UAllocator>
+ friend class vector;
/// @endcond
public:
//////////////////////////////////////////////
@@ -403,8 +607,13 @@
typedef typename ::boost::container::allocator_traits<Allocator>::difference_type difference_type;
typedef Allocator allocator_type;
typedef Allocator stored_allocator_type;
+ #if defined BOOST_CONTAINER_VECTOR_ITERATOR_IS_POINTER && !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+ typedef BOOST_CONTAINER_IMPDEF(pointer) iterator;
+ typedef BOOST_CONTAINER_IMPDEF(const_pointer) const_iterator;
+ #else
typedef BOOST_CONTAINER_IMPDEF(container_detail::vector_iterator<pointer>) iterator;
typedef BOOST_CONTAINER_IMPDEF(container_detail::vector_const_iterator<pointer>) const_iterator;
+ #endif
typedef BOOST_CONTAINER_IMPDEF(std::reverse_iterator<iterator>) reverse_iterator;
typedef BOOST_CONTAINER_IMPDEF(std::reverse_iterator<const_iterator>) const_reverse_iterator;
@@ -413,11 +622,11 @@
BOOST_COPYABLE_AND_MOVABLE(vector)
typedef container_detail::vector_value_traits<value_type, Allocator> value_traits;
- typedef typename base_t::allocator_v1 allocator_v1;
- typedef typename base_t::allocator_v2 allocator_v2;
- typedef typename base_t::alloc_version alloc_version;
+ typedef container_detail::integral_constant<unsigned, 0> allocator_v0;
+ typedef container_detail::integral_constant<unsigned, 1> allocator_v1;
+ typedef container_detail::integral_constant<unsigned, 2> allocator_v2;
- typedef constant_iterator<T, difference_type> cvalue_iterator;
+ typedef constant_iterator<T, difference_type> cvalue_iterator;
/// @endcond
public:
@@ -434,7 +643,7 @@
//! <b>Complexity</b>: Constant.
vector()
BOOST_CONTAINER_NOEXCEPT_IF(::boost::has_nothrow_default_constructor<Allocator>::value)
- : base_t()
+ : m_holder()
{}
//! <b>Effects</b>: Constructs a vector taking the allocator as parameter.
@@ -443,7 +652,7 @@
//!
//! <b>Complexity</b>: Constant.
explicit vector(const Allocator& a) BOOST_CONTAINER_NOEXCEPT
- : base_t(a)
+ : m_holder(a)
{}
//! <b>Effects</b>: Constructs a vector that will use a copy of allocator a
@@ -454,19 +663,50 @@
//!
//! <b>Complexity</b>: Linear to n.
explicit vector(size_type n)
- : base_t()
- { this->resize(n); }
+ : m_holder(n)
+ {
+ boost::container::uninitialized_default_alloc_n(this->m_holder.alloc(), n, container_detail::to_raw_pointer(this->m_holder.start()));
+ }
- //! <b>Effects</b>: Constructs a vector that will use a copy of allocator a
+ //! <b>Effects</b>: Constructs a vector
//! and inserts n copies of value.
//!
//! <b>Throws</b>: If allocator_type's default constructor or allocation
//! throws or T's copy constructor throws.
//!
//! <b>Complexity</b>: Linear to n.
- vector(size_type n, const T& value, const allocator_type& a = allocator_type())
- : base_t(a)
- { this->resize(n, value); }
+ vector(size_type n, const T& value)
+ : m_holder(n)
+ {
+ boost::container::uninitialized_fill_alloc_n
+ (this->m_holder.alloc(), value, n, container_detail::to_raw_pointer(this->m_holder.start()));
+ }
+
+ //! <b>Effects</b>: Constructs a vector that will use a copy of allocator a
+ //! and inserts n copies of value.
+ //!
+ //! <b>Throws</b>: If allocation
+ //! throws or T's copy constructor throws.
+ //!
+ //! <b>Complexity</b>: Linear to n.
+ vector(size_type n, const T& value, const allocator_type& a)
+ : m_holder(a, n)
+ {
+ boost::container::uninitialized_fill_alloc_n
+ (this->m_holder.alloc(), value, n, container_detail::to_raw_pointer(this->m_holder.start()));
+ }
+
+ //! <b>Effects</b>: Constructs a vector
+ //! and inserts a copy of the range [first, last) in the vector.
+ //!
+ //! <b>Throws</b>: If allocator_type's default constructor or allocation
+ //! throws or T's constructor taking an dereferenced InIt throws.
+ //!
+ //! <b>Complexity</b>: Linear to the range [first, last).
+ template <class InIt>
+ vector(InIt first, InIt last)
+ : m_holder()
+ { this->insert(this->cend(), first, last); }
//! <b>Effects</b>: Constructs a vector that will use a copy of allocator a
//! and inserts a copy of the range [first, last) in the vector.
@@ -476,9 +716,9 @@
//!
//! <b>Complexity</b>: Linear to the range [first, last).
template <class InIt>
- vector(InIt first, InIt last, const allocator_type& a = allocator_type())
- : base_t(a)
- { this->assign(first, last); }
+ vector(InIt first, InIt last, const allocator_type& a)
+ : m_holder(a)
+ { this->insert(this->cend(), first, last); }
//! <b>Effects</b>: Copy constructs a vector.
//!
@@ -489,10 +729,11 @@
//!
//! <b>Complexity</b>: Linear to the elements x contains.
vector(const vector &x)
- : base_t(allocator_traits_type::select_on_container_copy_construction(x.alloc()))
+ : m_holder(allocator_traits_type::select_on_container_copy_construction(x.m_holder.alloc()), x.size())
{
- this->assign( container_detail::to_raw_pointer(x.members_.m_start)
- , container_detail::to_raw_pointer(x.members_.m_start + x.members_.m_size));
+ ::boost::container::uninitialized_copy_alloc_n
+ ( this->m_holder.alloc(), container_detail::to_raw_pointer(x.m_holder.start())
+ , x.size(), container_detail::to_raw_pointer(this->m_holder.start()));
}
//! <b>Effects</b>: Move constructor. Moves mx's resources to *this.
@@ -501,8 +742,24 @@
//!
//! <b>Complexity</b>: Constant.
vector(BOOST_RV_REF(vector) mx) BOOST_CONTAINER_NOEXCEPT
- : base_t(boost::move(mx.alloc()))
- { this->swap_members(mx); }
+ : m_holder(boost::move(mx.m_holder))
+ {}
+
+ #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+
+ //! <b>Effects</b>: Move constructor. Moves mx's resources to *this.
+ //!
+ //! <b>Throws</b>: If T's move constructor or allocation throws
+ //!
+ //! <b>Complexity</b>: Linear.
+ //!
+ //! <b>Note</b>: Non-standard extension
+ template<class OtherAllocator>
+ vector(BOOST_RV_REF_BEG vector<T, OtherAllocator> BOOST_RV_REF_END mx)
+ : m_holder(boost::move(mx.m_holder))
+ {}
+
+ #endif //!defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
//! <b>Effects</b>: Copy constructs a vector using the specified allocator.
//!
@@ -513,10 +770,11 @@
//!
//! <b>Complexity</b>: Linear to the elements x contains.
vector(const vector &x, const allocator_type &a)
- : base_t(a)
+ : m_holder(a, x.size())
{
- this->assign( container_detail::to_raw_pointer(x.members_.m_start)
- , container_detail::to_raw_pointer(x.members_.m_start + x.members_.m_size));
+ ::boost::container::uninitialized_copy_alloc_n_source
+ ( this->m_holder.alloc(), container_detail::to_raw_pointer(x.m_holder.start())
+ , x.size(), container_detail::to_raw_pointer(this->m_holder.start()));
}
//! <b>Effects</b>: Move constructor using the specified allocator.
@@ -527,14 +785,18 @@
//!
//! <b>Complexity</b>: Constant if a == mx.get_allocator(), linear otherwise.
vector(BOOST_RV_REF(vector) mx, const allocator_type &a)
- : base_t(a)
+ : m_holder(a)
{
- if(mx.alloc() == a){
- this->swap_members(mx);
+ if(mx.m_holder.alloc() == a){
+ this->m_holder.move_from_empty(mx.m_holder);
}
else{
- this->assign( container_detail::to_raw_pointer(mx.members_.m_start)
- , container_detail::to_raw_pointer(mx.members_.m_start) + mx.members_.m_size);
+ const size_type n = mx.size();
+ this->m_holder.first_allocation_same_allocator_type(n);
+ ::boost::container::uninitialized_move_alloc_n_source
+ ( this->m_holder.alloc(), container_detail::to_raw_pointer(mx.m_holder.start())
+ , n, container_detail::to_raw_pointer(this->m_holder.start()));
+ this->m_holder.m_size = n;
}
}
@@ -545,7 +807,11 @@
//!
//! <b>Complexity</b>: Linear to the number of elements.
~vector() BOOST_CONTAINER_NOEXCEPT
- {} //vector_alloc_holder clears the data
+ {
+ boost::container::destroy_alloc_n
+ (this->get_stored_allocator(), container_detail::to_raw_pointer(this->m_holder.start()), this->m_holder.m_size);
+ //vector_alloc_holder deallocates the data
+ }
//! <b>Effects</b>: Makes *this contain the same elements as x.
//!
@@ -558,17 +824,7 @@
vector& operator=(BOOST_COPY_ASSIGN_REF(vector) x)
{
if (&x != this){
- allocator_type &this_alloc = this->alloc();
- const allocator_type &x_alloc = x.alloc();
- container_detail::bool_<allocator_traits_type::
- propagate_on_container_copy_assignment::value> flag;
- if(flag && this_alloc != x_alloc){
- this->clear();
- this->shrink_to_fit();
- }
- container_detail::assign_alloc(this_alloc, x_alloc, flag);
- this->assign( container_detail::to_raw_pointer(x.members_.m_start)
- , container_detail::to_raw_pointer(x.members_.m_start + x.members_.m_size));
+ this->priv_copy_assign(boost::move(x), alloc_version());
}
return *this;
}
@@ -585,28 +841,29 @@
//iG BOOST_CONTAINER_NOEXCEPT_IF(!allocator_type::propagate_on_container_move_assignment::value || is_nothrow_move_assignable<allocator_type>::value);)
BOOST_CONTAINER_NOEXCEPT
{
- if (&x != this){
- allocator_type &this_alloc = this->alloc();
- allocator_type &x_alloc = x.alloc();
- //If allocators are equal we can just swap pointers
- if(this_alloc == x_alloc){
- //Destroy objects but retain memory in case x reuses it in the future
- this->clear();
- this->swap_members(x);
- //Move allocator if needed
- container_detail::bool_<allocator_traits_type::
- propagate_on_container_move_assignment::value> flag;
- container_detail::move_alloc(this_alloc, x_alloc, flag);
- }
- //If unequal allocators, then do a one by one move
- else{
- this->assign( boost::make_move_iterator(container_detail::to_raw_pointer(x.members_.m_start))
- , boost::make_move_iterator(container_detail::to_raw_pointer(x.members_.m_start + x.members_.m_size)));
- }
- }
+ this->priv_move_assign(boost::move(x), alloc_version());
return *this;
}
+ #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+
+ //! <b>Effects</b>: Move assignment. All mx's values are transferred to *this.
+ //!
+ //! <b>Postcondition</b>: x.empty(). *this contains a the elements x had
+ //! before the function.
+ //!
+ //! <b>Throws</b>: If move constructor/assignment of T throws or allocation throws
+ //!
+ //! <b>Complexity</b>: Linear.
+ template<class OtherAllocator, class OtherAllocatorVersion>
+ vector& operator=(BOOST_RV_REF_BEG vector<OtherAllocator, OtherAllocatorVersion> BOOST_RV_REF_END x)
+ {
+ this->priv_move_assign(boost::move(x), alloc_version());
+ return *this;
+ }
+
+ #endif
+
//! <b>Effects</b>: Assigns the the range [first, last) to *this.
//!
//! <b>Throws</b>: If memory allocation throws or T's copy/move constructor/assignment or
@@ -625,13 +882,16 @@
{
//Overwrite all elements we can from [first, last)
iterator cur = this->begin();
- for ( ; first != last && cur != end(); ++cur, ++first){
+ const iterator end_it = this->end();
+ for ( ; first != last && cur != end_it; ++cur, ++first){
*cur = *first;
}
if (first == last){
//There are no more elements in the sequence, erase remaining
- this->erase(cur, this->cend());
+ T* const end_pos = container_detail::to_raw_pointer(this->m_holder.start()) + this->m_holder.m_size;
+ size_type n = static_cast<size_type>(end_pos - container_detail::to_raw_pointer(vector_iterator_get_ptr(cur)));
+ this->priv_destroy_last_n(n);
}
else{
//There are more elements in the range, insert the remaining ones
@@ -654,8 +914,7 @@
//!
//! <b>Complexity</b>: Constant.
allocator_type get_allocator() const BOOST_CONTAINER_NOEXCEPT
- { return this->alloc(); }
-
+ { return this->m_holder.alloc(); }
//! <b>Effects</b>: Returns a reference to the internal allocator.
//!
@@ -665,7 +924,7 @@
//!
//! <b>Note</b>: Non-standard extension.
stored_allocator_type &get_stored_allocator() BOOST_CONTAINER_NOEXCEPT
- { return this->alloc(); }
+ { return this->m_holder.alloc(); }
//! <b>Effects</b>: Returns a reference to the internal allocator.
//!
@@ -675,7 +934,7 @@
//!
//! <b>Note</b>: Non-standard extension.
const stored_allocator_type &get_stored_allocator() const BOOST_CONTAINER_NOEXCEPT
- { return this->alloc(); }
+ { return this->m_holder.alloc(); }
//////////////////////////////////////////////
//
@@ -689,7 +948,7 @@
//!
//! <b>Complexity</b>: Constant.
iterator begin() BOOST_CONTAINER_NOEXCEPT
- { return iterator(this->members_.m_start); }
+ { return iterator(this->m_holder.start()); }
//! <b>Effects</b>: Returns a const_iterator to the first element contained in the vector.
//!
@@ -697,7 +956,7 @@
//!
//! <b>Complexity</b>: Constant.
const_iterator begin() const BOOST_CONTAINER_NOEXCEPT
- { return const_iterator(this->members_.m_start); }
+ { return const_iterator(this->m_holder.start()); }
//! <b>Effects</b>: Returns an iterator to the end of the vector.
//!
@@ -705,7 +964,7 @@
//!
//! <b>Complexity</b>: Constant.
iterator end() BOOST_CONTAINER_NOEXCEPT
- { return iterator(this->members_.m_start + this->members_.m_size); }
+ { return iterator(this->m_holder.start() + this->m_holder.m_size); }
//! <b>Effects</b>: Returns a const_iterator to the end of the vector.
//!
@@ -757,7 +1016,7 @@
//!
//! <b>Complexity</b>: Constant.
const_iterator cbegin() const BOOST_CONTAINER_NOEXCEPT
- { return const_iterator(this->members_.m_start); }
+ { return const_iterator(this->m_holder.start()); }
//! <b>Effects</b>: Returns a const_iterator to the end of the vector.
//!
@@ -765,7 +1024,7 @@
//!
//! <b>Complexity</b>: Constant.
const_iterator cend() const BOOST_CONTAINER_NOEXCEPT
- { return const_iterator(this->members_.m_start + this->members_.m_size); }
+ { return const_iterator(this->m_holder.start() + this->m_holder.m_size); }
//! <b>Effects</b>: Returns a const_reverse_iterator pointing to the beginning
//! of the reversed vector.
@@ -797,7 +1056,7 @@
//!
//! <b>Complexity</b>: Constant.
bool empty() const BOOST_CONTAINER_NOEXCEPT
- { return !this->members_.m_size; }
+ { return !this->m_holder.m_size; }
//! <b>Effects</b>: Returns the number of the elements contained in the vector.
//!
@@ -805,7 +1064,7 @@
//!
//! <b>Complexity</b>: Constant.
size_type size() const BOOST_CONTAINER_NOEXCEPT
- { return this->members_.m_size; }
+ { return this->m_holder.m_size; }
//! <b>Effects</b>: Returns the largest possible size of the vector.
//!
@@ -813,7 +1072,7 @@
//!
//! <b>Complexity</b>: Constant.
size_type max_size() const BOOST_CONTAINER_NOEXCEPT
- { return allocator_traits_type::max_size(this->alloc()); }
+ { return allocator_traits_type::max_size(this->m_holder.alloc()); }
//! <b>Effects</b>: Inserts or erases elements at the end such that
//! the size becomes n. New elements are default constructed.
@@ -823,15 +1082,15 @@
//! <b>Complexity</b>: Linear to the difference between size() and new_size.
void resize(size_type new_size)
{
- if (new_size < this->size()){
+ const size_type sz = this->size();
+ if (new_size < sz){
//Destroy last elements
- this->erase(const_iterator(this->members_.m_start + new_size), this->end());
+ this->priv_destroy_last_n(sz - new_size);
}
else{
const size_type n = new_size - this->size();
- this->reserve(new_size);
- container_detail::insert_default_constructed_n_proxy<Allocator, T*> proxy(this->alloc());
- this->priv_forward_range_insert(this->cend().get_ptr(), n, proxy);
+ container_detail::insert_default_constructed_n_proxy<Allocator, T*> proxy(this->m_holder.alloc());
+ this->priv_forward_range_insert_at_end(n, proxy, alloc_version());
}
}
@@ -843,14 +1102,15 @@
//! <b>Complexity</b>: Linear to the difference between size() and new_size.
void resize(size_type new_size, const T& x)
{
- pointer finish = this->members_.m_start + this->members_.m_size;
- if (new_size < size()){
+ const size_type sz = this->size();
+ if (new_size < sz){
//Destroy last elements
- this->erase(const_iterator(this->members_.m_start + new_size), this->end());
+ this->priv_destroy_last_n(sz - new_size);
}
else{
- //Insert new elements at the end
- this->insert(const_iterator(finish), new_size - this->size(), x);
+ const size_type n = new_size - this->size();
+ container_detail::insert_n_copies_proxy<Allocator, T*> proxy(this->m_holder.alloc(), x);
+ this->priv_forward_range_insert_at_end(n, proxy, alloc_version());
}
}
@@ -861,7 +1121,7 @@
//!
//! <b>Complexity</b>: Constant.
size_type capacity() const BOOST_CONTAINER_NOEXCEPT
- { return this->members_.m_capacity; }
+ { return this->m_holder.capacity(); }
//! <b>Effects</b>: If n is less than or equal to capacity(), this call has no
//! effect. Otherwise, it is a request for allocation of additional memory.
@@ -872,54 +1132,7 @@
void reserve(size_type new_cap)
{
if (this->capacity() < new_cap){
- //There is not enough memory, allocate a new
- //buffer or expand the old one.
- bool same_buffer_start;
- size_type real_cap = 0;
- std::pair<pointer, bool> ret =
- this->allocation_command
- (allocate_new | expand_fwd | expand_bwd,
- new_cap, new_cap, real_cap, this->members_.m_start);
-
- //Check for forward expansion
- same_buffer_start = ret.second && this->members_.m_start == ret.first;
- if(same_buffer_start){
- #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
- ++this->num_expand_fwd;
- #endif
- this->members_.m_capacity = real_cap;
- }
-
- //If there is no forward expansion, move objects
- else{
- //We will reuse insert code, so create a dummy input iterator
- container_detail::insert_range_proxy<Allocator, boost::move_iterator<T*>, T*>
- proxy(this->alloc(), ::boost::make_move_iterator((T *)0));
- //Backwards (and possibly forward) expansion
- if(alloc_version::value > 1 && ret.second){
- #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
- ++this->num_expand_bwd;
- #endif
- this->priv_range_insert_expand_backwards
- ( container_detail::to_raw_pointer(ret.first)
- , real_cap
- , container_detail::to_raw_pointer(this->members_.m_start)
- , 0
- , proxy);
- }
- //New buffer
- else{
- #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
- ++this->num_alloc;
- #endif
- this->priv_range_insert_new_allocation
- ( container_detail::to_raw_pointer(ret.first)
- , real_cap
- , container_detail::to_raw_pointer(this->members_.m_start)
- , 0
- , proxy);
- }
- }
+ this->priv_reserve(new_cap, alloc_version());
}
}
@@ -947,7 +1160,7 @@
//!
//! <b>Complexity</b>: Constant.
reference front() BOOST_CONTAINER_NOEXCEPT
- { return *this->members_.m_start; }
+ { return *this->m_holder.start(); }
//! <b>Requires</b>: !empty()
//!
@@ -958,7 +1171,7 @@
//!
//! <b>Complexity</b>: Constant.
const_reference front() const BOOST_CONTAINER_NOEXCEPT
- { return *this->members_.m_start; }
+ { return *this->m_holder.start(); }
//! <b>Requires</b>: !empty()
//!
@@ -969,7 +1182,7 @@
//!
//! <b>Complexity</b>: Constant.
reference back() BOOST_CONTAINER_NOEXCEPT
- { return this->members_.m_start[this->members_.m_size - 1]; }
+ { return this->m_holder.start()[this->m_holder.m_size - 1]; }
//! <b>Requires</b>: !empty()
//!
@@ -980,7 +1193,7 @@
//!
//! <b>Complexity</b>: Constant.
const_reference back() const BOOST_CONTAINER_NOEXCEPT
- { return this->members_.m_start[this->members_.m_size - 1]; }
+ { return this->m_holder.start()[this->m_holder.m_size - 1]; }
//! <b>Requires</b>: size() > n.
//!
@@ -991,7 +1204,7 @@
//!
//! <b>Complexity</b>: Constant.
reference operator[](size_type n) BOOST_CONTAINER_NOEXCEPT
- { return this->members_.m_start[n]; }
+ { return this->m_holder.start()[n]; }
//! <b>Requires</b>: size() > n.
//!
@@ -1002,7 +1215,7 @@
//!
//! <b>Complexity</b>: Constant.
const_reference operator[](size_type n) const BOOST_CONTAINER_NOEXCEPT
- { return this->members_.m_start[n]; }
+ { return this->m_holder.start()[n]; }
//! <b>Requires</b>: size() > n.
//!
@@ -1013,7 +1226,7 @@
//!
//! <b>Complexity</b>: Constant.
reference at(size_type n)
- { this->priv_check_range(n); return this->members_.m_start[n]; }
+ { this->priv_check_range(n); return this->m_holder.start()[n]; }
//! <b>Requires</b>: size() > n.
//!
@@ -1024,7 +1237,7 @@
//!
//! <b>Complexity</b>: Constant.
const_reference at(size_type n) const
- { this->priv_check_range(n); return this->members_.m_start[n]; }
+ { this->priv_check_range(n); return this->m_holder.start()[n]; }
//////////////////////////////////////////////
//
@@ -1039,7 +1252,7 @@
//!
//! <b>Complexity</b>: Constant.
T* data() BOOST_CONTAINER_NOEXCEPT
- { return container_detail::to_raw_pointer(this->members_.m_start); }
+ { return container_detail::to_raw_pointer(this->m_holder.start()); }
//! <b>Returns</b>: Allocator pointer such that [data(),data() + size()) is a valid range.
//! For a non-empty vector, data() == &front().
@@ -1048,7 +1261,7 @@
//!
//! <b>Complexity</b>: Constant.
const T * data() const BOOST_CONTAINER_NOEXCEPT
- { return container_detail::to_raw_pointer(this->members_.m_start); }
+ { return container_detail::to_raw_pointer(this->m_holder.start()); }
//////////////////////////////////////////////
//
@@ -1067,16 +1280,16 @@
template<class ...Args>
void emplace_back(Args &&...args)
{
- T* back_pos = container_detail::to_raw_pointer(this->members_.m_start) + this->members_.m_size;
- if (this->members_.m_size < this->members_.m_capacity){
+ T* back_pos = container_detail::to_raw_pointer(this->m_holder.start()) + this->m_holder.m_size;
+ if (this->m_holder.m_size < this->m_holder.capacity()){
//There is more memory, just construct a new object at the end
- allocator_traits_type::construct(this->alloc(), back_pos, ::boost::forward<Args>(args)...);
- ++this->members_.m_size;
+ allocator_traits_type::construct(this->m_holder.alloc(), back_pos, ::boost::forward<Args>(args)...);
+ ++this->m_holder.m_size;
}
else{
typedef container_detail::insert_emplace_proxy<Allocator, T*, Args...> type;
- this->priv_forward_range_insert
- (back_pos, 1, type(this->alloc(), ::boost::forward<Args>(args)...));
+ this->priv_forward_range_insert_no_capacity
+ (vector_iterator_get_ptr(this->cend()), 1, type(this->m_holder.alloc(), ::boost::forward<Args>(args)...), alloc_version());
}
}
@@ -1095,41 +1308,42 @@
{
//Just call more general insert(pos, size, value) and return iterator
typedef container_detail::insert_emplace_proxy<Allocator, T*, Args...> type;
- return this->priv_forward_range_insert
- (position.get_ptr(), 1, type(this->alloc(), ::boost::forward<Args>(args)...));
+ return this->priv_forward_range_insert( vector_iterator_get_ptr(position), 1, type(this->m_holder.alloc()
+ , ::boost::forward<Args>(args)...), alloc_version());
}
#else
- #define BOOST_PP_LOCAL_MACRO(n) \
- BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, >) \
- void emplace_back(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \
- { \
- T* back_pos = container_detail::to_raw_pointer \
- (this->members_.m_start) + this->members_.m_size; \
- if (this->members_.m_size < this->members_.m_capacity){ \
- allocator_traits_type::construct (this->alloc() \
- , back_pos BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _) ); \
- ++this->members_.m_size; \
- } \
- else{ \
- container_detail::BOOST_PP_CAT(insert_emplace_proxy_arg, n) \
- <Allocator, T* BOOST_PP_ENUM_TRAILING_PARAMS(n, P)> proxy \
- (this->alloc() BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _)); \
- this->priv_forward_range_insert(back_pos, 1, proxy); \
- } \
- } \
- \
- BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, >) \
- iterator emplace(const_iterator pos \
- BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \
- { \
- container_detail::BOOST_PP_CAT(insert_emplace_proxy_arg, n) \
- <Allocator, T* BOOST_PP_ENUM_TRAILING_PARAMS(n, P)> proxy \
- (this->alloc() BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _)); \
- return this->priv_forward_range_insert \
- (container_detail::to_raw_pointer(pos.get_ptr()), 1, proxy); \
- } \
+ #define BOOST_PP_LOCAL_MACRO(n) \
+ BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, >) \
+ void emplace_back(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \
+ { \
+ T* back_pos = container_detail::to_raw_pointer \
+ (this->m_holder.start()) + this->m_holder.m_size; \
+ if (this->m_holder.m_size < this->m_holder.capacity()){ \
+ allocator_traits_type::construct (this->m_holder.alloc() \
+ , back_pos BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _) ); \
+ ++this->m_holder.m_size; \
+ } \
+ else{ \
+ container_detail::BOOST_PP_CAT(insert_emplace_proxy_arg, n) \
+ <Allocator, T* BOOST_PP_ENUM_TRAILING_PARAMS(n, P)> proxy \
+ (this->m_holder.alloc() BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _)); \
+ this->priv_forward_range_insert_no_capacity \
+ (vector_iterator_get_ptr(this->cend()), 1, proxy, alloc_version()); \
+ } \
+ } \
+ \
+ BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, >) \
+ iterator emplace(const_iterator pos \
+ BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \
+ { \
+ container_detail::BOOST_PP_CAT(insert_emplace_proxy_arg, n) \
+ <Allocator, T* BOOST_PP_ENUM_TRAILING_PARAMS(n, P)> proxy \
+ (this->m_holder.alloc() BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _)); \
+ return this->priv_forward_range_insert \
+ (container_detail::to_raw_pointer(vector_iterator_get_ptr(pos)), 1, proxy, alloc_version()); \
+ } \
//!
#define BOOST_PP_LOCAL_LIMITS (0, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS)
#include BOOST_PP_LOCAL_ITERATE()
@@ -1192,8 +1406,8 @@
//! <b>Complexity</b>: Linear to n.
iterator insert(const_iterator p, size_type n, const T& x)
{
- container_detail::insert_n_copies_proxy<Allocator, T*> proxy(this->alloc(), x);
- return this->priv_forward_range_insert(p.get_ptr(), n, proxy);
+ container_detail::insert_n_copies_proxy<Allocator, T*> proxy(this->m_holder.alloc(), x);
+ return this->priv_forward_range_insert(vector_iterator_get_ptr(p), n, proxy, alloc_version());
}
//! <b>Requires</b>: p must be a valid iterator of *this.
@@ -1217,12 +1431,12 @@
)
{
const size_type n_pos = pos - this->cbegin();
- iterator it(pos.get_ptr());
+ iterator it(vector_iterator_get_ptr(pos));
for(;first != last; ++first){
it = this->emplace(it, *first);
++it;
}
- return iterator(this->members_.m_start + n_pos);
+ return iterator(this->m_holder.start() + n_pos);
}
#if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
@@ -1234,8 +1448,8 @@
>::type * = 0
)
{
- container_detail::insert_range_proxy<Allocator, FwdIt, T*> proxy(this->alloc(), first);
- return this->priv_forward_range_insert(pos.get_ptr(), std::distance(first, last), proxy);
+ container_detail::insert_range_proxy<Allocator, FwdIt, T*> proxy(this->m_holder.alloc(), first);
+ return this->priv_forward_range_insert(vector_iterator_get_ptr(pos), std::distance(first, last), proxy, alloc_version());
}
#endif
@@ -1247,8 +1461,8 @@
void pop_back() BOOST_CONTAINER_NOEXCEPT
{
//Destroy last element
- --this->members_.m_size;
- this->destroy(container_detail::to_raw_pointer(this->members_.m_start) + this->members_.m_size);
+ --this->m_holder.m_size;
+ this->priv_destroy(container_detail::to_raw_pointer(this->m_holder.start()) + this->m_holder.m_size);
}
//! <b>Effects</b>: Erases the element at position pos.
@@ -1259,13 +1473,12 @@
//! last element. Constant if pos is the last element.
iterator erase(const_iterator position)
{
- T *const pos = container_detail::to_raw_pointer(position.get_ptr());
- T *const beg = container_detail::to_raw_pointer(this->members_.m_start);
- ::boost::move(pos + 1, beg + this->members_.m_size, pos);
- --this->members_.m_size;
- //Destroy last element
- base_t::destroy(container_detail::to_raw_pointer(this->members_.m_start) + this->members_.m_size);
- return iterator(position.get_ptr());
+ T *const pos = container_detail::to_raw_pointer(vector_iterator_get_ptr(position));
+ T *const beg = container_detail::to_raw_pointer(this->m_holder.start());
+ //Move elements forward and destroy last
+ this->priv_destroy(::boost::move(pos + 1, beg + this->m_holder.m_size, pos));
+ --this->m_holder.m_size;
+ return iterator(vector_iterator_get_ptr(position));
}
//! <b>Effects</b>: Erases the elements pointed by [first, last).
@@ -1277,17 +1490,17 @@
iterator erase(const_iterator first, const_iterator last)
{
if (first != last){
- T* end_pos = container_detail::to_raw_pointer(this->members_.m_start) + this->members_.m_size;
- T* ptr = container_detail::to_raw_pointer(boost::move
- (container_detail::to_raw_pointer(last.get_ptr())
+ T* const end_pos = container_detail::to_raw_pointer(this->m_holder.start()) + this->m_holder.m_size;
+ T* const ptr = container_detail::to_raw_pointer(boost::move
+ (container_detail::to_raw_pointer(vector_iterator_get_ptr(last))
,end_pos
- ,container_detail::to_raw_pointer(first.get_ptr())
+ ,container_detail::to_raw_pointer(vector_iterator_get_ptr(first))
));
const size_type destroyed = (end_pos - ptr);
- this->destroy_n(ptr, destroyed);
- this->members_.m_size -= destroyed;
+ boost::container::destroy_alloc_n(this->get_stored_allocator(), ptr, destroyed);
+ this->m_holder.m_size -= destroyed;
}
- return iterator(first.get_ptr());
+ return iterator(vector_iterator_get_ptr(first));
}
//! <b>Effects</b>: Swaps the contents of *this and x.
@@ -1295,22 +1508,39 @@
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
- void swap(vector& x)
+ void swap(vector& x) BOOST_CONTAINER_NOEXCEPT_IF((!container_detail::is_same<alloc_version, allocator_v0>::value))
{
- //Just swap internals
- this->swap_members(x);
+ //Just swap internals in case of !allocator_v0. Otherwise, deep swap
+ this->m_holder.swap(x.m_holder);
//And now the allocator
container_detail::bool_<allocator_traits_type::propagate_on_container_swap::value> flag;
- container_detail::swap_alloc(this->alloc(), x.alloc(), flag);
+ container_detail::swap_alloc(this->m_holder.alloc(), x.m_holder.alloc(), flag);
+ }
+
+ #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+
+ //! <b>Effects</b>: Swaps the contents of *this and x.
+ //!
+ //! <b>Throws</b>: If T's move constructor throws.
+ //!
+ //! <b>Complexity</b>: Linear
+ //!
+ //! <b>Note</b>: non-standard extension.
+ template<class OtherAllocator>
+ void swap(vector<T, OtherAllocator> & x)
+ {
+ this->m_holder.swap(x.m_holder);
}
+ #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+
//! <b>Effects</b>: Erases all the elements of the vector.
//!
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Linear to the number of elements in the vector.
void clear() BOOST_CONTAINER_NOEXCEPT
- { this->prot_destroy_all(); }
+ { this->priv_destroy_all(); }
/// @cond
@@ -1330,75 +1560,301 @@
}
private:
+
+ template<class OtherAllocator, class AllocVersion>
+ void priv_move_assign(BOOST_RV_REF_BEG vector<T, OtherAllocator> BOOST_RV_REF_END x
+ , AllocVersion
+ , typename container_detail::enable_if_c
+ < container_detail::is_same<AllocVersion, allocator_v0>::value &&
+ !container_detail::is_same<OtherAllocator, allocator_type>::value
+ >::type * = 0)
+ {
+ if(this->capacity() < x.size()){
+ throw_bad_alloc();
+ }
+ this->priv_move_assign_impl(boost::move(x), AllocVersion());
+ }
+
+ template<class OtherAllocator, class AllocVersion>
+ void priv_move_assign(BOOST_RV_REF_BEG vector<T, OtherAllocator> BOOST_RV_REF_END x
+ , AllocVersion
+ , typename container_detail::enable_if_c
+ < !container_detail::is_same<AllocVersion, allocator_v0>::value ||
+ container_detail::is_same<OtherAllocator, allocator_type>::value
+ >::type * = 0)
+ {
+ this->priv_move_assign_impl(boost::move(x), AllocVersion());
+ }
+
+ template<class OtherAllocator, class AllocVersion>
+ void priv_move_assign_impl(BOOST_RV_REF_BEG vector<T, OtherAllocator> BOOST_RV_REF_END x
+ , AllocVersion
+ , typename container_detail::enable_if_c
+ < container_detail::is_same<AllocVersion, allocator_v0>::value
+ >::type * = 0)
+ {
+ T* const this_start = container_detail::to_raw_pointer(m_holder.start());
+ T* const other_start = container_detail::to_raw_pointer(x.m_holder.start());
+ const size_type this_sz = m_holder.m_size;
+ const size_type other_sz = static_cast<size_type>(x.m_holder.m_size);
+ boost::container::move_assign_range_alloc_n(this->m_holder.alloc(), other_start, other_sz, this_start, this_sz);
+ this->m_holder.m_size = other_sz;
+ }
+
+ template<class OtherAllocator, class AllocVersion>
+ void priv_move_assign_impl(BOOST_RV_REF_BEG vector<T, OtherAllocator> BOOST_RV_REF_END x
+ , AllocVersion
+ , typename container_detail::enable_if_c
+ < !container_detail::is_same<AllocVersion, allocator_v0>::value
+ >::type * = 0)
+ {
+ //for move constructor, no aliasing (&x != this) is assummed.
+ allocator_type &this_alloc = this->m_holder.alloc();
+ allocator_type &x_alloc = x.m_holder.alloc();
+ //If allocators are equal we can just swap pointers
+ if(this_alloc == x_alloc){
+ //Destroy objects but retain memory in case x reuses it in the future
+ this->clear();
+ this->m_holder.swap(x.m_holder);
+ //Move allocator if needed
+ container_detail::bool_<allocator_traits_type::
+ propagate_on_container_move_assignment::value> flag;
+ container_detail::move_alloc(this_alloc, x_alloc, flag);
+ }
+ //If unequal allocators, then do a one by one move
+ else{
+ //TO-DO: optimize this
+ this->assign( boost::make_move_iterator(container_detail::to_raw_pointer(x.m_holder.start()))
+ , boost::make_move_iterator(container_detail::to_raw_pointer(x.m_holder.start() + x.m_holder.m_size)));
+ }
+ }
+
+ template<class AllocVersion>
+ void priv_copy_assign(const vector &x, AllocVersion
+ , typename container_detail::enable_if_c
+ < container_detail::is_same<AllocVersion, allocator_v0>::value
+ >::type * = 0)
+ {
+ T* const this_start = container_detail::to_raw_pointer(m_holder.start());
+ T* const other_start = container_detail::to_raw_pointer(x.m_holder.start());
+ const size_type this_sz = m_holder.m_size;
+ const size_type other_sz = static_cast<size_type>(x.m_holder.m_size);
+ boost::container::copy_assign_range_alloc_n(this->m_holder.alloc(), other_start, other_sz, this_start, this_sz);
+ this->m_holder.m_size = other_sz;
+ }
+
+ template<class AllocVersion>
+ void priv_copy_assign(const vector &x, AllocVersion
+ , typename container_detail::enable_if_c
+ < !container_detail::is_same<AllocVersion, allocator_v0>::value
+ >::type * = 0)
+ {
+ allocator_type &this_alloc = this->m_holder.alloc();
+ const allocator_type &x_alloc = x.m_holder.alloc();
+ container_detail::bool_<allocator_traits_type::
+ propagate_on_container_copy_assignment::value> flag;
+ if(flag && this_alloc != x_alloc){
+ this->clear();
+ this->shrink_to_fit();
+ }
+ container_detail::assign_alloc(this_alloc, x_alloc, flag);
+ this->assign( container_detail::to_raw_pointer(x.m_holder.start())
+ , container_detail::to_raw_pointer(x.m_holder.start() + x.m_holder.m_size));
+ }
+
+ void priv_reserve(size_type, allocator_v0)
+ {
+ throw_bad_alloc();
+ }
+
+ void priv_reserve(size_type new_cap, allocator_v1)
+ {
+ //There is not enough memory, allocate a new buffer
+ pointer p = this->m_holder.allocate(new_cap);
+ //Backwards (and possibly forward) expansion
+ #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
+ ++this->num_alloc;
+ #endif
+ T * const raw_beg = container_detail::to_raw_pointer(this->m_holder.start());
+ const size_type sz = m_holder.m_size;
+ ::boost::container::uninitialized_move_alloc_n_source
+ ( this->m_holder.alloc(), raw_beg, sz, container_detail::to_raw_pointer(p) );
+ boost::container::destroy_alloc_n(this->m_holder.alloc(), raw_beg, sz);
+ this->m_holder.start(p);
+ this->m_holder.capacity(new_cap);
+ }
+
+ void priv_reserve(size_type new_cap, allocator_v2)
+ {
+ //There is not enough memory, allocate a new
+ //buffer or expand the old one.
+ bool same_buffer_start;
+ size_type real_cap = 0;
+ std::pair<pointer, bool> ret =
+ this->m_holder.allocation_command
+ (allocate_new | expand_fwd | expand_bwd,
+ new_cap, new_cap, real_cap, this->m_holder.start());
+
+ //Check for forward expansion
+ same_buffer_start = ret.second && this->m_holder.start() == ret.first;
+ if(same_buffer_start){
+ #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
+ ++this->num_expand_fwd;
+ #endif
+ this->m_holder.capacity(real_cap);
+ }
+ //If there is no forward expansion, move objects
+ else{
+ //Backwards (and possibly forward) expansion
+ if(ret.second){
+ //We will reuse insert code, so create a dummy input iterator
+ container_detail::insert_range_proxy<Allocator, boost::move_iterator<T*>, T*>
+ proxy(this->m_holder.alloc(), ::boost::make_move_iterator((T *)0));
+ #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
+ ++this->num_expand_bwd;
+ #endif
+ this->priv_forward_range_insert_expand_backwards
+ ( container_detail::to_raw_pointer(ret.first)
+ , real_cap
+ , container_detail::to_raw_pointer(this->m_holder.start())
+ , 0
+ , proxy);
+ }
+ //New buffer
+ else{
+ //Backwards (and possibly forward) expansion
+ #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
+ ++this->num_alloc;
+ #endif
+ T * const raw_beg = container_detail::to_raw_pointer(this->m_holder.start());
+ const size_type sz = m_holder.m_size;
+ ::boost::container::uninitialized_move_alloc_n_source
+ ( this->m_holder.alloc(), raw_beg, sz, container_detail::to_raw_pointer(ret.first) );
+ boost::container::destroy_alloc_n(this->m_holder.alloc(), raw_beg, sz);
+ this->m_holder.start(ret.first);
+ this->m_holder.capacity(real_cap);
+ }
+ }
+ }
+
+ template<class Proxy>
+ void priv_uninitialized_fill(Proxy proxy, size_type n) const
+ {
+ //Copy first new elements in pos
+ proxy.uninitialized_copy_n_and_update
+ (container_detail::to_raw_pointer(this->m_holder.start()), n);
+ //m_holder.size was already initialized to n in vector_alloc_holder's constructor
+ }
+
+ void priv_destroy(value_type* p) BOOST_CONTAINER_NOEXCEPT
+ {
+ if(!value_traits::trivial_dctr)
+ allocator_traits_type::destroy(this->get_stored_allocator(), p);
+ }
+
+ void priv_destroy_last_n(size_type n) BOOST_CONTAINER_NOEXCEPT
+ {
+ T* const end_pos = container_detail::to_raw_pointer(this->m_holder.start()) + this->m_holder.m_size;
+ boost::container::destroy_alloc_n(this->get_stored_allocator(), end_pos-n, n);
+ this->m_holder.m_size -= n;
+ }
+
+ void priv_destroy_all() BOOST_CONTAINER_NOEXCEPT
+ {
+ boost::container::destroy_alloc_n
+ (this->get_stored_allocator(), container_detail::to_raw_pointer(this->m_holder.start()), this->m_holder.m_size);
+ this->m_holder.m_size = 0;
+ }
+
template<class U>
iterator priv_insert(const const_iterator &p, BOOST_FWD_REF(U) x)
{
return this->priv_forward_range_insert
- (p.get_ptr(), 1, container_detail::get_insert_value_proxy<T*>(this->alloc(), ::boost::forward<U>(x)));
+ ( vector_iterator_get_ptr(p), 1, container_detail::get_insert_value_proxy<T*>(this->m_holder.alloc()
+ , ::boost::forward<U>(x)), alloc_version());
+ }
+
+ void priv_push_back(const T &x)
+ {
+ if (this->m_holder.m_size < this->m_holder.capacity()){
+ //There is more memory, just construct a new object at the end
+ allocator_traits_type::construct
+ ( this->m_holder.alloc()
+ , container_detail::to_raw_pointer(this->m_holder.start() + this->m_holder.m_size)
+ , x );
+ ++this->m_holder.m_size;
+ }
+ else{
+ container_detail::insert_copy_proxy<Allocator, T*> proxy(this->m_holder.alloc(), x);
+ this->priv_forward_range_insert_no_capacity(vector_iterator_get_ptr(this->cend()), 1, proxy, alloc_version());
+ }
}
- template <class U>
- void priv_push_back(BOOST_FWD_REF(U) x)
+ void priv_push_back(BOOST_RV_REF(T) x)
{
- if (this->members_.m_size < this->members_.m_capacity){
+ if (this->m_holder.m_size < this->m_holder.capacity()){
//There is more memory, just construct a new object at the end
allocator_traits_type::construct
- ( this->alloc()
- , container_detail::to_raw_pointer(this->members_.m_start + this->members_.m_size)
- , ::boost::forward<U>(x) );
- ++this->members_.m_size;
+ ( this->m_holder.alloc()
+ , container_detail::to_raw_pointer(this->m_holder.start() + this->m_holder.m_size)
+ , ::boost::move(x) );
+ ++this->m_holder.m_size;
}
else{
- this->priv_insert(this->cend(), ::boost::forward<U>(x));
+ container_detail::insert_move_proxy<Allocator, T*> proxy(this->m_holder.alloc(), x);
+ this->priv_forward_range_insert_no_capacity(vector_iterator_get_ptr(this->cend()), 1, proxy, alloc_version());
}
}
+ void priv_shrink_to_fit(allocator_v0) BOOST_CONTAINER_NOEXCEPT
+ {}
+
void priv_shrink_to_fit(allocator_v1)
{
- if(this->members_.m_capacity){
- if(!this->size()){
- this->prot_deallocate();
+ const size_type cp = this->m_holder.capacity();
+ if(cp){
+ const size_type sz = this->size();
+ if(!sz){
+ this->m_holder.alloc().deallocate(this->m_holder.m_start, cp);
+ this->m_holder.m_start = pointer();
+ this->m_holder.m_capacity = 0;
}
- else{
+ else if(sz < cp){
//Allocate a new buffer.
- size_type real_cap = 0;
- std::pair<pointer, bool> ret =
- this->allocation_command
- (allocate_new, this->size(), this->size(), real_cap, this->members_.m_start);
- if(real_cap < this->capacity()){
- //We will reuse insert code, so create a dummy input iterator
- container_detail::insert_range_proxy<Allocator, boost::move_iterator<T*>, T*>
- proxy(this->alloc(), ::boost::make_move_iterator((T *)0));
- #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
- ++this->num_alloc;
- #endif
- this->priv_range_insert_new_allocation
- ( container_detail::to_raw_pointer(ret.first)
- , real_cap
- , container_detail::to_raw_pointer(this->members_.m_start)
- , 0
- , proxy);
- }
- else{
- this->alloc().deallocate(ret.first, real_cap);
- }
+ pointer p = this->m_holder.allocate(sz);
+
+ //We will reuse insert code, so create a dummy input iterator
+ container_detail::insert_range_proxy<Allocator, boost::move_iterator<T*>, T*>
+ proxy(this->m_holder.alloc(), ::boost::make_move_iterator((T *)0));
+ #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
+ ++this->num_alloc;
+ #endif
+ this->priv_forward_range_insert_new_allocation
+ ( container_detail::to_raw_pointer(p)
+ , sz
+ , container_detail::to_raw_pointer(this->m_holder.start())
+ , 0
+ , proxy);
}
}
}
- void priv_shrink_to_fit(allocator_v2)
+ void priv_shrink_to_fit(allocator_v2) BOOST_CONTAINER_NOEXCEPT
{
- if(this->members_.m_capacity){
- if(!size()){
- this->prot_deallocate();
+ const size_type cp = this->m_holder.capacity();
+ if(cp){
+ const size_type sz = this->size();
+ if(!sz){
+ this->m_holder.alloc().deallocate(this->m_holder.m_start, cp);
+ this->m_holder.m_start = pointer();
+ this->m_holder.m_capacity = 0;
}
else{
size_type received_size;
- if(this->allocation_command
+ if(this->m_holder.allocation_command
( shrink_in_place | nothrow_allocation
- , this->capacity(), this->size()
- , received_size, this->members_.m_start).first){
- this->members_.m_capacity = received_size;
+ , cp, sz, received_size, this->m_holder.start()).first){
+ this->m_holder.capacity(received_size);
#ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
++this->num_shrink;
#endif
@@ -1408,78 +1864,164 @@
}
template <class InsertionProxy>
- iterator priv_forward_range_insert
- (const pointer &pos, const size_type n, const InsertionProxy insert_range_proxy)
+ iterator priv_forward_range_insert_no_capacity
+ (const pointer &pos, const size_type, const InsertionProxy , allocator_v0)
+ {
+ throw_bad_alloc();
+ return iterator(pos);
+ }
+
+ template <class InsertionProxy>
+ iterator priv_forward_range_insert_no_capacity
+ (const pointer &pos, const size_type n, const InsertionProxy insert_range_proxy, allocator_v1)
{
//Check if we have enough memory or try to expand current memory
- const size_type remaining = this->members_.m_capacity - this->members_.m_size;
- const size_type n_pos = pos - this->members_.m_start;
+ const size_type n_pos = pos - this->m_holder.start();
T *const raw_pos = container_detail::to_raw_pointer(pos);
- //Check if we already have room
- if(alloc_version::value > 1){ //Version 2 allocator, compile time check
- bool same_buffer_start = n <= remaining;
- if (!same_buffer_start){
- size_type real_cap = 0;
- //There is not enough memory, allocate a new
- //buffer or expand the old one.
- std::pair<pointer, bool> ret = (this->allocation_command
- (allocate_new | expand_fwd | expand_bwd,
- this->members_.m_size + n, this->next_capacity(n), real_cap, this->members_.m_start));
-
- //Buffer reallocated
- if(ret.second){
- //Forward expansion, delay insertion
- if(this->members_.m_start == ret.first){
- #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
- ++this->num_expand_fwd;
- #endif
- this->members_.m_capacity = real_cap;
- //Expand forward
- this->priv_range_insert_expand_forward(raw_pos, n, insert_range_proxy);
- }
- //Backwards (and possibly forward) expansion
- else{
- #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
- ++this->num_expand_bwd;
- #endif
- this->priv_range_insert_expand_backwards
- ( container_detail::to_raw_pointer(ret.first)
- , real_cap, raw_pos, n, insert_range_proxy);
- }
- }
- //New buffer
- else{
- #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
- ++this->num_alloc;
- #endif
- this->priv_range_insert_new_allocation
- ( container_detail::to_raw_pointer(ret.first)
- , real_cap, raw_pos, n, insert_range_proxy);
- }
- }
- else{
+ const size_type new_cap = this->m_holder.next_capacity(n);
+ T * new_buf = container_detail::to_raw_pointer(this->m_holder.alloc().allocate(new_cap));
+ #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
+ ++this->num_alloc;
+ #endif
+ this->priv_forward_range_insert_new_allocation
+ ( new_buf, new_cap, raw_pos, n, insert_range_proxy);
+ return iterator(this->m_holder.start() + n_pos);
+ }
+
+
+ template <class InsertionProxy>
+ iterator priv_forward_range_insert_no_capacity
+ (const pointer &pos, const size_type n, const InsertionProxy insert_range_proxy, allocator_v2)
+ {
+ //Check if we have enough memory or try to expand current memory
+ T *const raw_pos = container_detail::to_raw_pointer(pos);
+ const size_type n_pos = raw_pos - container_detail::to_raw_pointer(this->m_holder.start());
+
+ size_type real_cap = 0;
+ //There is not enough memory, allocate a new
+ //buffer or expand the old one.
+ std::pair<pointer, bool> ret = (this->m_holder.allocation_command
+ (allocate_new | expand_fwd | expand_bwd,
+ this->m_holder.m_size + n, this->m_holder.next_capacity(n), real_cap, this->m_holder.start()));
+
+ //Buffer reallocated
+ if(ret.second){
+ //Forward expansion, delay insertion
+ if(this->m_holder.start() == ret.first){
+ #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
+ ++this->num_expand_fwd;
+ #endif
+ this->m_holder.capacity(real_cap);
//Expand forward
- this->priv_range_insert_expand_forward
- (raw_pos, n, insert_range_proxy);
- }
- }
- else{ //Version 1 allocator
- if (n <= remaining){
- this->priv_range_insert_expand_forward
- (raw_pos, n, insert_range_proxy);
+ this->priv_forward_range_insert_expand_forward(raw_pos, n, insert_range_proxy);
}
+ //Backwards (and possibly forward) expansion
else{
- const size_type new_cap = this->next_capacity(n);
- T * new_buf = container_detail::to_raw_pointer(this->alloc().allocate(new_cap));
#ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
- ++this->num_alloc;
+ ++this->num_expand_bwd;
#endif
- this->priv_range_insert_new_allocation
- ( new_buf, new_cap, raw_pos, n, insert_range_proxy);
+ this->priv_forward_range_insert_expand_backwards
+ ( container_detail::to_raw_pointer(ret.first)
+ , real_cap, raw_pos, n, insert_range_proxy);
}
}
- return iterator(this->members_.m_start + n_pos);
+ //New buffer
+ else{
+ #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
+ ++this->num_alloc;
+ #endif
+ this->priv_forward_range_insert_new_allocation
+ ( container_detail::to_raw_pointer(ret.first)
+ , real_cap, raw_pos, n, insert_range_proxy);
+ }
+
+ return iterator(this->m_holder.start() + n_pos);
+ }
+
+ template <class InsertionProxy>
+ iterator priv_forward_range_insert
+ (const pointer &pos, const size_type n, const InsertionProxy insert_range_proxy, allocator_v0)
+ {
+ //Check if we have enough memory or try to expand current memory
+ const size_type remaining = this->m_holder.capacity() - this->m_holder.m_size;
+
+ if (n > remaining){
+ //This will trigger an error
+ throw_bad_alloc();
+ }
+ const size_type n_pos = pos - this->m_holder.start();
+ T *const raw_pos = container_detail::to_raw_pointer(pos);
+ this->priv_forward_range_insert_expand_forward(raw_pos, n, insert_range_proxy);
+ return iterator(this->m_holder.start() + n_pos);
+ }
+
+ template <class InsertionProxy>
+ iterator priv_forward_range_insert
+ (const pointer &pos, const size_type n, const InsertionProxy insert_range_proxy, allocator_v1)
+ {
+ //Check if we have enough memory or try to expand current memory
+ const size_type remaining = this->m_holder.capacity() - this->m_holder.m_size;
+ T *const raw_pos = container_detail::to_raw_pointer(pos);
+
+ if (n <= remaining){
+ const size_type n_pos = raw_pos - container_detail::to_raw_pointer(this->m_holder.start());
+ this->priv_forward_range_insert_expand_forward
+ (raw_pos, n, insert_range_proxy);
+ return iterator(this->m_holder.start() + n_pos);
+ }
+ else{
+ return this->priv_forward_range_insert_no_capacity(pos, n, insert_range_proxy, alloc_version());
+ }
+ }
+
+ template <class InsertionProxy>
+ iterator priv_forward_range_insert
+ (const pointer &pos, const size_type n, const InsertionProxy insert_range_proxy, allocator_v2)
+ {
+ //Check if we have enough memory or try to expand current memory
+ const size_type remaining = this->m_holder.capacity() - this->m_holder.m_size;
+
+ bool same_buffer_start = n <= remaining;
+ if (!same_buffer_start){
+ return priv_forward_range_insert_no_capacity(pos, n, insert_range_proxy, alloc_version());
+ }
+ else{
+ //Expand forward
+ T *const raw_pos = container_detail::to_raw_pointer(pos);
+ const size_type n_pos = raw_pos - container_detail::to_raw_pointer(this->m_holder.start());
+ this->priv_forward_range_insert_expand_forward(raw_pos, n, insert_range_proxy);
+ return iterator(this->m_holder.start() + n_pos);
+ }
+ }
+
+ template <class InsertionProxy>
+ iterator priv_forward_range_insert_at_end
+ (const size_type n, const InsertionProxy insert_range_proxy, allocator_v0)
+ {
+ //Check if we have enough memory or try to expand current memory
+ const size_type remaining = this->m_holder.capacity() - this->m_holder.m_size;
+
+ if (n > remaining){
+ //This will trigger an error
+ throw_bad_alloc();
+ }
+ this->priv_forward_range_insert_at_end_expand_forward(n, insert_range_proxy);
+ return this->end();
+ }
+
+ template <class InsertionProxy>
+ iterator priv_forward_range_insert_at_end
+ (const size_type n, const InsertionProxy insert_range_proxy, allocator_v1)
+ {
+ return this->priv_forward_range_insert(vector_iterator_get_ptr(this->cend()), n, insert_range_proxy, allocator_v1());
+ }
+
+ template <class InsertionProxy>
+ iterator priv_forward_range_insert_at_end
+ (const size_type n, const InsertionProxy insert_range_proxy, allocator_v2)
+ {
+ return this->priv_forward_range_insert(vector_iterator_get_ptr(this->cend()), n, insert_range_proxy, allocator_v2());
}
//Absolutely experimental. This function might change, disappear or simply crash!
@@ -1489,7 +2031,7 @@
{
const size_type old_size_pos = this->size();
this->reserve(old_size_pos + element_count);
- T* const begin_ptr = container_detail::to_raw_pointer(this->members_.m_start);
+ T* const begin_ptr = container_detail::to_raw_pointer(this->m_holder.start());
size_type insertions_left = element_count;
size_type next_pos = old_size_pos;
size_type hole_size = element_count;
@@ -1497,7 +2039,7 @@
//Exception rollback. If any copy throws before the hole is filled, values
//already inserted/copied at the end of the buffer will be destroyed.
typename value_traits::ArrayDestructor past_hole_values_destroyer
- (begin_ptr + old_size_pos + element_count, this->alloc(), size_type(0u));
+ (begin_ptr + old_size_pos + element_count, this->m_holder.alloc(), size_type(0u));
//Loop for each insertion backwards, first moving the elements after the insertion point,
//then inserting the element.
while(insertions_left){
@@ -1518,12 +2060,12 @@
//The hole was reduced by priv_insert_ordered_at_shift_range so expand exception rollback range backwards
past_hole_values_destroyer.increment_size_backwards(next_pos - pos);
//Insert the new value in the hole
- allocator_traits_type::construct(this->alloc(), begin_ptr + pos + insertions_left - 1, *(--last_value_it));
+ allocator_traits_type::construct(this->m_holder.alloc(), begin_ptr + pos + insertions_left - 1, *(--last_value_it));
--new_hole_size;
if(new_hole_size == 0){
//Hole was just filled, disable exception rollback and change vector size
past_hole_values_destroyer.release();
- this->members_.m_size += element_count;
+ this->m_holder.m_size += element_count;
}
else{
//The hole was reduced by the new insertion by one
@@ -1534,7 +2076,7 @@
if(hole_size){
//Hole was just filled by priv_insert_ordered_at_shift_range, disable exception rollback and change vector size
past_hole_values_destroyer.release();
- this->members_.m_size += element_count;
+ this->m_holder.m_size += element_count;
}
//Insert the new value in the already constructed range
begin_ptr[pos + insertions_left - 1] = *(--last_value_it);
@@ -1602,7 +2144,7 @@
BOOST_ASSERT(first_pos <= last_pos);
BOOST_ASSERT(last_pos <= limit_pos);
//
- T* const begin_ptr = container_detail::to_raw_pointer(this->members_.m_start);
+ T* const begin_ptr = container_detail::to_raw_pointer(this->m_holder.start());
T* const first_ptr = begin_ptr + first_pos;
T* const last_ptr = begin_ptr + last_pos;
@@ -1615,7 +2157,8 @@
//Case B:
else if((first_pos + shift_count) >= limit_pos){
//All uninitialized_moved
- ::boost::container::uninitialized_move_alloc(this->alloc(), first_ptr, last_ptr, first_ptr + shift_count);
+ ::boost::container::uninitialized_move_alloc
+ (this->m_holder.alloc(), first_ptr, last_ptr, first_ptr + shift_count);
hole_size = last_pos + shift_count - limit_pos;
}
//Case C:
@@ -1623,7 +2166,7 @@
//Some uninitialized_moved
T* const limit_ptr = begin_ptr + limit_pos;
T* const boundary_ptr = limit_ptr - shift_count;
- ::boost::container::uninitialized_move_alloc(this->alloc(), boundary_ptr, last_ptr, limit_ptr);
+ ::boost::container::uninitialized_move_alloc(this->m_holder.alloc(), boundary_ptr, last_ptr, limit_ptr);
//The rest is move assigned
boost::move_backward(first_ptr, boundary_ptr, limit_ptr);
}
@@ -1632,25 +2175,32 @@
private:
template <class InsertionProxy>
- void priv_range_insert_expand_forward(T* const pos, const size_type n, InsertionProxy insert_range_proxy)
+ void priv_forward_range_insert_at_end_expand_forward(const size_type n, InsertionProxy insert_range_proxy)
+ {
+ T* const old_finish = container_detail::to_raw_pointer(this->m_holder.start()) + this->m_holder.m_size;
+ insert_range_proxy.uninitialized_copy_n_and_update(old_finish, n);
+ this->m_holder.m_size += n;
+ }
+
+ template <class InsertionProxy>
+ void priv_forward_range_insert_expand_forward(T* const pos, const size_type n, InsertionProxy insert_range_proxy)
{
//n can't be 0, because there is nothing to do in that case
if(!n) return;
//There is enough memory
- T* const old_finish = container_detail::to_raw_pointer(this->members_.m_start) + this->members_.m_size;
+ T* const old_finish = container_detail::to_raw_pointer(this->m_holder.start()) + this->m_holder.m_size;
const size_type elems_after = old_finish - pos;
if (!elems_after){
- //Copy first new elements in pos
- insert_range_proxy.uninitialized_copy_n_and_update(pos, n);
- this->members_.m_size += n;
+ insert_range_proxy.uninitialized_copy_n_and_update(old_finish, n);
+ this->m_holder.m_size += n;
}
else if (elems_after >= n){
//New elements can be just copied.
//Move to uninitialized memory last objects
::boost::container::uninitialized_move_alloc
- (this->alloc(), old_finish - n, old_finish, old_finish);
- this->members_.m_size += n;
+ (this->m_holder.alloc(), old_finish - n, old_finish, old_finish);
+ this->m_holder.m_size += n;
//Copy previous to last objects to the initialized end
boost::move_backward(pos, old_finish - n, old_finish);
//Insert new objects in the pos
@@ -1660,16 +2210,16 @@
//The new elements don't fit in the [pos, end()) range.
//Copy old [pos, end()) elements to the uninitialized memory (a gap is created)
- ::boost::container::uninitialized_move_alloc(this->alloc(), pos, old_finish, pos + n);
+ ::boost::container::uninitialized_move_alloc(this->m_holder.alloc(), pos, old_finish, pos + n);
BOOST_TRY{
//Copy first new elements in pos (gap is still there)
insert_range_proxy.copy_n_and_update(pos, elems_after);
//Copy to the beginning of the unallocated zone the last new elements (the gap is closed).
insert_range_proxy.uninitialized_copy_n_and_update(old_finish, n - elems_after);
- this->members_.m_size += n;
+ this->m_holder.m_size += n;
}
BOOST_CATCH(...){
- this->destroy_n(pos + n, elems_after);
+ boost::container::destroy_alloc_n(this->get_stored_allocator(), pos + n, elems_after);
BOOST_RETHROW
}
BOOST_CATCH_END
@@ -1677,22 +2227,22 @@
}
template <class InsertionProxy>
- void priv_range_insert_new_allocation
+ void priv_forward_range_insert_new_allocation
(T* const new_start, size_type new_cap, T* const pos, const size_type n, InsertionProxy insert_range_proxy)
{
//n can be zero, if we want to reallocate!
T *new_finish = new_start;
T *old_finish;
//Anti-exception rollbacks
- typename value_traits::ArrayDeallocator scoped_alloc(new_start, this->alloc(), new_cap);
- typename value_traits::ArrayDestructor constructed_values_destroyer(new_start, this->alloc(), 0u);
+ typename value_traits::ArrayDeallocator scoped_alloc(new_start, this->m_holder.alloc(), new_cap);
+ typename value_traits::ArrayDestructor constructed_values_destroyer(new_start, this->m_holder.alloc(), 0u);
//Initialize with [begin(), pos) old buffer
//the start of the new buffer
- T *old_buffer = container_detail::to_raw_pointer(this->members_.m_start);
+ T *old_buffer = container_detail::to_raw_pointer(this->m_holder.start());
if(old_buffer){
new_finish = ::boost::container::uninitialized_move_alloc
- (this->alloc(), container_detail::to_raw_pointer(this->members_.m_start), pos, old_finish = new_finish);
+ (this->m_holder.alloc(), container_detail::to_raw_pointer(this->m_holder.start()), pos, old_finish = new_finish);
constructed_values_destroyer.increment_size(new_finish - old_finish);
}
//Initialize new objects, starting from previous point
@@ -1703,31 +2253,31 @@
//starting from previous point
if(old_buffer){
new_finish = ::boost::container::uninitialized_move_alloc
- (this->alloc(), pos, old_buffer + this->members_.m_size, new_finish);
+ (this->m_holder.alloc(), pos, old_buffer + this->m_holder.m_size, new_finish);
//Destroy and deallocate old elements
//If there is allocated memory, destroy and deallocate
if(!value_traits::trivial_dctr_after_move)
- this->destroy_n(old_buffer, this->members_.m_size);
- this->alloc().deallocate(this->members_.m_start, this->members_.m_capacity);
+ boost::container::destroy_alloc_n(this->get_stored_allocator(), old_buffer, this->m_holder.m_size);
+ this->m_holder.alloc().deallocate(this->m_holder.start(), this->m_holder.capacity());
}
- this->members_.m_start = new_start;
- this->members_.m_size = new_finish - new_start;
- this->members_.m_capacity = new_cap;
+ this->m_holder.start(new_start);
+ this->m_holder.m_size = new_finish - new_start;
+ this->m_holder.capacity(new_cap);
//All construction successful, disable rollbacks
constructed_values_destroyer.release();
scoped_alloc.release();
}
template <class InsertionProxy>
- void priv_range_insert_expand_backwards
+ void priv_forward_range_insert_expand_backwards
(T* const new_start, const size_type new_capacity,
T* const pos, const size_type n, InsertionProxy insert_range_proxy)
{
//n can be zero to just expand capacity
//Backup old data
- T* const old_start = container_detail::to_raw_pointer(this->members_.m_start);
- T* const old_finish = old_start + this->members_.m_size;
- const size_type old_size = this->members_.m_size;
+ T* const old_start = container_detail::to_raw_pointer(this->m_holder.start());
+ T* const old_finish = old_start + this->m_holder.m_size;
+ const size_type old_size = this->m_holder.m_size;
//We can have 8 possibilities:
const size_type elemsbefore = static_cast<size_type>(pos - old_start);
@@ -1735,20 +2285,20 @@
const size_type before_plus_new = elemsbefore + n;
//Update the vector buffer information to a safe state
- this->members_.m_start = new_start;
- this->members_.m_capacity = new_capacity;
- this->members_.m_size = 0;
+ this->m_holder.start(new_start);
+ this->m_holder.capacity(new_capacity);
+ this->m_holder.m_size = 0;
//If anything goes wrong, this object will destroy
//all the old objects to fulfill previous vector state
- typename value_traits::OldArrayDestructor old_values_destroyer(old_start, this->alloc(), old_size);
+ typename value_traits::OldArrayDestructor old_values_destroyer(old_start, this->m_holder.alloc(), old_size);
//Check if s_before is big enough to hold the beginning of old data + new data
if(s_before >= before_plus_new){
//Copy first old values before pos, after that the new objects
- T *const new_elem_pos = ::boost::container::uninitialized_move_alloc(this->alloc(), old_start, pos, new_start);
- this->members_.m_size = elemsbefore;
+ T *const new_elem_pos = ::boost::container::uninitialized_move_alloc(this->m_holder.alloc(), old_start, pos, new_start);
+ this->m_holder.m_size = elemsbefore;
insert_range_proxy.uninitialized_copy_n_and_update(new_elem_pos, n);
- this->members_.m_size += n;
+ this->m_holder.m_size += n;
//Check if s_before is so big that even copying the old data + new data
//there is a gap between the new data and the old data
const size_type new_size = old_size + n;
@@ -1765,9 +2315,9 @@
//
//Now initialize the rest of memory with the last old values
::boost::container::uninitialized_move_alloc
- (this->alloc(), pos, old_finish, new_start + before_plus_new);
+ (this->m_holder.alloc(), pos, old_finish, new_start + before_plus_new);
//All new elements correctly constructed, avoid new element destruction
- this->members_.m_size = new_size;
+ this->m_holder.m_size = new_size;
//Old values destroyed automatically with "old_values_destroyer"
//when "old_values_destroyer" goes out of scope unless the have trivial
//destructor after move.
@@ -1792,9 +2342,9 @@
//Now initialize the rest of s_before memory with the
//first of elements after new values
::boost::container::uninitialized_move_alloc_n
- (this->alloc(), pos, raw_gap, new_start + before_plus_new);
+ (this->m_holder.alloc(), pos, raw_gap, new_start + before_plus_new);
//Update size since we have a contiguous buffer
- this->members_.m_size = old_size + s_before;
+ this->m_holder.m_size = old_size + s_before;
//All new elements correctly constructed, avoid old element destruction
old_values_destroyer.release();
//Now copy remaining last objects in the old buffer begin
@@ -1803,8 +2353,8 @@
//they have trivial destructor after move
size_type n_destroy = old_finish - to_destroy;
if(!value_traits::trivial_dctr_after_move)
- this->destroy_n(to_destroy, n_destroy);
- this->members_.m_size -= n_destroy;
+ boost::container::destroy_alloc_n(this->get_stored_allocator(), to_destroy, n_destroy);
+ this->m_holder.m_size -= n_destroy;
}
}
else{
@@ -1857,11 +2407,11 @@
//
//Copy the first part of old_begin to raw_mem
::boost::container::uninitialized_move_alloc_n
- (this->alloc(), old_start, s_before, new_start);
+ (this->m_holder.alloc(), old_start, s_before, new_start);
//The buffer is all constructed until old_end,
//release destroyer and update size
old_values_destroyer.release();
- this->members_.m_size = old_size + s_before;
+ this->m_holder.m_size = old_size + s_before;
//Now copy the second part of old_begin overwriting itself
T *const next = ::boost::move(old_start + s_before, pos, old_start);
if(do_after){
@@ -1877,8 +2427,8 @@
//they have trivial destructor after being moved
const size_type n_destroy = s_before - n;
if(!value_traits::trivial_dctr_after_move)
- this->destroy_n(move_end, n_destroy);
- this->members_.m_size -= n_destroy;
+ boost::container::destroy_alloc_n(this->get_stored_allocator(), move_end, n_destroy);
+ this->m_holder.m_size -= n_destroy;
}
}
else {
@@ -1909,13 +2459,13 @@
//
//First copy whole old_begin and part of new to raw_mem
T * const new_pos = ::boost::container::uninitialized_move_alloc
- (this->alloc(), old_start, pos, new_start);
- this->members_.m_size = elemsbefore;
+ (this->m_holder.alloc(), old_start, pos, new_start);
+ this->m_holder.m_size = elemsbefore;
const size_type mid_n = s_before - elemsbefore;
insert_range_proxy.uninitialized_copy_n_and_update(new_pos, mid_n);
//The buffer is all constructed until old_end,
//release destroyer
- this->members_.m_size = old_size + s_before;
+ this->m_holder.m_size = old_size + s_before;
old_values_destroyer.release();
if(do_after){
@@ -1933,8 +2483,8 @@
//have trivial destructor after being moved
size_type n_destroy = s_before - n;
if(!value_traits::trivial_dctr_after_move)
- this->destroy_n(move_end, n_destroy);
- this->members_.m_size -= n_destroy;
+ boost::container::destroy_alloc_n(this->get_stored_allocator(), move_end, n_destroy);
+ this->m_holder.m_size -= n_destroy;
}
}
@@ -1977,8 +2527,8 @@
//First copy the part of old_end raw_mem
T* finish_n = old_finish - n_after;
::boost::container::uninitialized_move_alloc
- (this->alloc(), finish_n, old_finish, old_finish);
- this->members_.m_size += n_after;
+ (this->m_holder.alloc(), finish_n, old_finish, old_finish);
+ this->m_holder.m_size += n_after;
//Displace the rest of old_end to the new position
boost::move_backward(pos, finish_n, old_finish);
//Now overwrite with new_end
@@ -2004,17 +2554,17 @@
//Copy to the old_end part to the uninitialized zone leaving a gap.
::boost::container::uninitialized_move_alloc
- (this->alloc(), pos, old_finish, old_finish + mid_last_dist);
+ (this->m_holder.alloc(), pos, old_finish, old_finish + mid_last_dist);
BOOST_TRY{
//Copy the first part to the already constructed old_end zone
insert_range_proxy.copy_n_and_update(pos, elemsafter);
//Copy the rest to the uninitialized zone filling the gap
insert_range_proxy.uninitialized_copy_n_and_update(old_finish, mid_last_dist);
- this->members_.m_size += n_after;
+ this->m_holder.m_size += n_after;
}
BOOST_CATCH(...){
- this->destroy_n(pos, mid_last_dist);
+ boost::container::destroy_alloc_n(this->get_stored_allocator(), pos, mid_last_dist);
BOOST_RETHROW
}
BOOST_CATCH_END
@@ -2024,10 +2574,10 @@
//The new_end part is [first + (n - n_after), last)
insert_range_proxy.uninitialized_copy_last_and_update(old_finish, elemsafter);
- this->members_.m_size += mid_last_dist;
+ this->m_holder.m_size += mid_last_dist;
::boost::container::uninitialized_move_alloc
- (this->alloc(), pos, old_finish, old_finish + mid_last_dist);
- this->members_.m_size += n_after - mid_last_dist;
+ (this->m_holder.alloc(), pos, old_finish, old_finish + mid_last_dist);
+ this->m_holder.m_size += n_after - mid_last_dist;
//Now copy the part of new_end over constructed elements
insert_range_proxy.copy_remaining_to(pos);*/
}
@@ -2038,8 +2588,9 @@
void priv_check_range(size_type n) const
{
//If n is out of range, throw an out_of_range exception
- if (n >= this->size())
- throw std::out_of_range("vector::at");
+ if (n >= this->size()){
+ throw_out_of_range("vector::at out of range");
+ }
}
#ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
@@ -2098,6 +2649,20 @@
}
+//#define BOOST_CONTAINER_PUT_SWAP_OVERLOAD_IN_NAMESPACE_STD
+
+#ifdef BOOST_CONTAINER_PUT_SWAP_OVERLOAD_IN_NAMESPACE_STD
+
+namespace std {
+
+template <class T, class Allocator>
+inline void swap(boost::container::vector<T, Allocator>& x, boost::container::vector<T, Allocator>& y)
+{ x.swap(y); }
+
+} //namespace std {
+
+#endif
+
/// @endcond
#include <boost/container/detail/config_end.hpp>
Modified: branches/release/boost/interprocess/detail/os_file_functions.hpp
==============================================================================
--- branches/release/boost/interprocess/detail/os_file_functions.hpp (original)
+++ branches/release/boost/interprocess/detail/os_file_functions.hpp 2013-05-18 06:40:55 EDT (Sat, 18 May 2013)
@@ -19,6 +19,7 @@
#include <string>
#include <limits>
#include <climits>
+#include <boost/type_traits/make_unsigned.hpp>
#if (defined BOOST_INTERPROCESS_WINDOWS)
# include <boost/interprocess/detail/win32_api.hpp>
@@ -66,6 +67,9 @@
, file_current = winapi::file_current
} file_pos_t;
+typedef unsigned long map_options_t;
+static const map_options_t default_map_options = map_options_t(-1);
+
namespace ipcdetail{
inline mapping_handle_t mapping_handle_from_file_handle(file_handle_t hnd)
@@ -129,10 +133,10 @@
if(!winapi::get_file_size(hnd, filesize))
return false;
- const offset_t max_filesize = (std::numeric_limits<offset_t>::max)();
+ typedef boost::make_unsigned<offset_t>::type uoffset_t;
+ const uoffset_t max_filesize = uoffset_t((std::numeric_limits<offset_t>::max)());
//Avoid unused variable warnings in 32 bit systems
- (void)max_filesize;
- if( sizeof(std::size_t) >= sizeof(offset_t) && size > std::size_t(max_filesize) ){
+ if(size > max_filesize){
winapi::set_last_error(winapi::error_file_too_large);
return false;
}
@@ -278,7 +282,7 @@
//if(::SetFileAttributes(strFilePath.c_str(), winapi::file_attribute_normal) == 0)
//return winapi::get_last_error();
// Delete file
- winapi::delete_file(strFilePath.c_str());
+ winapi::unlink_file(strFilePath.c_str());
}
}
//Go to the next file
@@ -375,6 +379,9 @@
, file_current = SEEK_CUR
} file_pos_t;
+typedef int map_options_t;
+static const map_options_t default_map_options = map_options_t(-1);
+
namespace ipcdetail{
inline mapping_handle_t mapping_handle_from_file_handle(file_handle_t hnd)
@@ -449,11 +456,10 @@
inline bool truncate_file (file_handle_t hnd, std::size_t size)
{
- if(sizeof(off_t) == sizeof(std::size_t)){
- if(size > ((~std::size_t(0)) >> 1)){
- errno = EINVAL;
- return false;
- }
+ typedef boost::make_unsigned<off_t>::type uoff_t;
+ if(uoff_t((std::numeric_limits<off_t>::max)()) < size){
+ errno = EINVAL;
+ return false;
}
return 0 == ::ftruncate(hnd, off_t(size));
}
Modified: branches/release/boost/interprocess/detail/win32_api.hpp
==============================================================================
--- branches/release/boost/interprocess/detail/win32_api.hpp (original)
+++ branches/release/boost/interprocess/detail/win32_api.hpp 2013-05-18 06:40:55 EDT (Sat, 18 May 2013)
@@ -16,7 +16,7 @@
#include <boost/date_time/filetime_functions.hpp>
#include <cstddef>
#include <cstring>
-#include <cassert>
+#include <boost/assert.hpp>
#include <string>
#include <vector>
#include <memory>
@@ -90,6 +90,7 @@
static const int file_share_valid_flags = 0x00000007;
static const long file_delete_on_close = 0x00001000L;
static const long obj_case_insensitive = 0x00000040L;
+static const long delete_flag = 0x00010000L;
static const unsigned long movefile_copy_allowed = 0x02;
static const unsigned long movefile_delay_until_reboot = 0x04;
@@ -834,6 +835,8 @@
wchar_t NameBuffer[1];
};
+//Kernel32.dll
+
//Some windows API declarations
extern "C" __declspec(dllimport) unsigned long __stdcall GetCurrentProcessId();
extern "C" __declspec(dllimport) unsigned long __stdcall GetCurrentThreadId();
@@ -870,8 +873,6 @@
extern "C" __declspec(dllimport) void * __stdcall MapViewOfFileEx (void *, unsigned long, unsigned long, unsigned long, std::size_t, void*);
extern "C" __declspec(dllimport) void * __stdcall OpenFileMappingA (unsigned long, int, const char *);
extern "C" __declspec(dllimport) void * __stdcall CreateFileA (const char *, unsigned long, unsigned long, struct interprocess_security_attributes*, unsigned long, unsigned long, void *);
-extern "C" __declspec(dllimport) int __stdcall DeleteFileA (const char *);
-extern "C" __declspec(dllimport) int __stdcall MoveFileExA (const char *, const char *, unsigned long);
extern "C" __declspec(dllimport) void __stdcall GetSystemInfo (struct system_info *);
extern "C" __declspec(dllimport) int __stdcall FlushViewOfFile (void *, std::size_t);
extern "C" __declspec(dllimport) int __stdcall VirtualUnlock (void *, std::size_t);
@@ -904,13 +905,14 @@
extern "C" __declspec(dllimport) void *__stdcall GetProcAddress(void *, const char*);
extern "C" __declspec(dllimport) void *__stdcall GetModuleHandleA(const char*);
extern "C" __declspec(dllimport) void *__stdcall GetFileInformationByHandle(void *, interprocess_by_handle_file_information*);
-extern "C" __declspec(dllimport) unsigned long __stdcall GetMappedFileNameW(void *, void *, wchar_t *, unsigned long);
+extern "C" __declspec(dllimport) int __stdcall QueryPerformanceCounter(__int64 *lpPerformanceCount);
+
+//Advapi32.dll
extern "C" __declspec(dllimport) long __stdcall RegOpenKeyExA(void *, const char *, unsigned long, unsigned long, void **);
extern "C" __declspec(dllimport) long __stdcall RegQueryValueExA(void *, const char *, unsigned long*, unsigned long*, unsigned char *, unsigned long*);
extern "C" __declspec(dllimport) long __stdcall RegCloseKey(void *);
-extern "C" __declspec(dllimport) int __stdcall QueryPerformanceCounter(__int64 *lpPerformanceCount);
-//COM API
+//Ole32.dll
extern "C" __declspec(dllimport) long __stdcall CoInitializeEx(void *pvReserved, unsigned long dwCoInit);
extern "C" __declspec(dllimport) long __stdcall CoInitializeSecurity(
void* pSecDesc,
@@ -932,18 +934,19 @@
unsigned long dwImpLevel,
void *pAuthInfo,
unsigned long dwCapabilities);
-
-extern "C" __declspec(dllimport) long __stdcall VariantClear(wchar_variant * pvarg);
extern "C" __declspec(dllimport) long __stdcall CoCreateInstance(const GUID_BIPC & rclsid, IUnknown_BIPC *pUnkOuter,
unsigned long dwClsContext, const GUID_BIPC & riid, void** ppv);
extern "C" __declspec(dllimport) void __stdcall CoUninitialize(void);
+//OleAut32.dll
+extern "C" __declspec(dllimport) long __stdcall VariantClear(wchar_variant * pvarg);
-//API function typedefs
-//Pointer to functions
+//ntdll.dll
typedef long (__stdcall *NtDeleteFile_t)(object_attributes_t *ObjectAttributes);
typedef long (__stdcall *NtSetInformationFile_t)(void *FileHandle, io_status_block_t *IoStatusBlock, void *FileInformation, unsigned long Length, int FileInformationClass );
+typedef long (__stdcall *NtOpenFile)(void **FileHandle, unsigned long DesiredAccess, object_attributes_t *ObjectAttributes
+ , io_status_block_t *IoStatusBlock, unsigned long ShareAccess, unsigned long Length, unsigned long OpenOptions);
typedef long (__stdcall *NtQuerySystemInformation_t)(int, void*, unsigned long, unsigned long *);
typedef long (__stdcall *NtQueryObject_t)(void*, object_information_class, void *, unsigned long, unsigned long *);
typedef long (__stdcall *NtQuerySemaphore_t)(void*, unsigned int info_class, interprocess_semaphore_basic_information *pinfo, unsigned int info_size, unsigned int *ret_len);
@@ -951,14 +954,6 @@
typedef long (__stdcall *NtQueryInformationFile_t)(void *,io_status_block_t *,void *, long, int);
typedef long (__stdcall *NtOpenFile_t)(void*,unsigned long ,object_attributes_t*,io_status_block_t*,unsigned long,unsigned long);
typedef long (__stdcall *NtClose_t) (void*);
-typedef long (__stdcall *RtlCreateUnicodeStringFromAsciiz_t)(unicode_string_t *, const char *);
-typedef void (__stdcall *RtlFreeUnicodeString_t)(unicode_string_t *);
-typedef void (__stdcall *RtlInitUnicodeString_t)( unicode_string_t *, const wchar_t * );
-typedef long (__stdcall *RtlAppendUnicodeToString_t)(unicode_string_t *Destination, const wchar_t *Source);
-typedef unsigned long (__stdcall * GetMappedFileName_t)(void *, void *, wchar_t *, unsigned long);
-typedef long (__stdcall * RegOpenKeyEx_t)(void *, const char *, unsigned long, unsigned long, void **);
-typedef long (__stdcall * RegQueryValueEx_t)(void *, const char *, unsigned long*, unsigned long*, unsigned char *, unsigned long*);
-typedef long (__stdcall * RegCloseKey_t)(void *);
} //namespace winapi {
} //namespace interprocess {
@@ -1125,12 +1120,6 @@
return invalid_handle_value;
}
-inline bool delete_file(const char *name)
-{ return 0 != DeleteFileA(name); }
-
-inline bool move_file_ex(const char *source_filename, const char *destination_filename, unsigned long flags)
-{ return 0 != MoveFileExA(source_filename, destination_filename, flags); }
-
inline void get_system_info(system_info *info)
{ GetSystemInfo(info); }
@@ -1213,9 +1202,6 @@
inline void *get_module_handle(const char *name)
{ return GetModuleHandleA(name); }
-inline unsigned long get_mapped_file_name(void *process, void *lpv, wchar_t *lpfilename, unsigned long nSize)
-{ return GetMappedFileNameW(process, lpv, lpfilename, nSize); }
-
inline long reg_open_key_ex(void *hKey, const char *lpSubKey, unsigned long ulOptions, unsigned long samDesired, void **phkResult)
{ return RegOpenKeyExA(hKey, lpSubKey, ulOptions, samDesired, phkResult); }
@@ -1254,27 +1240,27 @@
template<int Dummy>
struct function_address_holder
{
- enum { NtSetInformationFile, NtQuerySystemInformation, NtQueryObject, NtQuerySemaphore, NtQuerySection, NumFunction };
+ enum { NtSetInformationFile, NtQuerySystemInformation, NtQueryObject, NtQuerySemaphore, NtQuerySection, NtOpenFile, NtClose, NumFunction };
enum { NtDll_dll, NumModule };
private:
+ static const char *FunctionNames[NumFunction];
+ static const char *ModuleNames[NumModule];
static void *FunctionAddresses[NumFunction];
+ static unsigned int FunctionModules[NumFunction];
static volatile long FunctionStates[NumFunction];
static void *ModuleAddresses[NumModule];
static volatile long ModuleStates[NumModule];
static void *get_module_from_id(unsigned int id)
{
- assert(id < (unsigned int)NumModule);
- const char *module[] = { "ntdll.dll" };
- bool compile_check[sizeof(module)/sizeof(module[0]) == NumModule];
- (void)compile_check;
- return get_module_handle(module[id]);
+ BOOST_ASSERT(id < (unsigned int)NumModule);
+ return get_module_handle(ModuleNames[id]);
}
static void *get_module(const unsigned int id)
{
- assert(id < (unsigned int)NumModule);
+ BOOST_ASSERT(id < (unsigned int)NumModule);
while(ModuleStates[id] < 2){
if(interlocked_compare_exchange(&ModuleStates[id], 1, 0) == 0){
ModuleAddresses[id] = get_module_from_id(id);
@@ -1290,17 +1276,14 @@
static void *get_address_from_dll(const unsigned int id)
{
- assert(id < (unsigned int)NumFunction);
- const char *function[] = { "NtSetInformationFile", "NtQuerySystemInformation", "NtQueryObject", "NtQuerySemaphore", "NtQuerySection" };
- bool compile_check[sizeof(function)/sizeof(function[0]) == NumFunction];
- (void)compile_check;
- return get_proc_address(get_module(NtDll_dll), function[id]);
+ BOOST_ASSERT(id < (unsigned int)NumFunction);
+ return get_proc_address(get_module(FunctionModules[id]), FunctionNames[id]);
}
public:
static void *get(const unsigned int id)
{
- assert(id < (unsigned int)NumFunction);
+ BOOST_ASSERT(id < (unsigned int)NumFunction);
while(FunctionStates[id] < 2){
if(interlocked_compare_exchange(&FunctionStates[id], 1, 0) == 0){
FunctionAddresses[id] = get_address_from_dll(id);
@@ -1316,6 +1299,37 @@
};
template<int Dummy>
+const char *function_address_holder<Dummy>::FunctionNames[function_address_holder<Dummy>::NumFunction] =
+{
+ "NtSetInformationFile",
+ "NtQuerySystemInformation",
+ "NtQueryObject",
+ "NtQuerySemaphore",
+ "NtQuerySection",
+ "NtOpenFile",
+ "NtClose"
+};
+
+template<int Dummy>
+unsigned int function_address_holder<Dummy>::FunctionModules[function_address_holder<Dummy>::NumFunction] =
+{
+ NtDll_dll,
+ NtDll_dll,
+ NtDll_dll,
+ NtDll_dll,
+ NtDll_dll,
+ NtDll_dll,
+ NtDll_dll
+};
+
+template<int Dummy>
+const char *function_address_holder<Dummy>::ModuleNames[function_address_holder<Dummy>::NumModule] =
+{
+ "ntdll.dll"
+};
+
+
+template<int Dummy>
void *function_address_holder<Dummy>::FunctionAddresses[function_address_holder<Dummy>::NumFunction];
template<int Dummy>
@@ -1340,47 +1354,6 @@
~library_unloader(){ free_library(lib_); }
};
-//pszFilename must have room for at least MaxPath+1 characters
-inline bool get_file_name_from_handle_function
- (void * hFile, wchar_t *pszFilename, std::size_t length, std::size_t &out_length)
-{
- if(length <= MaxPath){
- return false;
- }
-
-// void *hiPSAPI = load_library("PSAPI.DLL");
-// if (0 == hiPSAPI)
-// return 0;
-// library_unloader unloader(hiPSAPI);
-
-// Pointer to function getMappedFileName() in PSAPI.DLL
-// GetMappedFileName_t pfGMFN =
-// (GetMappedFileName_t)get_proc_address(hiPSAPI, "GetMappedFileNameW");
-// if (! pfGMFN){
-// return 0; // Failed: unexpected error
-// }
-
- bool bSuccess = false;
-
- // Create a file mapping object.
- void * hFileMap = create_file_mapping(hFile, page_readonly, 1, 0, 0);
- if(hFileMap){
- // Create a file mapping to get the file name.
- void* pMem = map_view_of_file_ex(hFileMap, file_map_read, 0, 1, 0);
-
- if (pMem){
- //out_length = pfGMFN(get_current_process(), pMem, pszFilename, MaxPath);
- out_length = get_mapped_file_name(get_current_process(), pMem, pszFilename, MaxPath);
- if(out_length){
- bSuccess = true;
- }
- unmap_view_of_file(pMem);
- }
- close_handle(hFileMap);
- }
-
- return(bSuccess);
-}
inline bool get_system_time_of_day_information(system_timeofday_information &info)
{
@@ -1437,6 +1410,21 @@
return true;
}
+//Writes the hexadecimal value of the buffer, in the wide character string.
+//str must be twice length
+inline void buffer_to_wide_str(const void *buf, std::size_t length, wchar_t *str)
+{
+ const wchar_t Characters [] =
+ { L'0', L'1', L'2', L'3', L'4', L'5', L'6', L'7'
+ , L'8', L'9', L'A', L'B', L'C', L'D', L'E', L'F' };
+ std::size_t char_counter = 0;
+ const char *chbuf = static_cast<const char *>(buf);
+ for(std::size_t i = 0; i != length; ++i){
+ str[char_counter++] = Characters[(chbuf[i]&0xF0)>>4];
+ str[char_counter++] = Characters[(chbuf[i]&0x0F)];
+ }
+}
+
inline bool get_boot_and_system_time_wstr(wchar_t *bootsystemstamp, std::size_t &s) //will write BootAndSystemstampLength chars
{
if(s < (BootAndSystemstampLength*2))
@@ -1446,14 +1434,8 @@
if(!ret){
return false;
}
- const wchar_t Characters [] =
- { L'0', L'1', L'2', L'3', L'4', L'5', L'6', L'7'
- , L'8', L'9', L'A', L'B', L'C', L'D', L'E', L'F' };
- std::size_t char_counter = 0;
- for(std::size_t i = 0; i != static_cast<std::size_t>(BootAndSystemstampLength); ++i){
- bootsystemstamp[char_counter++] = Characters[(info.Reserved1[i]&0xF0)>>4];
- bootsystemstamp[char_counter++] = Characters[(info.Reserved1[i]&0x0F)];
- }
+
+ buffer_to_wide_str(&info.Reserved1[0], BootAndSystemstampLength, bootsystemstamp);
s = BootAndSystemstampLength*2;
return true;
}
@@ -1475,10 +1457,51 @@
struct ren_t
{
file_rename_information_t info;
- wchar_t buf[32767];
+ wchar_t buf[1];
} ren;
};
+class nt_query_mem_deleter
+{
+ static const std::size_t rename_offset = offsetof(ntquery_mem_t, ren.info.FileName) -
+ offsetof(ntquery_mem_t, name.Name.Buffer);
+ // Timestamp process id atomic count
+ static const std::size_t rename_suffix = (SystemTimeOfDayInfoLength + sizeof(unsigned long) + sizeof(boost::uint32_t))*2;
+
+ public:
+ nt_query_mem_deleter(std::size_t object_name_information_size)
+ : m_size(object_name_information_size + rename_offset + rename_suffix)
+ , m_buf(new char [m_size])
+ {}
+
+ ~nt_query_mem_deleter()
+ {
+ delete[]m_buf;
+ }
+
+ void realloc(std::size_t num_bytes)
+ {
+ num_bytes += rename_suffix + rename_offset;
+ char *buf = m_buf;
+ m_buf = new char[num_bytes];
+ delete[]buf;
+ m_size = num_bytes;
+ }
+
+ ntquery_mem_t *query_mem() const
+ { return static_cast<ntquery_mem_t *>(static_cast<void*>(m_buf)); }
+
+ unsigned long object_name_information_size() const
+ { return static_cast<unsigned long>(m_size - rename_offset - SystemTimeOfDayInfoLength*2); }
+
+ std::size_t file_rename_information_size() const
+ { return static_cast<unsigned long>(m_size); }
+
+ private:
+ std::size_t m_size;
+ char *m_buf;
+};
+
inline bool unlink_file(const char *filename)
{
//Don't try to optimize doing a DeleteFile first
@@ -1499,71 +1522,96 @@
try{
NtSetInformationFile_t pNtSetInformationFile =
(NtSetInformationFile_t)dll_func::get(dll_func::NtSetInformationFile);
- if(!pNtSetInformationFile){
- return false;
- }
- NtQueryObject_t pNtQueryObject =
- (NtQueryObject_t)dll_func::get(dll_func::NtQueryObject);
+ NtQueryObject_t pNtQueryObject = (NtQueryObject_t)dll_func::get(dll_func::NtQueryObject);
//First step: Obtain a handle to the file using Win32 rules. This resolves relative paths
- void *fh = create_file(filename, generic_read | delete_access, open_existing,
- file_flag_backup_semantics | file_flag_delete_on_close, 0);
+ void *fh = create_file(filename, generic_read | delete_access, open_existing, 0, 0);
if(fh == invalid_handle_value){
return false;
}
handle_closer h_closer(fh);
+ {
+ //Obtain name length
+ unsigned long size;
+ const std::size_t initial_string_mem = 512u;
+
+ nt_query_mem_deleter nt_query_mem(sizeof(ntquery_mem_t)+initial_string_mem);
+ //Obtain file name with guessed length
+ if(pNtQueryObject(fh, object_name_information, nt_query_mem.query_mem(), nt_query_mem.object_name_information_size(), &size)){
+ //Obtain file name with exact length buffer
+ nt_query_mem.realloc(size);
+ if(pNtQueryObject(fh, object_name_information, nt_query_mem.query_mem(), nt_query_mem.object_name_information_size(), &size)){
+ return false;
+ }
+ }
+ ntquery_mem_t *pmem = nt_query_mem.query_mem();
+ file_rename_information_t *pfri = &pmem->ren.info;
+ const std::size_t RenMaxNumChars =
+ (((char*)(pmem) + nt_query_mem.file_rename_information_size()) - (char*)&pmem->ren.info.FileName[0])/sizeof(wchar_t);
+
+ //Copy filename to the rename member
+ std::memmove(pmem->ren.info.FileName, pmem->name.Name.Buffer, pmem->name.Name.Length);
+ std::size_t filename_string_length = pmem->name.Name.Length/sizeof(wchar_t);
+
+ //Search '\\' character to replace from it
+ for(std::size_t i = filename_string_length; i != 0; --filename_string_length){
+ if(pmem->ren.info.FileName[--i] == L'\\')
+ break;
+ }
- std::auto_ptr<ntquery_mem_t> pmem(new ntquery_mem_t);
- file_rename_information_t *pfri = &pmem->ren.info;
- const std::size_t RenMaxNumChars =
- ((char*)pmem.get() - (char*)&pmem->ren.info.FileName[0])/sizeof(wchar_t);
-
- //Obtain file name
- unsigned long size;
- if(pNtQueryObject(fh, object_name_information, pmem.get(), sizeof(ntquery_mem_t), &size)){
- return false;
- }
-
- //Copy filename to the rename member
- std::memmove(pmem->ren.info.FileName, pmem->name.Name.Buffer, pmem->name.Name.Length);
- std::size_t filename_string_length = pmem->name.Name.Length/sizeof(wchar_t);
-
- //Second step: obtain the complete native-nt filename
- //if(!get_file_name_from_handle_function(fh, pfri->FileName, RenMaxNumChars, filename_string_length)){
- //return 0;
- //}
-
- //Add trailing mark
- if((RenMaxNumChars-filename_string_length) < (SystemTimeOfDayInfoLength*2)){
- return false;
- }
-
- //Search '\\' character to replace it
- for(std::size_t i = filename_string_length; i != 0; --filename_string_length){
- if(pmem->ren.info.FileName[--i] == L'\\')
- break;
- }
+ //Add random number
+ std::size_t s = RenMaxNumChars - filename_string_length;
+ if(!get_boot_and_system_time_wstr(&pfri->FileName[filename_string_length], s)){
+ return false;
+ }
+ filename_string_length += s;
- //Add random number
- std::size_t s = RenMaxNumChars - filename_string_length;
- if(!get_boot_and_system_time_wstr(&pfri->FileName[filename_string_length], s)){
- return false;
+ //Sometimes the precission of the timestamp is not enough and we need to add another random number.
+ //The process id (to exclude concurrent processes) and an atomic count (to exclude concurrent threads).
+ //should be enough
+ const unsigned long pid = get_current_process_id();
+ buffer_to_wide_str(&pid, sizeof(pid), &pfri->FileName[filename_string_length]);
+ filename_string_length += sizeof(pid)*2;
+
+ static volatile boost::uint32_t u32_count = 0;
+ interlocked_decrement(reinterpret_cast<volatile long*>(&u32_count));
+ buffer_to_wide_str(const_cast<const boost::uint32_t *>(&u32_count), sizeof(boost::uint32_t), &pfri->FileName[filename_string_length]);
+ filename_string_length += sizeof(boost::uint32_t)*2;
+
+ //Fill rename information (FileNameLength is in bytes)
+ pfri->FileNameLength = static_cast<unsigned long>(sizeof(wchar_t)*(filename_string_length));
+ pfri->Replace = 1;
+ pfri->RootDir = 0;
+
+ //Cange the name of the in-use file...
+ io_status_block_t io;
+ if(0 != pNtSetInformationFile(fh, &io, pfri, nt_query_mem.file_rename_information_size(), file_rename_information)){
+ return false;
+ }
}
- filename_string_length += s;
-
- //Fill rename information (FileNameLength is in bytes)
- pfri->FileNameLength = static_cast<unsigned long>(sizeof(wchar_t)*(filename_string_length));
- pfri->Replace = 1;
- pfri->RootDir = 0;
-
- //Final step: change the name of the in-use file:
- io_status_block_t io;
- if(0 != pNtSetInformationFile(fh, &io, pfri, sizeof(ntquery_mem_t::ren_t), file_rename_information)){
- return false;
+ //...and mark it as delete-on-close
+ {
+ //Don't use pNtSetInformationFile with file_disposition_information as it can return STATUS_CANNOT_DELETE
+ //if the file is still mapped. Reopen it with NtOpenFile and file_delete_on_close
+ NtOpenFile_t pNtOpenFile = (NtOpenFile_t)dll_func::get(dll_func::NtOpenFile);
+ NtClose_t pNtClose = (NtClose_t)dll_func::get(dll_func::NtClose);
+ const wchar_t empty_str [] = L"";
+ unicode_string_t ustring = { sizeof(empty_str) - sizeof (wchar_t) //length in bytes without null
+ , sizeof(empty_str) //total size in bytes of memory allocated for Buffer.
+ , const_cast<wchar_t*>(empty_str)
+ };
+ object_attributes_t object_attr;
+ initialize_object_attributes(&object_attr, &ustring, 0, fh, 0);
+ void* fh2 = 0;
+ io_status_block_t io;
+ pNtOpenFile( &fh2, delete_flag, &object_attr, &io
+ , file_share_read | file_share_write | file_share_delete, file_delete_on_close);
+ pNtClose(fh2);
+ //Even if NtOpenFile fails, the file was renamed and the original no longer exists, so return a success status
+ return true;
}
- return true;
}
catch(...){
return false;
@@ -1573,9 +1621,6 @@
struct reg_closer
{
- //reg_closer(RegCloseKey_t func, void *key) : func_(func), key_(key){}
- //~reg_closer(){ (*func_)(key_); }
- //RegCloseKey_t func_;
void *key_;
reg_closer(void *key) : key_(key){}
~reg_closer(){ reg_close_key(key_); }
Modified: branches/release/boost/interprocess/detail/workaround.hpp
==============================================================================
--- branches/release/boost/interprocess/detail/workaround.hpp (original)
+++ branches/release/boost/interprocess/detail/workaround.hpp 2013-05-18 06:40:55 EDT (Sat, 18 May 2013)
@@ -110,6 +110,10 @@
#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__APPLE__)
#define BOOST_INTERPROCESS_BSD_DERIVATIVE
+ //Some *BSD systems (OpenBSD & NetBSD) need sys/param.h before sys/sysctl.h, whereas
+ //others (FreeBSD & Darwin) need sys/types.h
+ #include <sys/types.h>
+ #include <sys/param.h>
#include <sys/sysctl.h>
#if defined(CTL_KERN) && defined (KERN_BOOTTIME)
//#define BOOST_INTERPROCESS_HAS_KERNEL_BOOTTIME
Modified: branches/release/boost/interprocess/file_mapping.hpp
==============================================================================
--- branches/release/boost/interprocess/file_mapping.hpp (original)
+++ branches/release/boost/interprocess/file_mapping.hpp 2013-05-18 06:40:55 EDT (Sat, 18 May 2013)
@@ -52,6 +52,7 @@
//!Does not throw
file_mapping(BOOST_RV_REF(file_mapping) moved)
: m_handle(file_handle_t(ipcdetail::invalid_file()))
+ , m_mode(read_only)
{ this->swap(moved); }
//!Moves the ownership of "moved"'s file mapping to *this.
@@ -95,13 +96,14 @@
//!Closes a previously opened file mapping. Never throws.
void priv_close();
file_handle_t m_handle;
- mode_t m_mode;
- std::string m_filename;
+ mode_t m_mode;
+ std::string m_filename;
/// @endcond
};
inline file_mapping::file_mapping()
: m_handle(file_handle_t(ipcdetail::invalid_file()))
+ , m_mode(read_only)
{}
inline file_mapping::~file_mapping()
Modified: branches/release/boost/interprocess/ipc/message_queue.hpp
==============================================================================
--- branches/release/boost/interprocess/ipc/message_queue.hpp (original)
+++ branches/release/boost/interprocess/ipc/message_queue.hpp 2013-05-18 06:40:55 EDT (Sat, 18 May 2013)
@@ -30,6 +30,7 @@
#include <boost/type_traits/make_unsigned.hpp>
#include <boost/type_traits/alignment_of.hpp>
#include <boost/intrusive/pointer_traits.hpp>
+#include <boost/assert.hpp>
#include <algorithm> //std::lower_bound
#include <cstddef> //std::size_t
#include <cstring> //memcpy
@@ -161,7 +162,7 @@
//!Returns the number of messages currently stored.
//!Never throws
- size_type get_num_msg();
+ size_type get_num_msg() const;
//!Removes the message queue from the system.
//!Returns false on error. Never throws
@@ -358,8 +359,8 @@
iterator idx_beg = &mp_index[0];
ret = std::lower_bound(idx_beg, end, value, func);
//sanity check, these cases should not call lower_bound (optimized out)
- assert(ret != end);
- assert(ret != begin);
+ BOOST_ASSERT(ret != end);
+ BOOST_ASSERT(ret != begin);
return ret;
}
else{
@@ -752,8 +753,8 @@
ipcdetail::msg_hdr_t<VoidPointer> &free_msg_hdr = p_hdr->queue_free_msg(priority);
//Sanity check, free msgs are always cleaned when received
- assert(free_msg_hdr.priority == 0);
- assert(free_msg_hdr.len == 0);
+ BOOST_ASSERT(free_msg_hdr.priority == 0);
+ BOOST_ASSERT(free_msg_hdr.len == 0);
//Copy control data to the free message
free_msg_hdr.priority = priority;
@@ -890,7 +891,7 @@
}
template<class VoidPointer>
-inline typename message_queue_t<VoidPointer>::size_type message_queue_t<VoidPointer>::get_num_msg()
+inline typename message_queue_t<VoidPointer>::size_type message_queue_t<VoidPointer>::get_num_msg() const
{
ipcdetail::mq_hdr_t<VoidPointer> *p_hdr = static_cast<ipcdetail::mq_hdr_t<VoidPointer>*>(m_shmem.get_user_address());
if(p_hdr){
Modified: branches/release/boost/interprocess/mapped_region.hpp
==============================================================================
--- branches/release/boost/interprocess/mapped_region.hpp (original)
+++ branches/release/boost/interprocess/mapped_region.hpp 2013-05-18 06:40:55 EDT (Sat, 18 May 2013)
@@ -21,6 +21,7 @@
#include <boost/interprocess/detail/os_file_functions.hpp>
#include <string>
#include <boost/cstdint.hpp>
+#include <boost/assert.hpp>
//Some Unixes use caddr_t instead of void * in madvise
// SunOS Tru64 HP-UX AIX
#if defined(sun) || defined(__sun) || defined(__osf__) || defined(__osf) || defined(_hpux) || defined(hpux) || defined(_AIX)
@@ -95,6 +96,22 @@
//!If an address is specified, both the offset and the address must be
//!multiples of the page size.
//!
+ //!The map is created using "default_map_options". This flag is OS
+ //!dependant and it should not be changed unless the user needs to
+ //!specify special options.
+ //!
+ //!In Windows systems "map_options" is a DWORD value passed as
+ //!"dwDesiredAccess" to "MapViewOfFileEx". If "default_map_options" is passed
+ //!it's initialized to zero. "map_options" is XORed with FILE_MAP_[COPY|READ|WRITE].
+ //!
+ //!In UNIX systems and POSIX mappings "map_options" is an int value passed as "flags"
+ //!to "mmap". If "default_map_options" is specified it's initialized to MAP_NOSYNC
+ //!if that option exists and to zero otherwise. "map_options" XORed with MAP_PRIVATE or MAP_SHARED.
+ //!
+ //!In UNIX systems and XSI mappings "map_options" is an int value passed as "shmflg"
+ //!to "shmat". If "default_map_options" is specified it's initialized to zero.
+ //!"map_options" is XORed with SHM_RDONLY if needed.
+ //!
//!The OS could allocate more pages than size/page_size(), but get_address()
//!will always return the address passed in this function (if not null) and
//!get_size() will return the specified size.
@@ -103,7 +120,8 @@
,mode_t mode
,offset_t offset = 0
,std::size_t size = 0
- ,const void *address = 0);
+ ,const void *address = 0
+ ,map_options_t map_options = default_map_options);
//!Default constructor. Address will be 0 (nullptr).
//!Size will be 0.
@@ -308,7 +326,7 @@
m_page_offset = m_page_offset % page_size;
m_size -= bytes;
m_base = static_cast<char *>(m_base) + bytes;
- assert(shrink_page_bytes%page_size == 0);
+ BOOST_ASSERT(shrink_page_bytes%page_size == 0);
}
return true;
}
@@ -366,7 +384,8 @@
,mode_t mode
,offset_t offset
,std::size_t size
- ,const void *address)
+ ,const void *address
+ ,map_options_t map_options)
: m_base(0), m_size(0), m_page_offset(0), m_mode(mode)
, m_file_or_mapping_hnd(ipcdetail::invalid_file())
{
@@ -378,7 +397,7 @@
//For "create_file_mapping"
unsigned long protection = 0;
//For "mapviewoffile"
- unsigned long map_access = 0;
+ unsigned long map_access = map_options == default_map_options ? 0 : map_options;
switch(mode)
{
@@ -444,7 +463,6 @@
priv_size_from_mapping_size(mapping_size, offset, page_offset, size);
}
-
//Map with new offsets and size
void *base = winapi::map_view_of_file_ex
(native_mapping_handle,
@@ -559,7 +577,8 @@
, mode_t mode
, offset_t offset
, std::size_t size
- , const void *address)
+ , const void *address
+ , map_options_t map_options)
: m_base(0), m_size(0), m_page_offset(0), m_mode(mode), m_is_xsi(false)
{
mapping_handle_t map_hnd = mapping.get_mapping_handle();
@@ -583,7 +602,7 @@
throw interprocess_exception(err);
}
//Calculate flag
- int flag = 0;
+ int flag = map_options == default_map_options ? 0 : map_options;
if(m_mode == read_only){
flag |= SHM_RDONLY;
}
@@ -620,15 +639,17 @@
priv_size_from_mapping_size(buf.st_size, offset, page_offset, size);
}
+ #ifdef MAP_NOSYNC
+ #define BOOST_INTERPROCESS_MAP_NOSYNC MAP_NOSYNC
+ #else
+ #define BOOST_INTERPROCESS_MAP_NOSYNC 0
+ #endif //MAP_NOSYNC
+
//Create new mapping
int prot = 0;
- int flags =
- #ifdef MAP_NOSYNC
- //Avoid excessive syncing in BSD systems
- MAP_NOSYNC;
- #else
- 0;
- #endif
+ int flags = map_options == default_map_options ? BOOST_INTERPROCESS_MAP_NOSYNC : map_options;
+
+ #undef BOOST_INTERPROCESS_MAP_NOSYNC
switch(mode)
{
Modified: branches/release/boost/interprocess/offset_ptr.hpp
==============================================================================
--- branches/release/boost/interprocess/offset_ptr.hpp (original)
+++ branches/release/boost/interprocess/offset_ptr.hpp 2013-05-18 06:40:55 EDT (Sat, 18 May 2013)
@@ -90,11 +90,11 @@
return 0;
}
else{
- caster_t caster((void*)this_ptr);
+ const caster_t caster((void*)this_ptr);
return caster_t(caster.size() + offset).pointer();
}
#else
- caster_t caster((void*)this_ptr);
+ const caster_t caster((void*)this_ptr);
return caster_t((caster.size() + offset) & -std::size_t(offset != 1)).pointer();
#endif
}
@@ -113,7 +113,7 @@
////////////////////////////////////////////////////////////////////////
#define BOOST_INTERPROCESS_OFFSET_PTR_INLINE_TO_OFF
//Branchless seems slower in x86
- //#define BOOST_INTERPROCESS_OFFSET_PTR_BRANCHLESS_TO_OFF
+ #define BOOST_INTERPROCESS_OFFSET_PTR_BRANCHLESS_TO_OFF
template<int Dummy>
#ifndef BOOST_INTERPROCESS_OFFSET_PTR_INLINE_TO_OFF
@@ -130,18 +130,21 @@
return 1;
}
else{
- caster_t this_caster((void*)this_ptr);
- caster_t ptr_caster((void*)ptr);
+ const caster_t this_caster((void*)this_ptr);
+ const caster_t ptr_caster((void*)ptr);
std::size_t offset = ptr_caster.size() - this_caster.size();
BOOST_ASSERT(offset != 1);
return offset;
}
#else
- caster_t this_caster((void*)this_ptr);
- caster_t ptr_caster((void*)ptr);
+ const caster_t this_caster((void*)this_ptr);
+ const caster_t ptr_caster((void*)ptr);
+ //std::size_t other = -std::size_t(ptr != 0);
+ //std::size_t offset = (ptr_caster.size() - this_caster.size()) & other;
+ //return offset + !other;
+ //
std::size_t offset = (ptr_caster.size() - this_caster.size() - 1) & -std::size_t(ptr != 0);
- ++offset;
- return offset;
+ return ++offset;
#endif
}
@@ -159,7 +162,7 @@
////////////////////////////////////////////////////////////////////////
#define BOOST_INTERPROCESS_OFFSET_PTR_INLINE_TO_OFF_FROM_OTHER
//Branchless seems slower in x86
- //#define BOOST_INTERPROCESS_OFFSET_PTR_BRANCHLESS_TO_OFF_FROM_OTHER
+ #define BOOST_INTERPROCESS_OFFSET_PTR_BRANCHLESS_TO_OFF_FROM_OTHER
template<int Dummy>
#ifndef BOOST_INTERPROCESS_OFFSET_PTR_INLINE_TO_OFF_FROM_OTHER
@@ -176,18 +179,16 @@
return 1;
}
else{
- caster_t this_caster((void*)this_ptr);
- caster_t other_caster((void*)other_ptr);
+ const caster_t this_caster((void*)this_ptr);
+ const caster_t other_caster((void*)other_ptr);
std::size_t offset = other_caster.size() - this_caster.size() + other_offset;
BOOST_ASSERT(offset != 1);
return offset;
}
#else
- caster_t this_caster((void*)this_ptr);
- caster_t other_caster((void*)other_ptr);
- std::size_t offset = (other_caster.size() - this_caster.size()) & -std::size_t(other_offset != 1);
- offset += other_offset;
- return offset;
+ const caster_t this_caster((void*)this_ptr);
+ const caster_t other_caster((void*)other_ptr);
+ return ((other_caster.size() - this_caster.size()) & -std::size_t(other_offset != 1)) + other_offset;
#endif
}
Modified: branches/release/boost/interprocess/shared_memory_object.hpp
==============================================================================
--- branches/release/boost/interprocess/shared_memory_object.hpp (original)
+++ branches/release/boost/interprocess/shared_memory_object.hpp 2013-05-18 06:40:55 EDT (Sat, 18 May 2013)
@@ -81,6 +81,7 @@
//!Does not throw
shared_memory_object(BOOST_RV_REF(shared_memory_object) moved)
: m_handle(file_handle_t(ipcdetail::invalid_file()))
+ , m_mode(read_only)
{ this->swap(moved); }
//!Moves the ownership of "moved"'s shared memory to *this.
@@ -144,6 +145,7 @@
inline shared_memory_object::shared_memory_object()
: m_handle(file_handle_t(ipcdetail::invalid_file()))
+ , m_mode(read_only)
{}
inline shared_memory_object::~shared_memory_object()
@@ -318,20 +320,26 @@
break;
case ipcdetail::DoOpenOrCreate:
{
- oflag |= O_CREAT;
- //We need a loop to change permissions correctly using fchmod, since
- //with "O_CREAT only" shm_open we don't know if we've created or opened the file.
+ //We need a create/open loop to change permissions correctly using fchmod, since
+ //with "O_CREAT" only we don't know if we've created or opened the shm.
while(1){
- m_handle = shm_open(m_filename.c_str(), oflag, unix_perm);
+ //Try to create shared memory
+ m_handle = shm_open(m_filename.c_str(), oflag | (O_CREAT | O_EXCL), unix_perm);
+ //If successful change real permissions
if(m_handle >= 0){
::fchmod(m_handle, unix_perm);
- break;
}
+ //If already exists, try to open
else if(errno == EEXIST){
- if((m_handle = shm_open(m_filename.c_str(), oflag, unix_perm)) >= 0 || errno != ENOENT){
- break;
+ m_handle = shm_open(m_filename.c_str(), oflag, unix_perm);
+ //If open fails and errno tells the file does not exist
+ //(shm was removed between creation and opening tries), just retry
+ if(m_handle < 0 && errno == ENOENT){
+ continue;
}
}
+ //Exit retries
+ break;
}
}
break;
@@ -343,7 +351,7 @@
}
//Check for error
- if(m_handle == -1){
+ if(m_handle < 0){
error_info err = errno;
this->priv_close();
throw interprocess_exception(err);
Modified: branches/release/boost/interprocess/smart_ptr/detail/shared_count.hpp
==============================================================================
--- branches/release/boost/interprocess/smart_ptr/detail/shared_count.hpp (original)
+++ branches/release/boost/interprocess/smart_ptr/detail/shared_count.hpp 2013-05-18 06:40:55 EDT (Sat, 18 May 2013)
@@ -284,6 +284,7 @@
weak_count & operator= (weak_count const & r) // nothrow
{
+ m_px = r.m_px;
counted_impl_ptr tmp = r.m_pi;
if(tmp != 0) tmp->weak_add_ref();
if(m_pi != 0) m_pi->weak_release();
Modified: branches/release/boost/interprocess/smart_ptr/unique_ptr.hpp
==============================================================================
--- branches/release/boost/interprocess/smart_ptr/unique_ptr.hpp (original)
+++ branches/release/boost/interprocess/smart_ptr/unique_ptr.hpp 2013-05-18 06:40:55 EDT (Sat, 18 May 2013)
@@ -82,7 +82,9 @@
class unique_ptr
{
/// @cond
- struct nat {int for_bool_;};
+ struct nat {int for_bool;};
+ struct nat2 {int for_nullptr;};
+ typedef int nat2::*nullptr_t;
typedef typename ipcdetail::add_reference<D>::type deleter_reference;
typedef typename ipcdetail::add_reference<const D>::type deleter_const_reference;
/// @endcond
@@ -175,7 +177,7 @@
//!
//!Throws: nothing.
template <class U, class E>
- unique_ptr(BOOST_RV_REF_2_TEMPL_ARGS(unique_ptr, U, E) u,
+ unique_ptr(BOOST_RV_REF_BEG unique_ptr<U, E> BOOST_RV_REF_END u,
typename ipcdetail::enable_if_c<
ipcdetail::is_convertible<typename unique_ptr<U, E>::pointer, pointer>::value &&
ipcdetail::is_convertible<E, D>::value &&
@@ -230,7 +232,7 @@
//!
//!Throws: nothing.
template <class U, class E>
- unique_ptr& operator=(BOOST_RV_REF_2_TEMPL_ARGS(unique_ptr, U, E) u)
+ unique_ptr& operator=(BOOST_RV_REF_BEG unique_ptr<U, E> BOOST_RV_REF_END u)
{
reset(u.release());
ptr_.second() = boost::move(u.get_deleter());
@@ -246,7 +248,7 @@
//!Returns: *this.
//!
//!Throws: nothing.
- unique_ptr& operator=(int nat::*)
+ unique_ptr& operator=(nullptr_t)
{
reset();
return *this;
@@ -286,7 +288,7 @@
//!
//!Throws: nothing.
operator int nat::*() const
- { return ptr_.first() ? &nat::for_bool_ : 0; }
+ { return ptr_.first() ? &nat::for_bool : 0; }
//!Postcondition: get() == 0.
//!
@@ -457,7 +459,7 @@
pointer get() const {return ptr_.first();}
deleter_reference get_deleter() {return ptr_.second();}
deleter_const_reference get_deleter() const {return ptr_.second();}
- operator int nat::*() const {return ptr_.first() ? &nat::for_bool_ : 0;}
+ operator int nat::*() const {return ptr_.first() ? &nat::for_bool : 0;}
// modifiers
pointer release()
Modified: branches/release/boost/interprocess/sync/shm/named_condition.hpp
==============================================================================
--- branches/release/boost/interprocess/sync/shm/named_condition.hpp (original)
+++ branches/release/boost/interprocess/sync/shm/named_condition.hpp 2013-05-18 06:40:55 EDT (Sat, 18 May 2013)
@@ -145,7 +145,8 @@
typedef interprocess_condition internal_condition;
#endif //defined (BOOST_INTERPROCESS_NAMED_MUTEX_USES_POSIX_SEMAPHORES)
- internal_condition m_cond;
+ internal_condition &internal_cond()
+ { return *static_cast<internal_condition*>(m_shmem.get_user_address()); }
friend class boost::interprocess::ipcdetail::interprocess_tester;
void dont_close_on_destruction();
@@ -196,71 +197,29 @@
inline void shm_named_condition::dont_close_on_destruction()
{ interprocess_tester::dont_close_on_destruction(m_shmem); }
-#if defined(BOOST_INTERPROCESS_NAMED_MUTEX_USES_POSIX_SEMAPHORES)
-
inline void shm_named_condition::notify_one()
-{ m_cond.notify_one(); }
+{ this->internal_cond().notify_one(); }
inline void shm_named_condition::notify_all()
-{ m_cond.notify_all(); }
+{ this->internal_cond().notify_all(); }
template <typename L>
inline void shm_named_condition::wait(L& lock)
-{ m_cond.wait(lock); }
+{ this->internal_cond().wait(lock); }
template <typename L, typename Pr>
inline void shm_named_condition::wait(L& lock, Pr pred)
-{ m_cond.wait(lock, pred); }
+{ this->internal_cond().wait(lock, pred); }
template <typename L>
inline bool shm_named_condition::timed_wait
(L& lock, const boost::posix_time::ptime &abs_time)
-{ return m_cond.timed_wait(lock, abs_time); }
+{ return this->internal_cond().timed_wait(lock, abs_time); }
template <typename L, typename Pr>
inline bool shm_named_condition::timed_wait
(L& lock, const boost::posix_time::ptime &abs_time, Pr pred)
-{ return m_cond.timed_wait(lock, abs_time, pred); }
-
-#else
-
-inline void shm_named_condition::notify_one()
-{ m_cond.notify_one(); }
-
-inline void shm_named_condition::notify_all()
-{ m_cond.notify_all(); }
-
-template <typename L>
-inline void shm_named_condition::wait(L& lock)
-{
- internal_mutex_lock<L> internal_lock(lock);
- m_cond.wait(internal_lock);
-}
-
-template <typename L, typename Pr>
-inline void shm_named_condition::wait(L& lock, Pr pred)
-{
- internal_mutex_lock<L> internal_lock(lock);
- m_cond.wait(internal_lock, pred);
-}
-
-template <typename L>
-inline bool shm_named_condition::timed_wait
- (L& lock, const boost::posix_time::ptime &abs_time)
-{
- internal_mutex_lock<L> internal_lock(lock);
- return m_cond.timed_wait(internal_lock, abs_time);
-}
-
-template <typename L, typename Pr>
-inline bool shm_named_condition::timed_wait
- (L& lock, const boost::posix_time::ptime &abs_time, Pr pred)
-{
- internal_mutex_lock<L> internal_lock(lock);
- return m_cond.timed_wait(internal_lock, abs_time, pred);
-}
-
-#endif
+{ return this->internal_cond().timed_wait(lock, abs_time, pred); }
inline bool shm_named_condition::remove(const char *name)
{ return shared_memory_object::remove(name); }
Modified: branches/release/boost/interprocess/sync/windows/mutex.hpp
==============================================================================
--- branches/release/boost/interprocess/sync/windows/mutex.hpp (original)
+++ branches/release/boost/interprocess/sync/windows/mutex.hpp 2013-05-18 06:40:55 EDT (Sat, 18 May 2013)
@@ -57,8 +57,8 @@
bool open_or_created;
(void)handles.obtain_mutex(this->id_, &open_or_created);
//The mutex must be created, never opened
- assert(open_or_created);
- assert(open_or_created && winapi::get_last_error() != winapi::error_already_exists);
+ BOOST_ASSERT(open_or_created);
+ BOOST_ASSERT(open_or_created && winapi::get_last_error() != winapi::error_already_exists);
(void)open_or_created;
}
Modified: branches/release/boost/interprocess/sync/windows/named_sync.hpp
==============================================================================
--- branches/release/boost/interprocess/sync/windows/named_sync.hpp (original)
+++ branches/release/boost/interprocess/sync/windows/named_sync.hpp 2013-05-18 06:40:55 EDT (Sat, 18 May 2013)
@@ -24,7 +24,7 @@
#include <boost/interprocess/errors.hpp>
#include <boost/interprocess/exceptions.hpp>
#include <string>
-#include <cassert>
+#include <boost/assert.hpp>
namespace boost {
namespace interprocess {
@@ -145,7 +145,7 @@
success = true;
}
winapi::get_file_size(m_file_hnd, filesize);
- assert(std::size_t(filesize) == sizeof_file_info);
+ BOOST_ASSERT(std::size_t(filesize) == sizeof_file_info);
}
else{
void *buf = sync_interface.buffer_to_store_init_data_from_file();
Modified: branches/release/boost/interprocess/sync/windows/semaphore.hpp
==============================================================================
--- branches/release/boost/interprocess/sync/windows/semaphore.hpp (original)
+++ branches/release/boost/interprocess/sync/windows/semaphore.hpp 2013-05-18 06:40:55 EDT (Sat, 18 May 2013)
@@ -23,6 +23,7 @@
#include <boost/interprocess/sync/windows/sync_utils.hpp>
#include <boost/interprocess/sync/windows/winapi_semaphore_wrapper.hpp>
#include <boost/interprocess/exceptions.hpp>
+#include <boost/assert.hpp>
namespace boost {
@@ -56,8 +57,8 @@
bool open_or_created;
handles.obtain_semaphore(this->id_, initialCount, &open_or_created);
//The semaphore must be created, never opened
- assert(open_or_created);
- assert(open_or_created && winapi::get_last_error() != winapi::error_already_exists);
+ BOOST_ASSERT(open_or_created);
+ BOOST_ASSERT(open_or_created && winapi::get_last_error() != winapi::error_already_exists);
(void)open_or_created;
}
Modified: branches/release/boost/intrusive/detail/parent_from_member.hpp
==============================================================================
--- branches/release/boost/intrusive/detail/parent_from_member.hpp (original)
+++ branches/release/boost/intrusive/detail/parent_from_member.hpp 2013-05-18 06:40:55 EDT (Sat, 18 May 2013)
@@ -16,9 +16,9 @@
#include <cstddef>
#if defined(BOOST_MSVC) || ((defined(_WIN32) || defined(__WIN32__) || defined(WIN32)) && defined(BOOST_INTEL))
-
-#define BOOST_INTRUSIVE_MSVC_COMPLIANT_PTR_TO_MEMBER
-#include <boost/cstdint.hpp>
+ #define BOOST_INTRUSIVE_MSVC_ABI_PTR_TO_MEMBER
+ #include <boost/cstdint.hpp>
+ #include <boost/static_assert.hpp>
#endif
namespace boost {
@@ -29,7 +29,7 @@
inline std::ptrdiff_t offset_from_pointer_to_member(const Member Parent::* ptr_to_member)
{
//The implementation of a pointer to member is compiler dependent.
- #if defined(BOOST_INTRUSIVE_MSVC_COMPLIANT_PTR_TO_MEMBER)
+ #if defined(BOOST_INTRUSIVE_MSVC_ABI_PTR_TO_MEMBER)
//msvc compliant compilers use their the first 32 bits as offset (even in 64 bit mode)
union caster_union
{
@@ -37,6 +37,10 @@
boost::int32_t offset;
} caster;
caster.ptr_to_member = ptr_to_member;
+ //MSVC ABI can use up to 3 int32 to represent pointer to member data
+ //with virtual base classes, in those cases there is no simple to
+ //obtain the address of parent. So static assert to avoid runtime errors
+ BOOST_STATIC_ASSERT( sizeof(caster) == sizeof(boost::int32_t) );
return std::ptrdiff_t(caster.offset);
//This works with gcc, msvc, ac++, ibmcpp
#elif defined(__GNUC__) || defined(__HP_aCC) || defined(BOOST_INTEL) || \
@@ -84,8 +88,8 @@
} //namespace intrusive {
} //namespace boost {
-#ifdef BOOST_INTRUSIVE_MSVC_COMPLIANT_PTR_TO_MEMBER
-#undef BOOST_INTRUSIVE_MSVC_COMPLIANT_PTR_TO_MEMBER
+#ifdef BOOST_INTRUSIVE_MSVC_ABI_PTR_TO_MEMBER
+#undef BOOST_INTRUSIVE_MSVC_ABI_PTR_TO_MEMBER
#endif
#include <boost/intrusive/detail/config_end.hpp>
Modified: branches/release/boost/intrusive/detail/utilities.hpp
==============================================================================
--- branches/release/boost/intrusive/detail/utilities.hpp (original)
+++ branches/release/boost/intrusive/detail/utilities.hpp 2013-05-18 06:40:55 EDT (Sat, 18 May 2013)
@@ -28,6 +28,7 @@
#include <iterator>
#include <boost/cstdint.hpp>
#include <boost/static_assert.hpp>
+#include <boost/detail/no_exceptions_support.hpp>
namespace boost {
namespace intrusive {
@@ -131,6 +132,12 @@
void increment()
{ ++size_; }
+ void increase(SizeType n)
+ { size_ += n; }
+
+ void decrease(SizeType n)
+ { size_ -= n; }
+
SizeType size_;
};
@@ -151,6 +158,12 @@
void increment()
{}
+
+ void increase(SizeType)
+ {}
+
+ void decrease(SizeType)
+ {}
};
template<class KeyValueCompare, class Container>
@@ -692,19 +705,20 @@
{
char *init_buf = (char*)rawbuf;
std::size_t i = 0;
- try{
+ BOOST_TRY{
for(; i != N; ++i){
new(init_buf)T(init);
init_buf += sizeof(T);
}
}
- catch(...){
+ BOOST_CATCH(...){
while(i--){
init_buf -= sizeof(T);
((T*)init_buf)->~T();
}
- throw;
+ BOOST_RETHROW;
}
+ BOOST_CATCH_END
}
operator T* ()
Modified: branches/release/boost/intrusive/list.hpp
==============================================================================
--- branches/release/boost/intrusive/list.hpp (original)
+++ branches/release/boost/intrusive/list.hpp 2013-05-18 06:40:55 EDT (Sat, 18 May 2013)
@@ -645,7 +645,7 @@
}
else{
if(constant_time_size){
- this->priv_size_traits().set_size(this->priv_size_traits().get_size() - n);
+ this->priv_size_traits().decrease(n);
}
node_algorithms::unlink(b.pointed_node(), e.pointed_node());
return e.unconst();
@@ -886,11 +886,11 @@
void splice(const_iterator p, list_impl& x)
{
if(!x.empty()){
- size_traits &thist = this->priv_size_traits();
- size_traits &xt = x.priv_size_traits();
node_algorithms::transfer
(p.pointed_node(), x.begin().pointed_node(), x.end().pointed_node());
- thist.set_size(thist.get_size() + xt.get_size());
+ size_traits &thist = this->priv_size_traits();
+ size_traits &xt = x.priv_size_traits();
+ thist.increase(xt.get_size());
xt.set_size(size_type(0));
}
}
@@ -953,12 +953,12 @@
{
if(n){
if(constant_time_size){
- size_traits &thist = this->priv_size_traits();
- size_traits &xt = x.priv_size_traits();
BOOST_INTRUSIVE_INVARIANT_ASSERT(n == std::distance(f, e));
node_algorithms::transfer(p.pointed_node(), f.pointed_node(), e.pointed_node());
- thist.set_size(thist.get_size() + n);
- xt.set_size(xt.get_size() - n);
+ size_traits &thist = this->priv_size_traits();
+ size_traits &xt = x.priv_size_traits();
+ thist.increase(n);
+ xt.decrease(n);
}
else{
node_algorithms::transfer(p.pointed_node(), f.pointed_node(), e.pointed_node());
Modified: branches/release/boost/intrusive/options.hpp
==============================================================================
--- branches/release/boost/intrusive/options.hpp (original)
+++ branches/release/boost/intrusive/options.hpp 2013-05-18 06:40:55 EDT (Sat, 18 May 2013)
@@ -33,6 +33,8 @@
struct default_hook_tag{};
+#ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+
#define BOOST_INTRUSIVE_DEFAULT_HOOK_MARKER_DEFINITION(BOOST_INTRUSIVE_DEFAULT_HOOK_MARKER) \
struct BOOST_INTRUSIVE_DEFAULT_HOOK_MARKER : public default_hook_tag\
{\
@@ -51,6 +53,8 @@
#undef BOOST_INTRUSIVE_DEFAULT_HOOK_MARKER_DEFINITION
+#endif //BOOST_INTRUSIVE_DOXYGEN_INVOKED
+
template <class ValueTraits>
struct eval_value_traits
{
Modified: branches/release/boost/intrusive/pointer_plus_bits.hpp
==============================================================================
--- branches/release/boost/intrusive/pointer_plus_bits.hpp (original)
+++ branches/release/boost/intrusive/pointer_plus_bits.hpp 2013-05-18 06:40:55 EDT (Sat, 18 May 2013)
@@ -47,7 +47,11 @@
//!has_pointer_plus_bits<>::value is non-zero can make use of these
//!operations to embed the bits in the pointer.
template<class Pointer, std::size_t NumBits>
-struct pointer_plus_bits;
+struct pointer_plus_bits
+ #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+ {}
+ #endif
+;
//!This is the specialization to embed extra bits of information
//!in a raw pointer. The extra bits are stored in the lower bits of the pointer.
Modified: branches/release/boost/intrusive/slist.hpp
==============================================================================
--- branches/release/boost/intrusive/slist.hpp (original)
+++ branches/release/boost/intrusive/slist.hpp 2013-05-18 06:40:55 EDT (Sat, 18 May 2013)
@@ -819,8 +819,23 @@
template<class Iterator>
void insert_after(const_iterator prev_p, Iterator f, Iterator l)
{
- for (; f != l; ++f)
- prev_p = this->insert_after(prev_p, *f);
+ //Insert first nodes avoiding cache and size checks
+ size_type count = 0;
+ node_ptr prev_n(prev_p.pointed_node());
+ for (; f != l; ++f, ++count){
+ const node_ptr n = get_real_value_traits().to_node_ptr(*f);
+ if(safemode_or_autounlink)
+ BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::inited(n));
+ node_algorithms::link_after(prev_n, n);
+ prev_n = n;
+ }
+ //Now fix special cases if needed
+ if(cache_last && (this->get_last_node() == prev_p.pointed_node())){
+ this->set_last_node(prev_n);
+ }
+ if(constant_time_size){
+ this->priv_size_traits().increase(count);
+ }
}
//! <b>Requires</b>: value must be an lvalue and p must point to an element
@@ -932,7 +947,7 @@
}
node_algorithms::unlink_after(bfp, lp);
if(constant_time_size){
- this->priv_size_traits().set_size(this->priv_size_traits().get_size() - n);
+ this->priv_size_traits().decrease(n);
}
return l.unconst();
}
@@ -1209,7 +1224,7 @@
}
}
node_algorithms::transfer_after( prev_n, x.before_begin().pointed_node(), last_x_n);
- this->priv_size_traits().set_size(this->priv_size_traits().get_size() + x.priv_size_traits().get_size());
+ this->priv_size_traits().increase(x.priv_size_traits().get_size());
x.priv_size_traits().set_size(size_type(0));
if(l) *l = last_x;
}
@@ -1278,8 +1293,8 @@
this->priv_splice_after
(prev_pos.pointed_node(), x, before_f.pointed_node(), before_l.pointed_node());
if(constant_time_size){
- this->priv_size_traits().set_size(this->priv_size_traits().get_size() + n);
- x.priv_size_traits().set_size(x.priv_size_traits().get_size() - n);
+ this->priv_size_traits().increase(n);
+ x.priv_size_traits().decrease(n);
}
}
@@ -1834,7 +1849,7 @@
BOOST_INTRUSIVE_INVARIANT_ASSERT(size_type(std::distance(iterator(f, this), iterator(before_l, this)))+1 == n);
this->priv_incorporate_after(prev_pos.pointed_node(), f, before_l);
if(constant_time_size){
- this->priv_size_traits().set_size(this->priv_size_traits().get_size() + n);
+ this->priv_size_traits().increase(n);
}
}
}
Modified: branches/release/boost/intrusive/treap_algorithms.hpp
==============================================================================
--- branches/release/boost/intrusive/treap_algorithms.hpp (original)
+++ branches/release/boost/intrusive/treap_algorithms.hpp 2013-05-18 06:40:55 EDT (Sat, 18 May 2013)
@@ -389,7 +389,6 @@
{
rebalance_for_erasure(header, z, pcomp);
tree_algorithms::erase(header, z);
-// assert(check_invariant(header, pcomp));
return z;
}
Modified: branches/release/boost/move/core.hpp
==============================================================================
--- branches/release/boost/move/core.hpp (original)
+++ branches/release/boost/move/core.hpp 2013-05-18 06:40:55 EDT (Sat, 18 May 2013)
@@ -18,6 +18,21 @@
#include <boost/move/detail/config_begin.hpp>
+#ifdef BOOST_NO_CXX11_DELETED_FUNCTIONS
+ #define BOOST_MOVE_IMPL_NO_COPY_CTOR_OR_ASSIGN(TYPE) \
+ private:\
+ TYPE(TYPE &);\
+ TYPE& operator=(TYPE &);\
+ //
+#else
+ #define BOOST_MOVE_IMPL_NO_COPY_CTOR_OR_ASSIGN(TYPE) \
+ public:\
+ TYPE(TYPE const &) = delete;\
+ TYPE& operator=(TYPE const &) = delete;\
+ private:\
+ //
+#endif //BOOST_NO_CXX11_DELETED_FUNCTIONS
+
#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && !defined(BOOST_MOVE_DOXYGEN_INVOKED)
#include <boost/move/detail/meta_utils.hpp>
@@ -152,9 +167,7 @@
//
//////////////////////////////////////////////////////////////////////////////
#define BOOST_MOVABLE_BUT_NOT_COPYABLE(TYPE)\
- private:\
- TYPE(TYPE &);\
- TYPE& operator=(TYPE &);\
+ BOOST_MOVE_IMPL_NO_COPY_CTOR_OR_ASSIGN(TYPE)\
public:\
operator ::boost::rv<TYPE>&() \
{ return *static_cast< ::boost::rv<TYPE>* >(this); }\
@@ -210,11 +223,9 @@
//! and assignment. The user will need to write a move constructor/assignment as explained
//! in the documentation to fully write a movable but not copyable class.
#define BOOST_MOVABLE_BUT_NOT_COPYABLE(TYPE)\
+ BOOST_MOVE_IMPL_NO_COPY_CTOR_OR_ASSIGN(TYPE)\
public:\
typedef int boost_move_emulation_t;\
- private:\
- TYPE(const TYPE &);\
- TYPE& operator=(const TYPE &);\
//
//! This macro marks a type as copyable and movable.
@@ -228,6 +239,8 @@
//
#endif //#if !defined(BOOST_MOVE_DOXYGEN_INVOKED)
+ namespace boost {
+
//!This trait yields to a compile-time true boolean if T was marked as
//!BOOST_MOVABLE_BUT_NOT_COPYABLE or BOOST_COPYABLE_AND_MOVABLE and
//!rvalue references are not available on the platform. False otherwise.
@@ -237,6 +250,8 @@
static const bool value = false;
};
+ } //namespace boost{
+
//!This macro is used to achieve portable syntax in move
//!constructors and assignments for classes marked as
//!BOOST_COPYABLE_AND_MOVABLE or BOOST_MOVABLE_BUT_NOT_COPYABLE
@@ -299,7 +314,7 @@
//
#define BOOST_COPY_ASSIGN_REF_3_TEMPL_ARGS(TYPE, ARG1, ARG2, ARG3)\
- TYPE<ARG1, ARG2, ARG3>& \
+ const TYPE<ARG1, ARG2, ARG3>& \
//
#define BOOST_CATCH_CONST_RLVALUE(TYPE)\
Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk