summaryrefslogtreecommitdiff
path: root/boost/container/detail
diff options
context:
space:
mode:
Diffstat (limited to 'boost/container/detail')
-rw-r--r--boost/container/detail/adaptive_node_pool.hpp162
-rw-r--r--boost/container/detail/adaptive_node_pool_impl.hpp725
-rw-r--r--boost/container/detail/advanced_insert_int.hpp630
-rw-r--r--boost/container/detail/algorithms.hpp32
-rw-r--r--boost/container/detail/alloc_lib.h326
-rw-r--r--boost/container/detail/alloc_lib_auto_link.hpp20
-rw-r--r--boost/container/detail/allocation_type.hpp12
-rw-r--r--boost/container/detail/allocator_version_traits.hpp168
-rw-r--r--boost/container/detail/auto_link.hpp38
-rw-r--r--boost/container/detail/config_begin.hpp9
-rw-r--r--boost/container/detail/config_end.hpp6
-rw-r--r--boost/container/detail/destroyers.hpp141
-rw-r--r--boost/container/detail/flat_tree.hpp694
-rw-r--r--boost/container/detail/function_detector.hpp6
-rw-r--r--boost/container/detail/hash_table.hpp383
-rw-r--r--boost/container/detail/iterators.hpp385
-rw-r--r--boost/container/detail/math_functions.hpp12
-rw-r--r--boost/container/detail/memory_util.hpp25
-rw-r--r--boost/container/detail/mpl.hpp37
-rw-r--r--boost/container/detail/multiallocation_chain.hpp178
-rw-r--r--boost/container/detail/mutex.hpp284
-rw-r--r--boost/container/detail/node_alloc_holder.hpp236
-rw-r--r--boost/container/detail/node_pool.hpp156
-rw-r--r--boost/container/detail/node_pool_impl.hpp59
-rw-r--r--boost/container/detail/pair.hpp41
-rw-r--r--boost/container/detail/placement_new.hpp27
-rw-r--r--boost/container/detail/pool_common.hpp15
-rw-r--r--boost/container/detail/pool_common_alloc.hpp98
-rw-r--r--boost/container/detail/preprocessor.hpp113
-rw-r--r--boost/container/detail/singleton.hpp117
-rw-r--r--boost/container/detail/std_fwd.hpp59
-rw-r--r--boost/container/detail/stored_ref.hpp92
-rw-r--r--boost/container/detail/transform_iterator.hpp19
-rw-r--r--boost/container/detail/tree.hpp1066
-rw-r--r--boost/container/detail/type_traits.hpp39
-rw-r--r--boost/container/detail/utilities.hpp1173
-rw-r--r--boost/container/detail/value_init.hpp6
-rw-r--r--boost/container/detail/variadic_templates_tools.hpp7
-rw-r--r--boost/container/detail/version_type.hpp17
-rw-r--r--boost/container/detail/workaround.hpp46
40 files changed, 5641 insertions, 2018 deletions
diff --git a/boost/container/detail/adaptive_node_pool.hpp b/boost/container/detail/adaptive_node_pool.hpp
new file mode 100644
index 0000000000..4e7375412b
--- /dev/null
+++ b/boost/container/detail/adaptive_node_pool.hpp
@@ -0,0 +1,162 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2005-2013. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_CONTAINER_DETAIL_ADAPTIVE_NODE_POOL_HPP
+#define BOOST_CONTAINER_DETAIL_ADAPTIVE_NODE_POOL_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif
+
+#include <boost/container/detail/config_begin.hpp>
+#include <boost/container/detail/workaround.hpp>
+
+#include <boost/intrusive/set.hpp>
+#include <boost/aligned_storage.hpp>
+#include <boost/container/detail/alloc_lib_auto_link.hpp>
+#include <boost/container/detail/multiallocation_chain.hpp>
+#include <boost/container/detail/pool_common_alloc.hpp>
+#include <boost/container/detail/mutex.hpp>
+#include <boost/container/detail/adaptive_node_pool_impl.hpp>
+#include <boost/container/detail/multiallocation_chain.hpp>
+#include <cstddef>
+#include <cmath>
+#include <cassert>
+
+
+namespace boost {
+namespace container {
+namespace container_detail {
+
+template<bool AlignOnly>
+struct select_private_adaptive_node_pool_impl
+{
+ typedef boost::container::container_detail::
+ private_adaptive_node_pool_impl
+ < fake_segment_manager
+ , unsigned(AlignOnly)*::boost::container::adaptive_pool_flag::align_only
+ | ::boost::container::adaptive_pool_flag::size_ordered | ::boost::container::adaptive_pool_flag::address_ordered
+ > type;
+};
+
+//!Pooled memory allocator using an smart adaptive pool. Includes
+//!a reference count but the class does not delete itself, this is
+//!responsibility of user classes. Node size (NodeSize) and the number of
+//!nodes allocated per block (NodesPerBlock) are known at compile time.
+template< std::size_t NodeSize
+ , std::size_t NodesPerBlock
+ , std::size_t MaxFreeBlocks
+ , std::size_t OverheadPercent
+ >
+class private_adaptive_node_pool
+ : public select_private_adaptive_node_pool_impl<(OverheadPercent == 0)>::type
+{
+ typedef typename select_private_adaptive_node_pool_impl<OverheadPercent == 0>::type base_t;
+ //Non-copyable
+ private_adaptive_node_pool(const private_adaptive_node_pool &);
+ private_adaptive_node_pool &operator=(const private_adaptive_node_pool &);
+
+ public:
+ typedef typename base_t::multiallocation_chain multiallocation_chain;
+ static const std::size_t nodes_per_block = NodesPerBlock;
+
+ //!Constructor. Never throws
+ private_adaptive_node_pool()
+ : base_t(0
+ , NodeSize
+ , NodesPerBlock
+ , MaxFreeBlocks
+ , (unsigned char)OverheadPercent)
+ {}
+};
+
+//!Pooled memory allocator using adaptive pool. Includes
+//!a reference count but the class does not delete itself, this is
+//!responsibility of user classes. Node size (NodeSize) and the number of
+//!nodes allocated per block (NodesPerBlock) are known at compile time
+template< std::size_t NodeSize
+ , std::size_t NodesPerBlock
+ , std::size_t MaxFreeBlocks
+ , std::size_t OverheadPercent
+ >
+class shared_adaptive_node_pool
+ : public private_adaptive_node_pool
+ <NodeSize, NodesPerBlock, MaxFreeBlocks, OverheadPercent>
+{
+ private:
+ typedef private_adaptive_node_pool
+ <NodeSize, NodesPerBlock, MaxFreeBlocks, OverheadPercent> private_node_allocator_t;
+ public:
+ typedef typename private_node_allocator_t::multiallocation_chain multiallocation_chain;
+
+ //!Constructor. Never throws
+ shared_adaptive_node_pool()
+ : private_node_allocator_t(){}
+
+ //!Destructor. Deallocates all allocated blocks. Never throws
+ ~shared_adaptive_node_pool()
+ {}
+
+ //!Allocates array of count elements. Can throw std::bad_alloc
+ void *allocate_node()
+ {
+ //-----------------------
+ scoped_lock<default_mutex> guard(mutex_);
+ //-----------------------
+ return private_node_allocator_t::allocate_node();
+ }
+
+ //!Deallocates an array pointed by ptr. Never throws
+ void deallocate_node(void *ptr)
+ {
+ //-----------------------
+ scoped_lock<default_mutex> guard(mutex_);
+ //-----------------------
+ private_node_allocator_t::deallocate_node(ptr);
+ }
+
+ //!Allocates a singly linked list of n nodes ending in null pointer.
+ //!can throw std::bad_alloc
+ void allocate_nodes(const std::size_t n, multiallocation_chain &chain)
+ {
+ //-----------------------
+ scoped_lock<default_mutex> guard(mutex_);
+ //-----------------------
+ return private_node_allocator_t::allocate_nodes(n, chain);
+ }
+
+ void deallocate_nodes(multiallocation_chain &chain)
+ {
+ //-----------------------
+ scoped_lock<default_mutex> guard(mutex_);
+ //-----------------------
+ private_node_allocator_t::deallocate_nodes(chain);
+ }
+
+ //!Deallocates all the free blocks of memory. Never throws
+ void deallocate_free_blocks()
+ {
+ //-----------------------
+ scoped_lock<default_mutex> guard(mutex_);
+ //-----------------------
+ private_node_allocator_t::deallocate_free_blocks();
+ }
+
+ private:
+ default_mutex mutex_;
+};
+
+} //namespace container_detail {
+} //namespace container {
+} //namespace boost {
+
+#include <boost/container/detail/config_end.hpp>
+
+#endif //#ifndef BOOST_CONTAINER_DETAIL_ADAPTIVE_NODE_POOL_HPP
diff --git a/boost/container/detail/adaptive_node_pool_impl.hpp b/boost/container/detail/adaptive_node_pool_impl.hpp
index afba6b5f1b..dc1a7f102e 100644
--- a/boost/container/detail/adaptive_node_pool_impl.hpp
+++ b/boost/container/detail/adaptive_node_pool_impl.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
+// (C) Copyright Ion Gaztanaga 2005-2013. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
@@ -11,26 +11,40 @@
#ifndef BOOST_CONTAINER_DETAIL_ADAPTIVE_NODE_POOL_IMPL_HPP
#define BOOST_CONTAINER_DETAIL_ADAPTIVE_NODE_POOL_IMPL_HPP
-#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#if defined(_MSC_VER)
# pragma once
#endif
-#include "config_begin.hpp"
-#include <boost/container/container_fwd.hpp>
+#include <boost/container/detail/config_begin.hpp>
#include <boost/container/detail/workaround.hpp>
+
+#include <boost/container/container_fwd.hpp>
#include <boost/container/detail/utilities.hpp>
#include <boost/intrusive/pointer_traits.hpp>
#include <boost/intrusive/set.hpp>
+#include <boost/intrusive/list.hpp>
#include <boost/intrusive/slist.hpp>
#include <boost/container/detail/type_traits.hpp>
#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/core/no_exceptions_support.hpp>
#include <cstddef>
namespace boost {
namespace container {
+
+namespace adaptive_pool_flag {
+
+static const unsigned int none = 0u;
+static const unsigned int align_only = 1u << 0u;
+static const unsigned int size_ordered = 1u << 1u;
+static const unsigned int address_ordered = 1u << 2u;
+
+} //namespace adaptive_pool_flag{
+
namespace container_detail {
template<class size_type>
@@ -42,42 +56,160 @@ struct hdr_offset_holder_t
size_type hdr_offset;
};
+template<class SizeType, unsigned int Flags>
+struct less_func;
+
+template<class SizeType>
+struct less_func<SizeType, adaptive_pool_flag::none>
+{
+ static bool less(SizeType, SizeType, const void *, const void *)
+ { return true; }
+};
+
+template<class SizeType>
+struct less_func<SizeType, adaptive_pool_flag::size_ordered>
+{
+ static bool less(SizeType ls, SizeType rs, const void *, const void *)
+ { return ls < rs; }
+};
+
+template<class SizeType>
+struct less_func<SizeType, adaptive_pool_flag::address_ordered>
+{
+ static bool less(SizeType, SizeType, const void *la, const void *ra)
+ { return &la < &ra; }
+};
+
+template<class SizeType>
+struct less_func<SizeType, adaptive_pool_flag::size_ordered | adaptive_pool_flag::address_ordered>
+{
+ static bool less(SizeType ls, SizeType rs, const void *la, const void *ra)
+ { return (ls < rs) || ((ls == rs) && (la < ra)); }
+};
+
+template<class VoidPointer, class SizeType, bool ordered>
+struct block_container_traits
+{
+ typedef typename bi::make_set_base_hook
+ < bi::void_pointer<VoidPointer>
+ , bi::optimize_size<true>
+ , bi::link_mode<bi::normal_link> >::type hook_t;
+
+ template<class T>
+ struct container
+ {
+ typedef typename bi::make_multiset
+ <T, bi::base_hook<hook_t>, bi::size_type<SizeType> >::type type;
+ };
+
+ template<class Container>
+ static void reinsert_was_used(Container &container, typename Container::reference v, bool)
+ {
+ typedef typename Container::const_iterator const_block_iterator;
+ const const_block_iterator this_block
+ (Container::s_iterator_to(const_cast<typename Container::const_reference>(v)));
+ const_block_iterator next_block(this_block);
+ if(++next_block != container.cend()){
+ if(this_block->free_nodes.size() > next_block->free_nodes.size()){
+ container.erase(this_block);
+ container.insert(v);
+ }
+ }
+ }
+
+ template<class Container>
+ static void insert_was_empty(Container &container, typename Container::value_type &v, bool)
+ {
+ container.insert(v);
+ }
+
+ template<class Container>
+ static void erase_first(Container &container)
+ {
+ container.erase(container.cbegin());
+ }
+
+ template<class Container>
+ static void erase_last(Container &container)
+ {
+ container.erase(--container.cend());
+ }
+};
+
template<class VoidPointer, class SizeType>
+struct block_container_traits<VoidPointer, SizeType, false>
+{
+ typedef typename bi::make_list_base_hook
+ < bi::void_pointer<VoidPointer>
+ , bi::link_mode<bi::normal_link> >::type hook_t;
+
+ template<class T>
+ struct container
+ {
+ typedef typename bi::make_list
+ <T, bi::base_hook<hook_t>, bi::size_type<SizeType>, bi::constant_time_size<false> >::type type;
+ };
+
+ template<class Container>
+ static void reinsert_was_used(Container &container, typename Container::value_type &v, bool is_full)
+ {
+ if(is_full){
+ container.erase(Container::s_iterator_to(v));
+ container.push_back(v);
+ }
+ }
+
+ template<class Container>
+ static void insert_was_empty(Container &container, typename Container::value_type &v, bool is_full)
+ {
+ if(is_full){
+ container.push_back(v);
+ }
+ else{
+ container.push_front(v);
+ }
+ }
+
+ template<class Container>
+ static void erase_first(Container &container)
+ {
+ container.pop_front();
+ }
+
+ template<class Container>
+ static void erase_last(Container &container)
+ {
+ container.pop_back();
+ }
+};
+
+template<class MultiallocationChain, class VoidPointer, class SizeType, unsigned int Flags>
struct adaptive_pool_types
{
typedef VoidPointer void_pointer;
- typedef typename bi::make_set_base_hook
- < bi::void_pointer<void_pointer>
- , bi::optimize_size<true>
- , bi::constant_time_size<false>
- , bi::link_mode<bi::normal_link> >::type multiset_hook_t;
-
+ static const bool ordered = (Flags & (adaptive_pool_flag::size_ordered | adaptive_pool_flag::address_ordered)) != 0;
+ typedef block_container_traits<VoidPointer, SizeType, ordered> block_container_traits_t;
+ typedef typename block_container_traits_t::hook_t hook_t;
typedef hdr_offset_holder_t<SizeType> hdr_offset_holder;
+ static const unsigned int order_flags = Flags & (adaptive_pool_flag::size_ordered | adaptive_pool_flag::address_ordered);
+ typedef MultiallocationChain free_nodes_t;
struct block_info_t
- :
- public hdr_offset_holder,
- public multiset_hook_t
+ : public hdr_offset_holder,
+ public hook_t
{
- typedef typename node_slist<void_pointer>::node_slist_t free_nodes_t;
//An intrusive list of free node from this block
free_nodes_t free_nodes;
friend bool operator <(const block_info_t &l, const block_info_t &r)
{
-// { return l.free_nodes.size() < r.free_nodes.size(); }
- //Let's order blocks first by free nodes and then by address
- //so that highest address fully free blocks are deallocated.
- //This improves returning memory to the OS (trimming).
- const bool is_less = l.free_nodes.size() < r.free_nodes.size();
- const bool is_equal = l.free_nodes.size() == r.free_nodes.size();
- return is_less || (is_equal && (&l < &r));
+ return less_func<SizeType, order_flags>::
+ less(l.free_nodes.size(), r.free_nodes.size(), &l , &r);
}
friend bool operator ==(const block_info_t &l, const block_info_t &r)
{ return &l == &r; }
};
- typedef typename bi::make_multiset
- <block_info_t, bi::base_hook<multiset_hook_t> >::type block_multiset_t;
+ typedef typename block_container_traits_t:: template container<block_info_t>::type block_container_t;
};
template<class size_type>
@@ -113,9 +245,9 @@ inline void calculate_num_subblocks
, size_type &num_subblocks, size_type &real_num_node, size_type overhead_percent
, size_type hdr_size, size_type hdr_offset_size, size_type payload_per_allocation)
{
+ const size_type hdr_subblock_elements = (alignment - hdr_size - payload_per_allocation)/real_node_size;
size_type elements_per_subblock = (alignment - hdr_offset_size)/real_node_size;
size_type possible_num_subblock = (elements_per_block - 1)/elements_per_subblock + 1;
- size_type hdr_subblock_elements = (alignment - hdr_size - payload_per_allocation)/real_node_size;
while(((possible_num_subblock-1)*elements_per_subblock + hdr_subblock_elements) < elements_per_block){
++possible_num_subblock;
}
@@ -135,7 +267,7 @@ inline void calculate_num_subblocks
real_num_node = (possible_num_subblock-1)*elements_per_subblock + hdr_subblock_elements;
}
-template<class SegmentManagerBase, bool AlignOnly = false>
+template<class SegmentManagerBase, unsigned int Flags>
class private_adaptive_node_pool_impl
{
//Non-copyable
@@ -147,27 +279,42 @@ class private_adaptive_node_pool_impl
typedef typename SegmentManagerBase::void_pointer void_pointer;
static const typename SegmentManagerBase::
size_type PayloadPerAllocation = SegmentManagerBase::PayloadPerAllocation;
+ //Flags
+ //align_only
+ static const bool AlignOnly = (Flags & adaptive_pool_flag::align_only) != 0;
typedef bool_<AlignOnly> IsAlignOnly;
typedef true_ AlignOnlyTrue;
typedef false_ AlignOnlyFalse;
+ //size_ordered
+ static const bool SizeOrdered = (Flags & adaptive_pool_flag::size_ordered) != 0;
+ typedef bool_<SizeOrdered> IsSizeOrdered;
+ typedef true_ SizeOrderedTrue;
+ typedef false_ SizeOrderedFalse;
+ //address_ordered
+ static const bool AddressOrdered = (Flags & adaptive_pool_flag::address_ordered) != 0;
+ typedef bool_<AddressOrdered> IsAddressOrdered;
+ typedef true_ AddressOrderedTrue;
+ typedef false_ AddressOrderedFalse;
public:
- typedef typename node_slist<void_pointer>::node_t node_t;
- typedef typename node_slist<void_pointer>::node_slist_t free_nodes_t;
- typedef typename SegmentManagerBase::multiallocation_chain multiallocation_chain;
- typedef typename SegmentManagerBase::size_type size_type;
+ typedef typename SegmentManagerBase::multiallocation_chain multiallocation_chain;
+ typedef typename SegmentManagerBase::size_type size_type;
private:
- typedef typename adaptive_pool_types<void_pointer, size_type>::block_info_t block_info_t;
- typedef typename adaptive_pool_types<void_pointer, size_type>::block_multiset_t block_multiset_t;
- typedef typename block_multiset_t::iterator block_iterator;
- typedef typename adaptive_pool_types<void_pointer, size_type>::hdr_offset_holder hdr_offset_holder;
-
- static const size_type MaxAlign = alignment_of<node_t>::value;
+ typedef adaptive_pool_types
+ <multiallocation_chain, void_pointer, size_type, Flags> adaptive_pool_types_t;
+ typedef typename adaptive_pool_types_t::free_nodes_t free_nodes_t;
+ typedef typename adaptive_pool_types_t::block_info_t block_info_t;
+ typedef typename adaptive_pool_types_t::block_container_t block_container_t;
+ typedef typename adaptive_pool_types_t::block_container_traits_t block_container_traits_t;
+ typedef typename block_container_t::iterator block_iterator;
+ typedef typename block_container_t::const_iterator const_block_iterator;
+ typedef typename adaptive_pool_types_t::hdr_offset_holder hdr_offset_holder;
+
+ static const size_type MaxAlign = alignment_of<void_pointer>::value;
static const size_type HdrSize = ((sizeof(block_info_t)-1)/MaxAlign+1)*MaxAlign;
static const size_type HdrOffsetSize = ((sizeof(hdr_offset_holder)-1)/MaxAlign+1)*MaxAlign;
-
public:
//!Segment manager typedef
typedef SegmentManagerBase segment_manager_base_type;
@@ -181,7 +328,7 @@ class private_adaptive_node_pool_impl
, unsigned char overhead_percent
)
: m_max_free_blocks(max_free_blocks)
- , m_real_node_size(lcm(node_size, size_type(alignment_of<node_t>::value)))
+ , m_real_node_size(lcm(node_size, size_type(alignment_of<void_pointer>::value)))
//Round the size to a power of two value.
//This is the total memory size (including payload) that we want to
//allocate from the general-purpose allocator
@@ -195,7 +342,7 @@ class private_adaptive_node_pool_impl
, m_real_num_node(AlignOnly ? (m_real_block_alignment - PayloadPerAllocation - HdrSize)/m_real_node_size : 0)
//General purpose allocator
, mp_segment_mngr_base(segment_mngr_base)
- , m_block_multiset()
+ , m_block_container()
, m_totally_free_blocks(0)
{
if(!AlignOnly){
@@ -214,7 +361,7 @@ class private_adaptive_node_pool_impl
//!Destructor. Deallocates all allocated blocks. Never throws
~private_adaptive_node_pool_impl()
- { priv_clear(); }
+ { this->priv_clear(); }
size_type get_real_num_node() const
{ return m_real_num_node; }
@@ -226,84 +373,157 @@ class private_adaptive_node_pool_impl
//!Allocates array of count elements. Can throw
void *allocate_node()
{
- priv_invariants();
+ this->priv_invariants();
//If there are no free nodes we allocate a new block
- if (m_block_multiset.empty()){
- priv_alloc_block(1);
+ if(!m_block_container.empty()){
+ //We take the first free node the multiset can't be empty
+ free_nodes_t &free_nodes = m_block_container.begin()->free_nodes;
+ BOOST_ASSERT(!free_nodes.empty());
+ const size_type free_nodes_count = free_nodes.size();
+ void *first_node = container_detail::to_raw_pointer(free_nodes.pop_front());
+ if(free_nodes.empty()){
+ block_container_traits_t::erase_first(m_block_container);
+ }
+ m_totally_free_blocks -= static_cast<size_type>(free_nodes_count == m_real_num_node);
+ this->priv_invariants();
+ return first_node;
+ }
+ else{
+ multiallocation_chain chain;
+ this->priv_append_from_new_blocks(1, chain, IsAlignOnly());
+ return container_detail::to_raw_pointer(chain.pop_front());
}
- //We take the first free node the multiset can't be empty
- return priv_take_first_node();
}
//!Deallocates an array pointed by ptr. Never throws
void deallocate_node(void *pElem)
{
- multiallocation_chain chain;
- chain.push_front(void_pointer(pElem));
- this->priv_reinsert_nodes_in_block(chain, 1);
- //Update free block count<
- if(m_totally_free_blocks > m_max_free_blocks){
- this->priv_deallocate_free_blocks(m_max_free_blocks);
- }
- priv_invariants();
+ this->priv_invariants();
+ block_info_t &block_info = *this->priv_block_from_node(pElem);
+ BOOST_ASSERT(block_info.free_nodes.size() < m_real_num_node);
+
+ //We put the node at the beginning of the free node list
+ block_info.free_nodes.push_back(void_pointer(pElem));
+
+ //The loop reinserts all blocks except the last one
+ this->priv_reinsert_block(block_info, block_info.free_nodes.size() == 1);
+ this->priv_deallocate_free_blocks(m_max_free_blocks);
+ this->priv_invariants();
}
//!Allocates n nodes.
//!Can throw
- multiallocation_chain allocate_nodes(const size_type n)
+ void allocate_nodes(const size_type n, multiallocation_chain &chain)
{
- multiallocation_chain chain;
size_type i = 0;
- try{
- priv_invariants();
+ BOOST_TRY{
+ this->priv_invariants();
while(i != n){
//If there are no free nodes we allocate all needed blocks
- if (m_block_multiset.empty()){
- priv_alloc_block(((n - i) - 1)/m_real_num_node + 1);
+ if (m_block_container.empty()){
+ this->priv_append_from_new_blocks(n - i, chain, IsAlignOnly());
+ BOOST_ASSERT(m_block_container.empty() || (++m_block_container.cbegin() == m_block_container.cend()));
+ BOOST_ASSERT(chain.size() == n);
+ break;
}
- free_nodes_t &free_nodes = m_block_multiset.begin()->free_nodes;
+ free_nodes_t &free_nodes = m_block_container.begin()->free_nodes;
const size_type free_nodes_count_before = free_nodes.size();
- if(free_nodes_count_before == m_real_num_node){
- --m_totally_free_blocks;
- }
- const size_type num_elems = ((n-i) < free_nodes_count_before) ? (n-i) : free_nodes_count_before;
- for(size_type j = 0; j != num_elems; ++j){
- void *new_node = &free_nodes.front();
- free_nodes.pop_front();
- chain.push_back(new_node);
+ m_totally_free_blocks -= static_cast<size_type>(free_nodes_count_before == m_real_num_node);
+ const size_type num_left = n-i;
+ const size_type num_elems = (num_left < free_nodes_count_before) ? num_left : free_nodes_count_before;
+ typedef typename free_nodes_t::iterator free_nodes_iterator;
+
+ if(num_left < free_nodes_count_before){
+ const free_nodes_iterator it_bbeg(free_nodes.before_begin());
+ free_nodes_iterator it_bend(it_bbeg);
+ for(size_type j = 0; j != num_elems; ++j){
+ ++it_bend;
+ }
+ free_nodes_iterator it_end = it_bend; ++it_end;
+ free_nodes_iterator it_beg = it_bbeg; ++it_beg;
+ free_nodes.erase_after(it_bbeg, it_end, num_elems);
+ chain.incorporate_after(chain.last(), &*it_beg, &*it_bend, num_elems);
+ //chain.splice_after(chain.last(), free_nodes, it_bbeg, it_bend, num_elems);
+ BOOST_ASSERT(!free_nodes.empty());
}
-
- if(free_nodes.empty()){
- m_block_multiset.erase(m_block_multiset.begin());
+ else{
+ const free_nodes_iterator it_beg(free_nodes.begin()), it_bend(free_nodes.last());
+ free_nodes.clear();
+ chain.incorporate_after(chain.last(), &*it_beg, &*it_bend, num_elems);
+ block_container_traits_t::erase_first(m_block_container);
}
i += num_elems;
}
}
- catch(...){
- this->deallocate_nodes(boost::move(chain));
- throw;
+ BOOST_CATCH(...){
+ this->deallocate_nodes(chain);
+ BOOST_RETHROW
}
- priv_invariants();
- return boost::move(chain);
+ BOOST_CATCH_END
+ this->priv_invariants();
}
//!Deallocates a linked list of nodes. Never throws
- void deallocate_nodes(multiallocation_chain nodes)
+ void deallocate_nodes(multiallocation_chain &nodes)
{
- this->priv_reinsert_nodes_in_block(nodes, nodes.size());
- if(m_totally_free_blocks > m_max_free_blocks){
+ this->priv_invariants();
+ //To take advantage of node locality, wait until two
+ //nodes belong to different blocks. Only then reinsert
+ //the block of the first node in the block tree.
+ //Cache of the previous block
+ block_info_t *prev_block_info = 0;
+
+ //If block was empty before this call, it's not already
+ //inserted in the block tree.
+ bool prev_block_was_empty = false;
+ typedef typename free_nodes_t::iterator free_nodes_iterator;
+ {
+ const free_nodes_iterator itbb(nodes.before_begin()), ite(nodes.end());
+ free_nodes_iterator itf(nodes.begin()), itbf(itbb);
+ size_type splice_node_count = size_type(-1);
+ while(itf != ite){
+ void *pElem = container_detail::to_raw_pointer(container_detail::iterator_to_pointer(itf));
+ block_info_t &block_info = *this->priv_block_from_node(pElem);
+ BOOST_ASSERT(block_info.free_nodes.size() < m_real_num_node);
+ ++splice_node_count;
+
+ //If block change is detected calculate the cached block position in the tree
+ if(&block_info != prev_block_info){
+ if(prev_block_info){ //Make sure we skip the initial "dummy" cache
+ free_nodes_iterator it(itbb); ++it;
+ nodes.erase_after(itbb, itf, splice_node_count);
+ prev_block_info->free_nodes.incorporate_after(prev_block_info->free_nodes.last(), &*it, &*itbf, splice_node_count);
+ this->priv_reinsert_block(*prev_block_info, prev_block_was_empty);
+ splice_node_count = 0;
+ }
+ //Update cache with new data
+ prev_block_was_empty = block_info.free_nodes.empty();
+ prev_block_info = &block_info;
+ }
+ itbf = itf;
+ ++itf;
+ }
+ }
+ if(prev_block_info){
+ //The loop reinserts all blocks except the last one
+ const free_nodes_iterator itfirst(nodes.begin()), itlast(nodes.last());
+ const size_type splice_node_count = nodes.size();
+ nodes.clear();
+ prev_block_info->free_nodes.incorporate_after(prev_block_info->free_nodes.last(), &*itfirst, &*itlast, splice_node_count);
+ this->priv_reinsert_block(*prev_block_info, prev_block_was_empty);
+ this->priv_invariants();
this->priv_deallocate_free_blocks(m_max_free_blocks);
}
}
void deallocate_free_blocks()
- { this->priv_deallocate_free_blocks(0); }
+ { this->priv_deallocate_free_blocks(0); }
size_type num_free_nodes()
{
- typedef typename block_multiset_t::const_iterator citerator;
+ typedef typename block_container_t::const_iterator citerator;
size_type count = 0;
- citerator it (m_block_multiset.begin()), itend(m_block_multiset.end());
+ citerator it (m_block_container.begin()), itend(m_block_container.end());
for(; it != itend; ++it){
count += it->free_nodes.size();
}
@@ -318,7 +538,7 @@ class private_adaptive_node_pool_impl
BOOST_ASSERT(m_real_num_node == other.m_real_num_node);
std::swap(mp_segment_mngr_base, other.mp_segment_mngr_base);
std::swap(m_totally_free_blocks, other.m_totally_free_blocks);
- m_block_multiset.swap(other.m_block_multiset);
+ m_block_container.swap(other.m_block_container);
}
//Deprecated, use deallocate_free_blocks
@@ -326,84 +546,54 @@ class private_adaptive_node_pool_impl
{ this->priv_deallocate_free_blocks(0); }
private:
+
void priv_deallocate_free_blocks(size_type max_free_blocks)
+ { //Trampoline function to ease inlining
+ if(m_totally_free_blocks > max_free_blocks){
+ this->priv_deallocate_free_blocks_impl(max_free_blocks);
+ }
+ }
+
+ void priv_deallocate_free_blocks_impl(size_type max_free_blocks)
{
- priv_invariants();
+ this->priv_invariants();
//Now check if we've reached the free nodes limit
//and check if we have free blocks. If so, deallocate as much
//as we can to stay below the limit
- for( block_iterator itend = m_block_multiset.end()
- ; m_totally_free_blocks > max_free_blocks
- ; --m_totally_free_blocks
- ){
- BOOST_ASSERT(!m_block_multiset.empty());
- block_iterator it = itend;
+ multiallocation_chain chain;
+ {
+ const const_block_iterator itend = m_block_container.cend();
+ const_block_iterator it = itend;
--it;
- BOOST_ASSERT(it->free_nodes.size() == m_real_num_node);
- m_block_multiset.erase_and_dispose(it, block_destroyer(this));
- }
- }
-
- void priv_reinsert_nodes_in_block(multiallocation_chain &chain, size_type n)
- {
- block_iterator block_it(m_block_multiset.end());
- while(n--){
- void *pElem = container_detail::to_raw_pointer(chain.front());
- chain.pop_front();
- priv_invariants();
- block_info_t *block_info = this->priv_block_from_node(pElem);
- BOOST_ASSERT(block_info->free_nodes.size() < m_real_num_node);
- //We put the node at the beginning of the free node list
- node_t * to_deallocate = static_cast<node_t*>(pElem);
- block_info->free_nodes.push_front(*to_deallocate);
-
- block_iterator this_block(block_multiset_t::s_iterator_to(*block_info));
- block_iterator next_block(this_block);
- ++next_block;
-
- //Cache the free nodes from the block
- size_type this_block_free_nodes = this_block->free_nodes.size();
-
- if(this_block_free_nodes == 1){
- m_block_multiset.insert(m_block_multiset.begin(), *block_info);
+ size_type totally_free_blocks = m_totally_free_blocks;
+
+ for( ; totally_free_blocks > max_free_blocks; --totally_free_blocks){
+ BOOST_ASSERT(it->free_nodes.size() == m_real_num_node);
+ void *addr = priv_first_subblock_from_block(const_cast<block_info_t*>(&*it));
+ --it;
+ block_container_traits_t::erase_last(m_block_container);
+ chain.push_front(void_pointer(addr));
}
- else{
- block_iterator next_block(this_block);
- ++next_block;
- if(next_block != block_it){
- size_type next_free_nodes = next_block->free_nodes.size();
- if(this_block_free_nodes > next_free_nodes){
- //Now move the block to the new position
- m_block_multiset.erase(this_block);
- m_block_multiset.insert(*block_info);
- }
- }
- }
- //Update free block count
- if(this_block_free_nodes == m_real_num_node){
- ++m_totally_free_blocks;
- }
- priv_invariants();
+ BOOST_ASSERT((m_totally_free_blocks - max_free_blocks) == chain.size());
+ m_totally_free_blocks = max_free_blocks;
}
+ this->mp_segment_mngr_base->deallocate_many(chain);
}
- node_t *priv_take_first_node()
+ void priv_reinsert_block(block_info_t &prev_block_info, const bool prev_block_was_empty)
{
- BOOST_ASSERT(m_block_multiset.begin() != m_block_multiset.end());
- //We take the first free node the multiset can't be empty
- free_nodes_t &free_nodes = m_block_multiset.begin()->free_nodes;
- node_t *first_node = &free_nodes.front();
- const size_type free_nodes_count = free_nodes.size();
- BOOST_ASSERT(0 != free_nodes_count);
- free_nodes.pop_front();
- if(free_nodes_count == 1){
- m_block_multiset.erase(m_block_multiset.begin());
+ //Cache the free nodes from the block
+ const size_type this_block_free_nodes = prev_block_info.free_nodes.size();
+ const bool is_full = this_block_free_nodes == m_real_num_node;
+
+ //Update free block count
+ m_totally_free_blocks += static_cast<size_type>(is_full);
+ if(prev_block_was_empty){
+ block_container_traits_t::insert_was_empty(m_block_container, prev_block_info, is_full);
}
- else if(free_nodes_count == m_real_num_node){
- --m_totally_free_blocks;
+ else{
+ block_container_traits_t::reinsert_was_used(m_block_container, prev_block_info, is_full);
}
- priv_invariants();
- return first_node;
}
class block_destroyer;
@@ -412,33 +602,31 @@ class private_adaptive_node_pool_impl
class block_destroyer
{
public:
- block_destroyer(const this_type *impl)
- : mp_impl(impl)
+ block_destroyer(const this_type *impl, multiallocation_chain &chain)
+ : mp_impl(impl), m_chain(chain)
{}
- void operator()(typename block_multiset_t::pointer to_deallocate)
+ void operator()(typename block_container_t::pointer to_deallocate)
{ return this->do_destroy(to_deallocate, IsAlignOnly()); }
private:
- void do_destroy(typename block_multiset_t::pointer to_deallocate, AlignOnlyTrue)
+ void do_destroy(typename block_container_t::pointer to_deallocate, AlignOnlyTrue)
{
- size_type free_nodes = to_deallocate->free_nodes.size();
- (void)free_nodes;
- BOOST_ASSERT(free_nodes == mp_impl->m_real_num_node);
- mp_impl->mp_segment_mngr_base->deallocate(to_deallocate);
+ BOOST_ASSERT(to_deallocate->free_nodes.size() == mp_impl->m_real_num_node);
+ m_chain.push_back(to_deallocate);
}
- void do_destroy(typename block_multiset_t::pointer to_deallocate, AlignOnlyFalse)
+ void do_destroy(typename block_container_t::pointer to_deallocate, AlignOnlyFalse)
{
- size_type free_nodes = to_deallocate->free_nodes.size();
- (void)free_nodes;
- BOOST_ASSERT(free_nodes == mp_impl->m_real_num_node);
+ BOOST_ASSERT(to_deallocate->free_nodes.size() == mp_impl->m_real_num_node);
BOOST_ASSERT(0 == to_deallocate->hdr_offset);
- hdr_offset_holder *hdr_off_holder = mp_impl->priv_first_subblock_from_block(container_detail::to_raw_pointer(to_deallocate));
- mp_impl->mp_segment_mngr_base->deallocate(hdr_off_holder);
+ hdr_offset_holder *hdr_off_holder =
+ mp_impl->priv_first_subblock_from_block(container_detail::to_raw_pointer(to_deallocate));
+ m_chain.push_back(hdr_off_holder);
}
const this_type *mp_impl;
+ multiallocation_chain &m_chain;
};
//This macro will activate invariant checking. Slow, but helpful for debugging the code.
@@ -447,44 +635,45 @@ class private_adaptive_node_pool_impl
#ifdef BOOST_CONTAINER_ADAPTIVE_NODE_POOL_CHECK_INVARIANTS
#undef BOOST_CONTAINER_ADAPTIVE_NODE_POOL_CHECK_INVARIANTS
{
- //We iterate through the block tree to free the memory
- block_iterator it(m_block_multiset.begin()),
- itend(m_block_multiset.end()), to_deallocate;
- if(it != itend){
- for(++it; it != itend; ++it){
- block_iterator prev(it);
- --prev;
- size_type sp = prev->free_nodes.size(),
- si = it->free_nodes.size();
- BOOST_ASSERT(sp <= si);
- (void)sp; (void)si;
+ const const_block_iterator itend(m_block_container.end());
+
+ { //We iterate through the block tree to free the memory
+ const_block_iterator it(m_block_container.begin());
+
+ if(it != itend){
+ for(++it; it != itend; ++it){
+ const_block_iterator prev(it);
+ --prev;
+ BOOST_ASSERT(*prev < *it);
+ (void)prev; (void)it;
+ }
}
}
- //Check that the total free nodes are correct
- it = m_block_multiset.begin();
- itend = m_block_multiset.end();
- size_type total_free_nodes = 0;
- for(; it != itend; ++it){
- total_free_nodes += it->free_nodes.size();
+ { //Check that the total free nodes are correct
+ const_block_iterator it(m_block_container.cbegin());
+ size_type total_free_nodes = 0;
+ for(; it != itend; ++it){
+ total_free_nodes += it->free_nodes.size();
+ }
+ BOOST_ASSERT(total_free_nodes >= m_totally_free_blocks*m_real_num_node);
}
- BOOST_ASSERT(total_free_nodes >= m_totally_free_blocks*m_real_num_node);
-
- //Check that the total totally free blocks are correct
- it = m_block_multiset.begin();
- itend = m_block_multiset.end();
- total_free = 0;
- for(; it != itend; ++it){
- total_free += it->free_nodes.size() == m_real_num_node;
+ { //Check that the total totally free blocks are correct
+ BOOST_ASSERT(m_block_container.size() >= m_totally_free_blocks);
+ const_block_iterator it = m_block_container.cend();
+ size_type total_free_blocks = m_totally_free_blocks;
+ while(total_free_blocks--){
+ BOOST_ASSERT((--it)->free_nodes.size() == m_real_num_node);
+ }
}
- BOOST_ASSERT(total_free >= m_totally_free_blocks);
if(!AlignOnly){
//Check that header offsets are correct
- it = m_block_multiset.begin();
+ const_block_iterator it = m_block_container.begin();
for(; it != itend; ++it){
- hdr_offset_holder *hdr_off_holder = priv_first_subblock_from_block(&*it);
+ hdr_offset_holder *hdr_off_holder = this->priv_first_subblock_from_block(const_cast<block_info_t *>(&*it));
for(size_type i = 0, max = m_num_subblocks; i < max; ++i){
- BOOST_ASSERT(hdr_off_holder->hdr_offset == size_type(reinterpret_cast<char*>(&*it)- reinterpret_cast<char*>(hdr_off_holder)));
+ const size_type offset = reinterpret_cast<char*>(const_cast<block_info_t *>(&*it)) - reinterpret_cast<char*>(hdr_off_holder);
+ BOOST_ASSERT(hdr_off_holder->hdr_offset == offset);
BOOST_ASSERT(0 == ((size_type)hdr_off_holder & (m_real_block_alignment - 1)));
BOOST_ASSERT(0 == (hdr_off_holder->hdr_offset & (m_real_block_alignment - 1)));
hdr_off_holder = reinterpret_cast<hdr_offset_holder *>(reinterpret_cast<char*>(hdr_off_holder) + m_real_block_alignment);
@@ -500,19 +689,21 @@ class private_adaptive_node_pool_impl
void priv_clear()
{
#ifndef NDEBUG
- block_iterator it = m_block_multiset.begin();
- block_iterator itend = m_block_multiset.end();
- size_type num_free_nodes = 0;
+ block_iterator it = m_block_container.begin();
+ block_iterator itend = m_block_container.end();
+ size_type n_free_nodes = 0;
for(; it != itend; ++it){
//Check for memory leak
BOOST_ASSERT(it->free_nodes.size() == m_real_num_node);
- ++num_free_nodes;
+ ++n_free_nodes;
}
- BOOST_ASSERT(num_free_nodes == m_totally_free_blocks);
+ BOOST_ASSERT(n_free_nodes == m_totally_free_blocks);
#endif
//Check for memory leaks
- priv_invariants();
- m_block_multiset.clear_and_dispose(block_destroyer(this));
+ this->priv_invariants();
+ multiallocation_chain chain;
+ m_block_container.clear_and_dispose(block_destroyer(this, chain));
+ this->mp_segment_mngr_base->deallocate_many(chain);
m_totally_free_blocks = 0;
}
@@ -534,93 +725,129 @@ class private_adaptive_node_pool_impl
}
block_info_t *priv_block_from_node(void *node) const
- { return priv_block_from_node(node, IsAlignOnly()); }
+ { return this->priv_block_from_node(node, IsAlignOnly()); }
hdr_offset_holder *priv_first_subblock_from_block(block_info_t *block) const
+ { return this->priv_first_subblock_from_block(block, IsAlignOnly()); }
+
+ hdr_offset_holder *priv_first_subblock_from_block(block_info_t *block, AlignOnlyFalse) const
{
- hdr_offset_holder *hdr_off_holder = reinterpret_cast<hdr_offset_holder*>
+ hdr_offset_holder *const hdr_off_holder = reinterpret_cast<hdr_offset_holder*>
(reinterpret_cast<char*>(block) - (m_num_subblocks-1)*m_real_block_alignment);
BOOST_ASSERT(hdr_off_holder->hdr_offset == size_type(reinterpret_cast<char*>(block) - reinterpret_cast<char*>(hdr_off_holder)));
- BOOST_ASSERT(0 == ((std::size_t)hdr_off_holder & (m_real_block_alignment - 1)));
+ BOOST_ASSERT(0 == ((std::size_t)hdr_off_holder & (m_real_block_alignment - 1)));
BOOST_ASSERT(0 == (hdr_off_holder->hdr_offset & (m_real_block_alignment - 1)));
return hdr_off_holder;
}
+ hdr_offset_holder *priv_first_subblock_from_block(block_info_t *block, AlignOnlyTrue) const
+ {
+ return reinterpret_cast<hdr_offset_holder*>(block);
+ }
+
+ void priv_dispatch_block_chain_or_free
+ ( multiallocation_chain &chain, block_info_t &c_info, size_type num_node
+ , char *mem_address, size_type total_elements, bool insert_block_if_free)
+ {
+ BOOST_ASSERT(chain.size() <= total_elements);
+ //First add all possible nodes to the chain
+ const size_type left = total_elements - chain.size();
+ const size_type max_chain = (num_node < left) ? num_node : left;
+ mem_address = static_cast<char *>(container_detail::to_raw_pointer
+ (chain.incorporate_after(chain.last(), void_pointer(mem_address), m_real_node_size, max_chain)));
+ //Now store remaining nodes in the free list
+ if(const size_type max_free = num_node - max_chain){
+ free_nodes_t & free_nodes = c_info.free_nodes;
+ free_nodes.incorporate_after(free_nodes.last(), void_pointer(mem_address), m_real_node_size, max_free);
+ if(insert_block_if_free){
+ m_block_container.push_front(c_info);
+ }
+ }
+ }
+
//!Allocates a several blocks of nodes. Can throw
- void priv_alloc_block(size_type n, AlignOnlyTrue)
+ void priv_append_from_new_blocks(size_type min_elements, multiallocation_chain &chain, AlignOnlyTrue)
{
- size_type real_block_size = m_real_block_alignment - PayloadPerAllocation;
+ BOOST_ASSERT(m_block_container.empty());
+ BOOST_ASSERT(min_elements > 0);
+ const size_type n = (min_elements - 1)/m_real_num_node + 1;
+ const size_type real_block_size = m_real_block_alignment - PayloadPerAllocation;
+ const size_type total_elements = chain.size() + min_elements;
for(size_type i = 0; i != n; ++i){
//We allocate a new NodeBlock and put it the last
//element of the tree
char *mem_address = static_cast<char*>
(mp_segment_mngr_base->allocate_aligned(real_block_size, m_real_block_alignment));
- if(!mem_address) throw std::bad_alloc();
- ++m_totally_free_blocks;
- block_info_t *c_info = new(mem_address)block_info_t();
- m_block_multiset.insert(m_block_multiset.end(), *c_info);
-
+ if(!mem_address){
+ //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_bad_alloc();
+ }
+ block_info_t &c_info = *new(mem_address)block_info_t();
mem_address += HdrSize;
- //We initialize all Nodes in Node Block to insert
- //them in the free Node list
- typename free_nodes_t::iterator prev_insert_pos = c_info->free_nodes.before_begin();
- for(size_type i = 0; i < m_real_num_node; ++i){
- prev_insert_pos = c_info->free_nodes.insert_after(prev_insert_pos, *(node_t*)mem_address);
- mem_address += m_real_node_size;
+ if(i != (n-1)){
+ chain.incorporate_after(chain.last(), void_pointer(mem_address), m_real_node_size, m_real_num_node);
+ }
+ else{
+ this->priv_dispatch_block_chain_or_free(chain, c_info, m_real_num_node, mem_address, total_elements, true);
}
}
}
- void priv_alloc_block(size_type n, AlignOnlyFalse)
+ void priv_append_from_new_blocks(size_type min_elements, multiallocation_chain &chain, AlignOnlyFalse)
{
- size_type real_block_size = m_real_block_alignment*m_num_subblocks - PayloadPerAllocation;
- size_type elements_per_subblock = (m_real_block_alignment - HdrOffsetSize)/m_real_node_size;
- size_type hdr_subblock_elements = (m_real_block_alignment - HdrSize - PayloadPerAllocation)/m_real_node_size;
+ BOOST_ASSERT(m_block_container.empty());
+ BOOST_ASSERT(min_elements > 0);
+ const size_type n = (min_elements - 1)/m_real_num_node + 1;
+ const size_type real_block_size = m_real_block_alignment*m_num_subblocks - PayloadPerAllocation;
+ const size_type elements_per_subblock = (m_real_block_alignment - HdrOffsetSize)/m_real_node_size;
+ const size_type hdr_subblock_elements = (m_real_block_alignment - HdrSize - PayloadPerAllocation)/m_real_node_size;
+ const size_type total_elements = chain.size() + min_elements;
for(size_type i = 0; i != n; ++i){
//We allocate a new NodeBlock and put it the last
//element of the tree
char *mem_address = static_cast<char*>
(mp_segment_mngr_base->allocate_aligned(real_block_size, m_real_block_alignment));
- if(!mem_address) throw std::bad_alloc();
- ++m_totally_free_blocks;
-
+ if(!mem_address){
+ //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_bad_alloc();
+ }
//First initialize header information on the last subblock
char *hdr_addr = mem_address + m_real_block_alignment*(m_num_subblocks-1);
- block_info_t *c_info = new(hdr_addr)block_info_t();
+ block_info_t &c_info = *new(hdr_addr)block_info_t();
//Some structural checks
- BOOST_ASSERT(static_cast<void*>(&static_cast<hdr_offset_holder*>(c_info)->hdr_offset) ==
- static_cast<void*>(c_info));
- typename free_nodes_t::iterator prev_insert_pos = c_info->free_nodes.before_begin();
- for( size_type subblock = 0, maxsubblock = m_num_subblocks - 1
- ; subblock < maxsubblock
- ; ++subblock, mem_address += m_real_block_alignment){
- //Initialize header offset mark
- new(mem_address) hdr_offset_holder(size_type(hdr_addr - mem_address));
- char *pNode = mem_address + HdrOffsetSize;
- for(size_type i = 0; i < elements_per_subblock; ++i){
- prev_insert_pos = c_info->free_nodes.insert_after(prev_insert_pos, *new (pNode) node_t);
- pNode += m_real_node_size;
+ BOOST_ASSERT(static_cast<void*>(&static_cast<hdr_offset_holder&>(c_info).hdr_offset) ==
+ static_cast<void*>(&c_info)); (void)c_info;
+ if(i != (n-1)){
+ for( size_type subblock = 0, maxsubblock = m_num_subblocks - 1
+ ; subblock < maxsubblock
+ ; ++subblock, mem_address += m_real_block_alignment){
+ //Initialize header offset mark
+ new(mem_address) hdr_offset_holder(size_type(hdr_addr - mem_address));
+ chain.incorporate_after
+ (chain.last(), void_pointer(mem_address + HdrOffsetSize), m_real_node_size, elements_per_subblock);
}
+ chain.incorporate_after(chain.last(), void_pointer(hdr_addr + HdrSize), m_real_node_size, hdr_subblock_elements);
}
- {
- char *pNode = hdr_addr + HdrSize;
- //We initialize all Nodes in Node Block to insert
- //them in the free Node list
- for(size_type i = 0; i < hdr_subblock_elements; ++i){
- prev_insert_pos = c_info->free_nodes.insert_after(prev_insert_pos, *new (pNode) node_t);
- pNode += m_real_node_size;
+ else{
+ for( size_type subblock = 0, maxsubblock = m_num_subblocks - 1
+ ; subblock < maxsubblock
+ ; ++subblock, mem_address += m_real_block_alignment){
+ //Initialize header offset mark
+ new(mem_address) hdr_offset_holder(size_type(hdr_addr - mem_address));
+ this->priv_dispatch_block_chain_or_free
+ (chain, c_info, elements_per_subblock, mem_address + HdrOffsetSize, total_elements, false);
}
+ this->priv_dispatch_block_chain_or_free
+ (chain, c_info, hdr_subblock_elements, hdr_addr + HdrSize, total_elements, true);
}
- //Insert the block after the free node list is full
- m_block_multiset.insert(m_block_multiset.end(), *c_info);
}
}
- //!Allocates a block of nodes. Can throw std::bad_alloc
- void priv_alloc_block(size_type n)
- { return priv_alloc_block(n, IsAlignOnly()); }
-
private:
typedef typename boost::intrusive::pointer_traits
<void_pointer>::template rebind_pointer<segment_manager_base_type>::type segment_mngr_base_ptr_t;
@@ -634,9 +861,9 @@ class private_adaptive_node_pool_impl
//This is the real number of nodes per block
//const
size_type m_real_num_node;
- segment_mngr_base_ptr_t mp_segment_mngr_base; //Segment manager
- block_multiset_t m_block_multiset; //Intrusive block list
- size_type m_totally_free_blocks; //Free blocks
+ segment_mngr_base_ptr_t mp_segment_mngr_base; //Segment manager
+ block_container_t m_block_container; //Intrusive block list
+ size_type m_totally_free_blocks; //Free blocks
};
} //namespace container_detail {
diff --git a/boost/container/detail/advanced_insert_int.hpp b/boost/container/detail/advanced_insert_int.hpp
index a97af282e0..a35279dcf7 100644
--- a/boost/container/detail/advanced_insert_int.hpp
+++ b/boost/container/detail/advanced_insert_int.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2008-2012. Distributed under the Boost
+// (C) Copyright Ion Gaztanaga 2008-2013. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
@@ -11,170 +11,198 @@
#ifndef BOOST_CONTAINER_ADVANCED_INSERT_INT_HPP
#define BOOST_CONTAINER_ADVANCED_INSERT_INT_HPP
-#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#if defined(_MSC_VER)
# pragma once
#endif
-#include "config_begin.hpp"
+#include <boost/container/detail/config_begin.hpp>
#include <boost/container/detail/workaround.hpp>
+
#include <boost/container/allocator_traits.hpp>
#include <boost/container/detail/destroyers.hpp>
#include <boost/aligned_storage.hpp>
-#include <boost/move/move.hpp>
+#include <boost/move/utility_core.hpp>
+#include <boost/container/detail/mpl.hpp>
+#include <boost/container/detail/utilities.hpp>
+#include <boost/container/detail/type_traits.hpp>
+#include <boost/container/detail/iterators.hpp>
#include <iterator> //std::iterator_traits
#include <boost/assert.hpp>
+#include <boost/core/no_exceptions_support.hpp>
namespace boost { namespace container { namespace container_detail {
-//This class will be interface for operations dependent on FwdIt types used advanced_insert_aux_impl
-template<class Iterator>
-struct advanced_insert_aux_int
+template<class A, class FwdIt, class Iterator>
+struct move_insert_range_proxy
{
- typedef typename std::iterator_traits<Iterator>::difference_type difference_type;
- virtual void copy_remaining_to(Iterator p) = 0;
- virtual void uninitialized_copy_remaining_to(Iterator p) = 0;
- virtual void uninitialized_copy_some_and_update(Iterator pos, difference_type division_count, bool first) = 0;
- virtual void copy_some_and_update(Iterator pos, difference_type division_count, bool first) = 0;
- virtual ~advanced_insert_aux_int() {}
+ typedef typename allocator_traits<A>::size_type size_type;
+ typedef typename allocator_traits<A>::value_type value_type;
+
+ explicit move_insert_range_proxy(FwdIt first)
+ : first_(first)
+ {}
+
+ void uninitialized_copy_n_and_update(A &a, Iterator p, size_type n)
+ {
+ this->first_ = ::boost::container::uninitialized_move_alloc_n_source
+ (a, this->first_, n, p);
+ }
+
+ void copy_n_and_update(A &, Iterator p, size_type n)
+ {
+ this->first_ = ::boost::container::move_n_source(this->first_, n, p);
+ }
+
+ FwdIt first_;
};
-//This class template will adapt each FwIt types to advanced_insert_aux_int
+
template<class A, class FwdIt, class Iterator>
-struct advanced_insert_aux_proxy
- : public advanced_insert_aux_int<Iterator>
+struct insert_range_proxy
{
typedef typename allocator_traits<A>::size_type size_type;
typedef typename allocator_traits<A>::value_type value_type;
- typedef typename advanced_insert_aux_int<Iterator>::difference_type difference_type;
-
- advanced_insert_aux_proxy(A& a, FwdIt first, FwdIt last)
- : a_(a), first_(first), last_(last)
- {}
- virtual ~advanced_insert_aux_proxy()
+ explicit insert_range_proxy(FwdIt first)
+ : first_(first)
{}
- virtual void copy_remaining_to(Iterator p)
- { ::boost::copy_or_move(this->first_, this->last_, p); }
-
- virtual void uninitialized_copy_remaining_to(Iterator p)
- { ::boost::container::uninitialized_copy_or_move_alloc(this->a_, this->first_, this->last_, p); }
+ void uninitialized_copy_n_and_update(A &a, Iterator p, size_type n)
+ {
+ this->first_ = ::boost::container::uninitialized_copy_alloc_n_source(a, this->first_, n, p);
+ }
- virtual void uninitialized_copy_some_and_update(Iterator pos, difference_type division_count, bool first_n)
+ void copy_n_and_update(A &, Iterator p, size_type n)
{
- FwdIt mid = this->first_;
- std::advance(mid, division_count);
- if(first_n){
- ::boost::container::uninitialized_copy_or_move_alloc(this->a_, this->first_, mid, pos);
- this->first_ = mid;
- }
- else{
- ::boost::container::uninitialized_copy_or_move_alloc(this->a_, mid, this->last_, pos);
- this->last_ = mid;
- }
+ this->first_ = ::boost::container::copy_n_source(this->first_, n, p);
}
- virtual void copy_some_and_update(Iterator pos, difference_type division_count, bool first_n)
+ FwdIt first_;
+};
+
+
+template<class A, class Iterator>
+struct insert_n_copies_proxy
+{
+ typedef typename allocator_traits<A>::size_type size_type;
+ typedef typename allocator_traits<A>::value_type value_type;
+
+ explicit insert_n_copies_proxy(const value_type &v)
+ : v_(v)
+ {}
+
+ void uninitialized_copy_n_and_update(A &a, Iterator p, size_type n) const
+ { boost::container::uninitialized_fill_alloc_n(a, v_, n, p); }
+
+ void copy_n_and_update(A &, Iterator p, size_type n) const
{
- FwdIt mid = this->first_;
- std::advance(mid, division_count);
- if(first_n){
- ::boost::copy_or_move(this->first_, mid, pos);
- this->first_ = mid;
- }
- else{
- ::boost::copy_or_move(mid, this->last_, pos);
- this->last_ = mid;
+ for (; 0 < n; --n, ++p){
+ *p = v_;
}
}
- A &a_;
- FwdIt first_, last_;
+
+ const value_type &v_;
};
-//This class template will adapt default construction insertions to advanced_insert_aux_int
template<class A, class Iterator>
-struct default_construct_aux_proxy
- : public advanced_insert_aux_int<Iterator>
+struct insert_value_initialized_n_proxy
{
typedef ::boost::container::allocator_traits<A> alloc_traits;
typedef typename allocator_traits<A>::size_type size_type;
typedef typename allocator_traits<A>::value_type value_type;
- typedef typename advanced_insert_aux_int<Iterator>::difference_type difference_type;
- default_construct_aux_proxy(A &a, size_type count)
- : a_(a), count_(count)
- {}
+ void uninitialized_copy_n_and_update(A &a, Iterator p, size_type n) const
+ { boost::container::uninitialized_value_init_alloc_n(a, n, p); }
+
+ void copy_n_and_update(A &, Iterator, size_type) const
+ { BOOST_ASSERT(false); }
+};
- virtual ~default_construct_aux_proxy()
+template<class A, class Iterator>
+struct insert_default_initialized_n_proxy
+{
+ typedef ::boost::container::allocator_traits<A> alloc_traits;
+ typedef typename allocator_traits<A>::size_type size_type;
+ typedef typename allocator_traits<A>::value_type value_type;
+
+ void uninitialized_copy_n_and_update(A &a, Iterator p, size_type n) const
+ { boost::container::uninitialized_default_init_alloc_n(a, n, p); }
+
+ void copy_n_and_update(A &, Iterator, size_type) const
+ { BOOST_ASSERT(false); }
+};
+
+template<class A, class Iterator>
+struct insert_copy_proxy
+{
+ typedef boost::container::allocator_traits<A> alloc_traits;
+ typedef typename alloc_traits::size_type size_type;
+ typedef typename alloc_traits::value_type value_type;
+
+ explicit insert_copy_proxy(const value_type &v)
+ : v_(v)
{}
- virtual void copy_remaining_to(Iterator)
- { //This should never be called with any count
- BOOST_ASSERT(this->count_ == 0);
+ void uninitialized_copy_n_and_update(A &a, Iterator p, size_type n) const
+ {
+ BOOST_ASSERT(n == 1); (void)n;
+ alloc_traits::construct( a, iterator_to_raw_pointer(p), v_);
}
- virtual void uninitialized_copy_remaining_to(Iterator p)
- { this->priv_uninitialized_copy(p, this->count_); }
-
- virtual void uninitialized_copy_some_and_update(Iterator pos, difference_type division_count, bool first_n)
+ void copy_n_and_update(A &, Iterator p, size_type n) const
{
- size_type new_count;
- if(first_n){
- new_count = division_count;
- }
- else{
- BOOST_ASSERT(difference_type(this->count_)>= division_count);
- new_count = this->count_ - division_count;
- }
- this->priv_uninitialized_copy(pos, new_count);
+ BOOST_ASSERT(n == 1); (void)n;
+ *p =v_;
}
- virtual void copy_some_and_update(Iterator , difference_type division_count, bool first_n)
+ const value_type &v_;
+};
+
+
+template<class A, class Iterator>
+struct insert_move_proxy
+{
+ typedef boost::container::allocator_traits<A> alloc_traits;
+ typedef typename alloc_traits::size_type size_type;
+ typedef typename alloc_traits::value_type value_type;
+
+ explicit insert_move_proxy(value_type &v)
+ : v_(v)
+ {}
+
+ void uninitialized_copy_n_and_update(A &a, Iterator p, size_type n) const
{
- BOOST_ASSERT(this->count_ == 0);
- size_type new_count;
- if(first_n){
- new_count = division_count;
- }
- else{
- BOOST_ASSERT(difference_type(this->count_)>= division_count);
- new_count = this->count_ - division_count;
- }
- //This function should never called with a count different to zero
- BOOST_ASSERT(new_count == 0);
- (void)new_count;
+ BOOST_ASSERT(n == 1); (void)n;
+ alloc_traits::construct( a, iterator_to_raw_pointer(p), ::boost::move(v_) );
}
- private:
- void priv_uninitialized_copy(Iterator p, const size_type n)
+ void copy_n_and_update(A &, Iterator p, size_type n) const
{
- BOOST_ASSERT(n <= this->count_);
- Iterator orig_p = p;
- size_type i = 0;
- try{
- for(; i < n; ++i, ++p){
- alloc_traits::construct(this->a_, container_detail::to_raw_pointer(&*p));
- }
- }
- catch(...){
- while(i--){
- alloc_traits::destroy(this->a_, container_detail::to_raw_pointer(&*orig_p++));
- }
- throw;
- }
- this->count_ -= n;
+ BOOST_ASSERT(n == 1); (void)n;
+ *p = ::boost::move(v_);
}
- A &a_;
- size_type count_;
+
+ value_type &v_;
};
+template<class It, class A>
+insert_move_proxy<A, It> get_insert_value_proxy(BOOST_RV_REF(typename std::iterator_traits<It>::value_type) v)
+{
+ return insert_move_proxy<A, It>(v);
+}
+
+template<class It, class A>
+insert_copy_proxy<A, It> get_insert_value_proxy(const typename std::iterator_traits<It>::value_type &v)
+{
+ return insert_copy_proxy<A, It>(v);
+}
+
}}} //namespace boost { namespace container { namespace container_detail {
#ifdef BOOST_CONTAINER_PERFECT_FORWARDING
#include <boost/container/detail/variadic_templates_tools.hpp>
-#include <boost/container/detail/stored_ref.hpp>
-#include <boost/move/move.hpp>
+#include <boost/move/utility_core.hpp>
#include <typeinfo>
//#include <iostream> //For debugging purposes
@@ -182,143 +210,117 @@ namespace boost {
namespace container {
namespace container_detail {
-
-//This class template will adapt emplace construction insertions of movable types
-//to advanced_insert_aux_int
template<class A, class Iterator, class ...Args>
-struct advanced_insert_aux_non_movable_emplace
- : public advanced_insert_aux_int<Iterator>
+struct insert_non_movable_emplace_proxy
{
- typedef boost::container::allocator_traits<A> alloc_traits;
- typedef typename allocator_traits<A>::size_type size_type;
- typedef typename allocator_traits<A>::value_type value_type;
- typedef typename advanced_insert_aux_int<Iterator>::difference_type difference_type;
- typedef typename build_number_seq<sizeof...(Args)>::type index_tuple_t;
+ typedef boost::container::allocator_traits<A> alloc_traits;
+ typedef typename alloc_traits::size_type size_type;
+ typedef typename alloc_traits::value_type value_type;
- explicit advanced_insert_aux_non_movable_emplace(A &a, Args&&... args)
- : a_(a)
- , args_(args...)
- , used_(false)
- {}
+ typedef typename build_number_seq<sizeof...(Args)>::type index_tuple_t;
- ~advanced_insert_aux_non_movable_emplace()
+ explicit insert_non_movable_emplace_proxy(Args&&... args)
+ : args_(args...)
{}
- virtual void copy_remaining_to(Iterator)
- //This code can't be called since value_type is not movable or copyable
- { BOOST_ASSERT(false); }
-
- virtual void uninitialized_copy_remaining_to(Iterator p)
- { this->priv_uninitialized_copy_remaining_to(index_tuple_t(), p); }
-
- virtual void uninitialized_copy_some_and_update(Iterator p, difference_type division_count, bool first_n)
- { this->priv_uninitialized_copy_some_and_update(index_tuple_t(), p, division_count, first_n); }
-
- virtual void copy_some_and_update(Iterator, difference_type, bool )
- //This code can't be called since value_type is not movable or copyable
- { BOOST_ASSERT(false); }
+ void uninitialized_copy_n_and_update(A &a, Iterator p, size_type n)
+ { this->priv_uninitialized_copy_some_and_update(a, index_tuple_t(), p, n); }
private:
template<int ...IdxPack>
- void priv_uninitialized_copy_some_and_update(const index_tuple<IdxPack...>&, Iterator p, difference_type division_count, bool first_n)
+ void priv_uninitialized_copy_some_and_update(A &a, const index_tuple<IdxPack...>&, Iterator p, size_type n)
{
- BOOST_ASSERT(division_count <=1);
- if((first_n && division_count == 1) || (!first_n && division_count == 0)){
- if(!this->used_){
- alloc_traits::construct( this->a_
- , container_detail::to_raw_pointer(&*p)
- , ::boost::container::container_detail::
- stored_ref<Args>::forward(get<IdxPack>(this->args_))...
- );
- this->used_ = true;
- }
- }
- }
-
- template<int ...IdxPack>
- void priv_uninitialized_copy_remaining_to(const index_tuple<IdxPack...>&, Iterator p)
- {
- if(!this->used_){
- alloc_traits::construct( this->a_
- , container_detail::to_raw_pointer(&*p)
- , ::boost::container::container_detail::
- stored_ref<Args>::forward(get<IdxPack>(this->args_))...
- );
- this->used_ = true;
- }
+ BOOST_ASSERT(n == 1); (void)n;
+ alloc_traits::construct( a, iterator_to_raw_pointer(p), ::boost::forward<Args>(get<IdxPack>(this->args_))... );
}
protected:
- A &a_;
tuple<Args&...> args_;
- bool used_;
};
-//This class template will adapt emplace construction insertions of movable types
-//to advanced_insert_aux_int
template<class A, class Iterator, class ...Args>
-struct advanced_insert_aux_emplace
- : public advanced_insert_aux_non_movable_emplace<A, Iterator, Args...>
+struct insert_emplace_proxy
+ : public insert_non_movable_emplace_proxy<A, Iterator, Args...>
{
- typedef advanced_insert_aux_non_movable_emplace<A, Iterator, Args...> base_t;
- typedef boost::container::allocator_traits<A> alloc_traits;
- typedef typename base_t::value_type value_type;
- typedef typename base_t::difference_type difference_type;
- typedef typename base_t::index_tuple_t index_tuple_t;
-
- explicit advanced_insert_aux_emplace(A &a, Args&&... args)
- : base_t(a, ::boost::forward<Args>(args)...)
+ typedef insert_non_movable_emplace_proxy<A, Iterator, Args...> base_t;
+ typedef boost::container::allocator_traits<A> alloc_traits;
+ typedef typename base_t::value_type value_type;
+ typedef typename base_t::size_type size_type;
+ typedef typename base_t::index_tuple_t index_tuple_t;
+
+ explicit insert_emplace_proxy(Args&&... args)
+ : base_t(::boost::forward<Args>(args)...)
{}
- ~advanced_insert_aux_emplace()
- {}
-
- //Override only needed functions
- virtual void copy_remaining_to(Iterator p)
- { this->priv_copy_remaining_to(index_tuple_t(), p); }
-
- virtual void copy_some_and_update(Iterator p, difference_type division_count, bool first_n)
- { this->priv_copy_some_and_update(index_tuple_t(), p, division_count, first_n); }
+ void copy_n_and_update(A &a, Iterator p, size_type n)
+ { this->priv_copy_some_and_update(a, index_tuple_t(), p, n); }
private:
+
template<int ...IdxPack>
- void priv_copy_remaining_to(const index_tuple<IdxPack...>&, Iterator p)
+ void priv_copy_some_and_update(A &a, const index_tuple<IdxPack...>&, Iterator p, size_type n)
{
- if(!this->used_){
- aligned_storage<sizeof(value_type), alignment_of<value_type>::value> v;
- value_type *vp = static_cast<value_type *>(static_cast<void *>(&v));
- alloc_traits::construct(this->a_, vp,
- ::boost::container::container_detail::stored_ref<Args>::forward(get<IdxPack>(this->args_))...);
- scoped_destructor<A> d(this->a_, vp);
+ BOOST_ASSERT(n ==1); (void)n;
+ aligned_storage<sizeof(value_type), alignment_of<value_type>::value> v;
+ value_type *vp = static_cast<value_type *>(static_cast<void *>(&v));
+ alloc_traits::construct(a, vp,
+ ::boost::forward<Args>(get<IdxPack>(this->args_))...);
+ BOOST_TRY{
*p = ::boost::move(*vp);
- d.release();
- this->used_ = true;
}
- }
-
- template<int ...IdxPack>
- void priv_copy_some_and_update(const index_tuple<IdxPack...>&, Iterator p, difference_type division_count, bool first_n)
- {
- BOOST_ASSERT(division_count <=1);
- if((first_n && division_count == 1) || (!first_n && division_count == 0)){
- if(!this->used_){
- aligned_storage<sizeof(value_type), alignment_of<value_type>::value> v;
- value_type *vp = static_cast<value_type *>(static_cast<void *>(&v));
- alloc_traits::construct(this->a_, vp,
- ::boost::container::container_detail::stored_ref<Args>::forward(get<IdxPack>(this->args_))...);
- try {
- *p = ::boost::move(*vp);
- } catch (...) {
- alloc_traits::destroy(this->a_, vp);
- throw;
- }
- alloc_traits::destroy(this->a_, vp);
- this->used_ = true;
- }
+ BOOST_CATCH(...){
+ alloc_traits::destroy(a, vp);
+ BOOST_RETHROW
}
+ BOOST_CATCH_END
+ alloc_traits::destroy(a, vp);
}
};
+//Specializations to avoid an unneeded temporary when emplacing from a single argument o type value_type
+template<class A, class Iterator>
+struct insert_emplace_proxy<A, Iterator, typename boost::container::allocator_traits<A>::value_type>
+ : public insert_move_proxy<A, Iterator>
+{
+ explicit insert_emplace_proxy(typename boost::container::allocator_traits<A>::value_type &&v)
+ : insert_move_proxy<A, Iterator>(v)
+ {}
+};
+
+//We use "add_const" here as adding "const" only confuses MSVC12(and maybe later) provoking
+//compiler error C2752 (“more than one partial specialization matches”).
+//Any problem is solvable with an extra layer of indirection? ;-)
+template<class A, class Iterator>
+struct insert_emplace_proxy<A, Iterator
+ , typename boost::container::container_detail::add_const<typename boost::container::allocator_traits<A>::value_type>::type
+ >
+ : public insert_copy_proxy<A, Iterator>
+{
+ explicit insert_emplace_proxy(const typename boost::container::allocator_traits<A>::value_type &v)
+ : insert_copy_proxy<A, Iterator>(v)
+ {}
+};
+
+template<class A, class Iterator>
+struct insert_emplace_proxy<A, Iterator, typename boost::container::allocator_traits<A>::value_type &>
+ : public insert_copy_proxy<A, Iterator>
+{
+ explicit insert_emplace_proxy(const typename boost::container::allocator_traits<A>::value_type &v)
+ : insert_copy_proxy<A, Iterator>(v)
+ {}
+};
+
+template<class A, class Iterator>
+struct insert_emplace_proxy<A, Iterator
+ , typename boost::container::container_detail::add_const<typename boost::container::allocator_traits<A>::value_type>::type &
+ >
+ : public insert_copy_proxy<A, Iterator>
+{
+ explicit insert_emplace_proxy(const typename boost::container::allocator_traits<A>::value_type &v)
+ : insert_copy_proxy<A, Iterator>(v)
+ {}
+};
+
}}} //namespace boost { namespace container { namespace container_detail {
#else //#ifdef BOOST_CONTAINER_PERFECT_FORWARDING
@@ -330,118 +332,142 @@ namespace boost {
namespace container {
namespace container_detail {
-#define BOOST_PP_LOCAL_MACRO(n) \
-template<class A, class Iterator BOOST_PP_ENUM_TRAILING_PARAMS(n, class P) > \
-struct BOOST_PP_CAT(BOOST_PP_CAT(advanced_insert_aux_non_movable_emplace, n), arg) \
- : public advanced_insert_aux_int<Iterator> \
+#define BOOST_PP_LOCAL_MACRO(N) \
+template<class A, class Iterator BOOST_PP_ENUM_TRAILING_PARAMS(N, class P) > \
+struct BOOST_PP_CAT(insert_non_movable_emplace_proxy_arg, N) \
{ \
typedef boost::container::allocator_traits<A> alloc_traits; \
- typedef typename allocator_traits<A>::size_type size_type; \
- typedef typename allocator_traits<A>::value_type value_type; \
- typedef typename advanced_insert_aux_int<Iterator>::difference_type \
- difference_type; \
+ typedef typename alloc_traits::size_type size_type; \
+ typedef typename alloc_traits::value_type value_type; \
\
- BOOST_PP_CAT(BOOST_PP_CAT(advanced_insert_aux_non_movable_emplace, n), arg) \
- ( A &a BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_LIST, _) ) \
- : a_(a) \
- , used_(false) \
- BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_INIT, _) \
- {} \
+ explicit BOOST_PP_CAT(insert_non_movable_emplace_proxy_arg, N) \
+ ( BOOST_PP_ENUM(N, BOOST_CONTAINER_PP_PARAM_LIST, _) ) \
+ BOOST_PP_EXPR_IF(N, :) BOOST_PP_ENUM(N, BOOST_CONTAINER_PP_PARAM_INIT, _) \
+ {} \
\
- virtual void copy_remaining_to(Iterator) \
- { BOOST_ASSERT(false); } \
- \
- virtual void uninitialized_copy_remaining_to(Iterator p) \
+ void uninitialized_copy_n_and_update(A &a, Iterator p, size_type n) \
{ \
- if(!this->used_){ \
- alloc_traits::construct \
- ( this->a_ \
- , container_detail::to_raw_pointer(&*p) \
- BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_MEMBER_FORWARD, _) \
- ); \
- this->used_ = true; \
- } \
+ BOOST_ASSERT(n == 1); (void)n; \
+ alloc_traits::construct \
+ ( a, iterator_to_raw_pointer(p) \
+ BOOST_PP_ENUM_TRAILING(N, BOOST_CONTAINER_PP_MEMBER_FORWARD, _) \
+ ); \
} \
\
- virtual void uninitialized_copy_some_and_update \
- (Iterator p, difference_type division_count, bool first_n) \
- { \
- BOOST_ASSERT(division_count <=1); \
- if((first_n && division_count == 1) || (!first_n && division_count == 0)){ \
- if(!this->used_){ \
- alloc_traits::construct \
- ( this->a_ \
- , container_detail::to_raw_pointer(&*p) \
- BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_MEMBER_FORWARD, _) \
- ); \
- this->used_ = true; \
- } \
- } \
- } \
- \
- virtual void copy_some_and_update(Iterator, difference_type, bool) \
+ void copy_n_and_update(A &, Iterator, size_type) \
{ BOOST_ASSERT(false); } \
\
- A &a_; \
- bool used_; \
- BOOST_PP_REPEAT(n, BOOST_CONTAINER_PP_PARAM_DEFINE, _) \
+ protected: \
+ BOOST_PP_REPEAT(N, BOOST_CONTAINER_PP_PARAM_DEFINE, _) \
}; \
\
-template<class A, class Iterator BOOST_PP_ENUM_TRAILING_PARAMS(n, class P) > \
-struct BOOST_PP_CAT(BOOST_PP_CAT(advanced_insert_aux_emplace, n), arg) \
- : BOOST_PP_CAT(BOOST_PP_CAT( \
- advanced_insert_aux_non_movable_emplace, n), arg) \
- < A, Iterator BOOST_PP_ENUM_TRAILING_PARAMS(n, P) > \
+template<class A, class Iterator BOOST_PP_ENUM_TRAILING_PARAMS(N, class P) > \
+struct BOOST_PP_CAT(insert_emplace_proxy_arg, N) \
+ : BOOST_PP_CAT(insert_non_movable_emplace_proxy_arg, N) \
+ < A, Iterator BOOST_PP_ENUM_TRAILING_PARAMS(N, P) > \
{ \
- typedef BOOST_PP_CAT(BOOST_PP_CAT( \
- advanced_insert_aux_non_movable_emplace, n), arg) \
- <A, Iterator BOOST_PP_ENUM_TRAILING_PARAMS(n, P) > base_t; \
+ typedef BOOST_PP_CAT(insert_non_movable_emplace_proxy_arg, N) \
+ <A, Iterator BOOST_PP_ENUM_TRAILING_PARAMS(N, P) > base_t; \
typedef typename base_t::value_type value_type; \
- typedef typename base_t::difference_type difference_type; \
+ typedef typename base_t::size_type size_type; \
typedef boost::container::allocator_traits<A> alloc_traits; \
\
- BOOST_PP_CAT(BOOST_PP_CAT(advanced_insert_aux_emplace, n), arg) \
- ( A &a BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_LIST, _) ) \
- : base_t(a BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _) ) \
- {} \
+ explicit BOOST_PP_CAT(insert_emplace_proxy_arg, N) \
+ ( BOOST_PP_ENUM(N, BOOST_CONTAINER_PP_PARAM_LIST, _) ) \
+ : base_t(BOOST_PP_ENUM(N, BOOST_CONTAINER_PP_PARAM_FORWARD, _) ) \
+ {} \
\
- virtual void copy_remaining_to(Iterator p) \
+ void copy_n_and_update(A &a, Iterator p, size_type n) \
{ \
- if(!this->used_){ \
- aligned_storage<sizeof(value_type), alignment_of<value_type>::value> v; \
- value_type *vp = static_cast<value_type *>(static_cast<void *>(&v)); \
- alloc_traits::construct(this->a_, vp \
- BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_MEMBER_FORWARD, _)); \
- scoped_destructor<A> d(this->a_, vp); \
- *p = ::boost::move(*vp); \
- d.release(); \
- this->used_ = true; \
+ BOOST_ASSERT(n == 1); (void)n; \
+ aligned_storage<sizeof(value_type), alignment_of<value_type>::value> v; \
+ value_type *vp = static_cast<value_type *>(static_cast<void *>(&v)); \
+ alloc_traits::construct(a, vp \
+ BOOST_PP_ENUM_TRAILING(N, BOOST_CONTAINER_PP_MEMBER_FORWARD, _)); \
+ BOOST_TRY{ \
+ *p = ::boost::move(*vp); \
} \
- } \
- \
- virtual void copy_some_and_update \
- (Iterator p, difference_type division_count, bool first_n) \
- { \
- BOOST_ASSERT(division_count <=1); \
- if((first_n && division_count == 1) || (!first_n && division_count == 0)){ \
- if(!this->used_){ \
- aligned_storage<sizeof(value_type), alignment_of<value_type>::value> v; \
- value_type *vp = static_cast<value_type *>(static_cast<void *>(&v)); \
- alloc_traits::construct(this->a_, vp \
- BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_MEMBER_FORWARD, _)); \
- scoped_destructor<A> d(this->a_, vp); \
- *p = ::boost::move(*vp); \
- d.release(); \
- this->used_ = true; \
- } \
+ BOOST_CATCH(...){ \
+ alloc_traits::destroy(a, vp); \
+ BOOST_RETHROW \
} \
+ BOOST_CATCH_END \
+ alloc_traits::destroy(a, vp); \
} \
}; \
//!
-
#define BOOST_PP_LOCAL_LIMITS (0, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS)
#include BOOST_PP_LOCAL_ITERATE()
+#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+
+//Specializations to avoid an unneeded temporary when emplacing from a single argument o type value_type
+template<class A, class Iterator>
+struct insert_emplace_proxy_arg1<A, Iterator, ::boost::rv<typename boost::container::allocator_traits<A>::value_type> >
+ : public insert_move_proxy<A, Iterator>
+{
+ explicit insert_emplace_proxy_arg1(typename boost::container::allocator_traits<A>::value_type &v)
+ : insert_move_proxy<A, Iterator>(v)
+ {}
+};
+
+template<class A, class Iterator>
+struct insert_emplace_proxy_arg1<A, Iterator, typename boost::container::allocator_traits<A>::value_type>
+ : public insert_copy_proxy<A, Iterator>
+{
+ explicit insert_emplace_proxy_arg1(const typename boost::container::allocator_traits<A>::value_type &v)
+ : insert_copy_proxy<A, Iterator>(v)
+ {}
+};
+
+#else //e.g. MSVC10 & MSVC11
+
+//Specializations to avoid an unneeded temporary when emplacing from a single argument o type value_type
+template<class A, class Iterator>
+struct insert_emplace_proxy_arg1<A, Iterator, typename boost::container::allocator_traits<A>::value_type>
+ : public insert_move_proxy<A, Iterator>
+{
+ explicit insert_emplace_proxy_arg1(typename boost::container::allocator_traits<A>::value_type &&v)
+ : insert_move_proxy<A, Iterator>(v)
+ {}
+};
+
+//We use "add_const" here as adding "const" only confuses MSVC10&11 provoking
+//compiler error C2752 (“more than one partial specialization matches”).
+//Any problem is solvable with an extra layer of indirection? ;-)
+template<class A, class Iterator>
+struct insert_emplace_proxy_arg1<A, Iterator
+ , typename boost::container::container_detail::add_const<typename boost::container::allocator_traits<A>::value_type>::type
+ >
+ : public insert_copy_proxy<A, Iterator>
+{
+ explicit insert_emplace_proxy_arg1(const typename boost::container::allocator_traits<A>::value_type &v)
+ : insert_copy_proxy<A, Iterator>(v)
+ {}
+};
+
+template<class A, class Iterator>
+struct insert_emplace_proxy_arg1<A, Iterator, typename boost::container::allocator_traits<A>::value_type &>
+ : public insert_copy_proxy<A, Iterator>
+{
+ explicit insert_emplace_proxy_arg1(const typename boost::container::allocator_traits<A>::value_type &v)
+ : insert_copy_proxy<A, Iterator>(v)
+ {}
+};
+
+template<class A, class Iterator>
+struct insert_emplace_proxy_arg1<A, Iterator
+ , typename boost::container::container_detail::add_const<typename boost::container::allocator_traits<A>::value_type>::type &
+ >
+ : public insert_copy_proxy<A, Iterator>
+{
+ explicit insert_emplace_proxy_arg1(const typename boost::container::allocator_traits<A>::value_type &v)
+ : insert_copy_proxy<A, Iterator>(v)
+ {}
+};
+
+#endif
+
}}} //namespace boost { namespace container { namespace container_detail {
#endif //#ifdef BOOST_CONTAINER_PERFECT_FORWARDING
diff --git a/boost/container/detail/algorithms.hpp b/boost/container/detail/algorithms.hpp
index dc09575b24..af15f65737 100644
--- a/boost/container/detail/algorithms.hpp
+++ b/boost/container/detail/algorithms.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2005-2012.
+// (C) Copyright Ion Gaztanaga 2005-2013.
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
@@ -13,38 +13,40 @@
#ifndef BOOST_CONTAINER_DETAIL_ALGORITHMS_HPP
#define BOOST_CONTAINER_DETAIL_ALGORITHMS_HPP
-#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#if defined(_MSC_VER)
# pragma once
#endif
-#include "config_begin.hpp"
+#include <boost/container/detail/config_begin.hpp>
#include <boost/container/detail/workaround.hpp>
-
-#include <boost/type_traits/has_trivial_copy.hpp>
-#include <boost/type_traits/has_trivial_assign.hpp>
-#include <boost/detail/no_exceptions_support.hpp>
-
-#include <boost/container/detail/type_traits.hpp>
-#include <boost/container/detail/mpl.hpp>
+#include <boost/container/allocator_traits.hpp>
#include <boost/container/detail/iterators.hpp>
-
-#include <cstring>
-
namespace boost {
namespace container {
template<class A, class T, class InpIt>
inline void construct_in_place(A &a, T* dest, InpIt source)
{ boost::container::allocator_traits<A>::construct(a, dest, *source); }
-//#endif
template<class A, class T, class U, class D>
-inline void construct_in_place(A &a, T *dest, default_construct_iterator<U, D>)
+inline void construct_in_place(A &a, T *dest, value_init_construct_iterator<U, D>)
{
boost::container::allocator_traits<A>::construct(a, dest);
}
+template <class T, class Difference>
+class default_init_construct_iterator;
+
+template<class A, class T, class U, class D>
+inline void construct_in_place(A &a, T *dest, default_init_construct_iterator<U, D>)
+{
+ boost::container::allocator_traits<A>::construct(a, dest, default_init);
+}
+
+template <class T, class EmplaceFunctor, class Difference>
+class emplace_iterator;
+
template<class A, class T, class U, class EF, class D>
inline void construct_in_place(A &a, T *dest, emplace_iterator<U, EF, D> ei)
{
diff --git a/boost/container/detail/alloc_lib.h b/boost/container/detail/alloc_lib.h
new file mode 100644
index 0000000000..4802d9d814
--- /dev/null
+++ b/boost/container/detail/alloc_lib.h
@@ -0,0 +1,326 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2005-2013. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+#ifndef BOOST_CONTAINER_ALLOC_LIB_EXT_H
+#define BOOST_CONTAINER_ALLOC_LIB_EXT_H
+
+#include <stddef.h>
+
+#ifdef _MSC_VER
+#pragma warning (push)
+#pragma warning (disable : 4127)
+
+/*
+ we need to import/export our code only if the user has specifically
+ asked for it by defining either BOOST_ALL_DYN_LINK if they want all boost
+ libraries to be dynamically linked, or BOOST_CONTAINER_DYN_LINK
+ if they want just this one to be dynamically liked:
+*/
+#if defined(BOOST_ALL_DYN_LINK) || defined(BOOST_CONTAINER_DYN_LINK)
+
+/* export if this is our own source, otherwise import: */
+#ifdef BOOST_CONTAINER_SOURCE
+# define BOOST_CONTAINER_DECL __declspec(dllexport)
+#else
+# define BOOST_CONTAINER_DECL __declspec(dllimport)
+#endif /* BOOST_CONTAINER_SOURCE */
+#endif /* DYN_LINK */
+#endif /* _MSC_VER */
+
+/* if BOOST_CONTAINER_DECL isn't defined yet define it now: */
+#ifndef BOOST_CONTAINER_DECL
+#define BOOST_CONTAINER_DECL
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*!An forward iterator to traverse the elements of a memory chain container.*/
+typedef struct multialloc_node_impl
+{
+ struct multialloc_node_impl *next_node_ptr;
+} boost_cont_memchain_node;
+
+
+/*!An forward iterator to traverse the elements of a memory chain container.*/
+typedef struct multialloc_it_impl
+{
+ boost_cont_memchain_node *node_ptr;
+} boost_cont_memchain_it;
+
+/*!Memory chain: A container holding memory portions allocated by boost_cont_multialloc_nodes
+ and boost_cont_multialloc_arrays functions.*/
+typedef struct boost_cont_memchain_impl
+{
+ size_t num_mem;
+ boost_cont_memchain_node root_node;
+ boost_cont_memchain_node *last_node_ptr;
+} boost_cont_memchain;
+
+/*!Advances the iterator one position so that it points to the next element in the memory chain*/
+#define BOOST_CONTAINER_MEMIT_NEXT(IT) (IT.node_ptr = IT.node_ptr->next_node_ptr)
+
+/*!Returns the address of the memory chain currently pointed by the iterator*/
+#define BOOST_CONTAINER_MEMIT_ADDR(IT) ((void*)IT.node_ptr)
+
+/*!Initializer for an iterator pointing to the position before the first element*/
+#define BOOST_CONTAINER_MEMCHAIN_BEFORE_BEGIN_IT(PMEMCHAIN) { &((PMEMCHAIN)->root_node) }
+
+/*!Initializer for an iterator pointing to the first element*/
+#define BOOST_CONTAINER_MEMCHAIN_BEGIN_IT(PMEMCHAIN) {(PMEMCHAIN)->root_node.next_node_ptr }
+
+/*!Initializer for an iterator pointing to the last element*/
+#define BOOST_CONTAINER_MEMCHAIN_LAST_IT(PMEMCHAIN) {(PMEMCHAIN)->last_node_ptr }
+
+/*!Initializer for an iterator pointing to one past the last element (end iterator)*/
+#define BOOST_CONTAINER_MEMCHAIN_END_IT(PMEMCHAIN) {(boost_cont_memchain_node *)0 }
+
+/*!True if IT is the end iterator, false otherwise*/
+#define BOOST_CONTAINER_MEMCHAIN_IS_END_IT(PMEMCHAIN, IT) (!(IT).node_ptr)
+
+/*!The address of the first memory portion hold by the memory chain*/
+#define BOOST_CONTAINER_MEMCHAIN_FIRSTMEM(PMEMCHAIN)((void*)((PMEMCHAIN)->root_node.next_node_ptr))
+
+/*!The address of the last memory portion hold by the memory chain*/
+#define BOOST_CONTAINER_MEMCHAIN_LASTMEM(PMEMCHAIN) ((void*)((PMEMCHAIN)->last_node_ptr))
+
+/*!The number of memory portions hold by the memory chain*/
+#define BOOST_CONTAINER_MEMCHAIN_SIZE(PMEMCHAIN) ((PMEMCHAIN)->num_mem)
+
+/*!Initializes the memory chain from the first memory portion, the last memory
+ portion and number of portions obtained from another memory chain*/
+#define BOOST_CONTAINER_MEMCHAIN_INIT_FROM(PMEMCHAIN, FIRST, LAST, NUM)\
+ (PMEMCHAIN)->last_node_ptr = (boost_cont_memchain_node *)(LAST), \
+ (PMEMCHAIN)->root_node.next_node_ptr = (boost_cont_memchain_node *)(FIRST), \
+ (PMEMCHAIN)->num_mem = (NUM);\
+/**/
+
+/*!Default initializes a memory chain. Postconditions: begin iterator is end iterator,
+ the number of portions is zero.*/
+#define BOOST_CONTAINER_MEMCHAIN_INIT(PMEMCHAIN)\
+ ((PMEMCHAIN)->root_node.next_node_ptr = 0, (PMEMCHAIN)->last_node_ptr = &((PMEMCHAIN)->root_node), (PMEMCHAIN)->num_mem = 0)\
+/**/
+
+/*!True if the memory chain is empty (holds no memory portions*/
+#define BOOST_CONTAINER_MEMCHAIN_EMPTY(PMEMCHAIN)\
+ ((PMEMCHAIN)->num_mem == 0)\
+/**/
+
+/*!Inserts a new memory portions in the front of the chain*/
+#define BOOST_CONTAINER_MEMCHAIN_PUSH_BACK(PMEMCHAIN, MEM)\
+ do{\
+ boost_cont_memchain *____chain____ = (PMEMCHAIN);\
+ boost_cont_memchain_node *____tmp_mem____ = (boost_cont_memchain_node *)(MEM);\
+ ____chain____->last_node_ptr->next_node_ptr = ____tmp_mem____;\
+ ____tmp_mem____->next_node_ptr = 0;\
+ ____chain____->last_node_ptr = ____tmp_mem____;\
+ ++____chain____->num_mem;\
+ }while(0)\
+/**/
+
+/*!Inserts a new memory portions in the back of the chain*/
+#define BOOST_CONTAINER_MEMCHAIN_PUSH_FRONT(PMEMCHAIN, MEM)\
+ do{\
+ boost_cont_memchain *____chain____ = (PMEMCHAIN);\
+ boost_cont_memchain_node *____tmp_mem____ = (boost_cont_memchain_node *)(MEM);\
+ boost_cont_memchain *____root____ = &((PMEMCHAIN)->root_node);\
+ if(!____chain____->root_node.next_node_ptr){\
+ ____chain____->last_node_ptr = ____tmp_mem____;\
+ }\
+ boost_cont_memchain_node *____old_first____ = ____root____->next_node_ptr;\
+ ____tmp_mem____->next_node_ptr = ____old_first____;\
+ ____root____->next_node_ptr = ____tmp_mem____;\
+ ++____chain____->num_mem;\
+ }while(0)\
+/**/
+
+/*!Erases the memory portion after the portion pointed by BEFORE_IT from the memory chain*/
+/*!Precondition: BEFORE_IT must be a valid iterator of the memory chain and it can't be the end iterator*/
+#define BOOST_CONTAINER_MEMCHAIN_ERASE_AFTER(PMEMCHAIN, BEFORE_IT)\
+ do{\
+ boost_cont_memchain *____chain____ = (PMEMCHAIN);\
+ boost_cont_memchain_node *____prev_node____ = (BEFORE_IT).node_ptr;\
+ boost_cont_memchain_node *____erase_node____ = ____prev_node____->next_node_ptr;\
+ if(____chain____->last_node_ptr == ____erase_node____){\
+ ____chain____->last_node_ptr = &____chain____->root_node;\
+ }\
+ ____prev_node____->next_node_ptr = ____erase_node____->next_node_ptr;\
+ --____chain____->num_mem;\
+ }while(0)\
+/**/
+
+/*!Erases the first portion from the memory chain.
+ Precondition: the memory chain must not be empty*/
+#define BOOST_CONTAINER_MEMCHAIN_POP_FRONT(PMEMCHAIN)\
+ do{\
+ boost_cont_memchain *____chain____ = (PMEMCHAIN);\
+ boost_cont_memchain_node *____prev_node____ = &____chain____->root_node;\
+ boost_cont_memchain_node *____erase_node____ = ____prev_node____->next_node_ptr;\
+ if(____chain____->last_node_ptr == ____erase_node____){\
+ ____chain____->last_node_ptr = &____chain____->root_node;\
+ }\
+ ____prev_node____->next_node_ptr = ____erase_node____->next_node_ptr;\
+ --____chain____->num_mem;\
+ }while(0)\
+/**/
+
+/*!Joins two memory chains inserting the portions of the second chain at the back of the first chain*/
+/*
+#define BOOST_CONTAINER_MEMCHAIN_SPLICE_BACK(PMEMCHAIN, PMEMCHAIN2)\
+ do{\
+ boost_cont_memchain *____chain____ = (PMEMCHAIN);\
+ boost_cont_memchain *____chain2____ = (PMEMCHAIN2);\
+ if(!____chain2____->root_node.next_node_ptr){\
+ break;\
+ }\
+ else if(!____chain____->first_mem){\
+ ____chain____->first_mem = ____chain2____->first_mem;\
+ ____chain____->last_node_ptr = ____chain2____->last_node_ptr;\
+ ____chain____->num_mem = ____chain2____->num_mem;\
+ BOOST_CONTAINER_MEMCHAIN_INIT(*____chain2____);\
+ }\
+ else{\
+ ____chain____->last_node_ptr->next_node_ptr = ____chain2____->first_mem;\
+ ____chain____->last_node_ptr = ____chain2____->last_node_ptr;\
+ ____chain____->num_mem += ____chain2____->num_mem;\
+ }\
+ }while(0)\*/
+/**/
+
+/*!Joins two memory chains inserting the portions of the second chain at the back of the first chain*/
+#define BOOST_CONTAINER_MEMCHAIN_INCORPORATE_AFTER(PMEMCHAIN, BEFORE_IT, FIRST, BEFORELAST, NUM)\
+ do{\
+ boost_cont_memchain *____chain____ = (PMEMCHAIN);\
+ boost_cont_memchain_node *____pnode____ = (BEFORE_IT).node_ptr;\
+ boost_cont_memchain_node *____next____ = ____pnode____->next_node_ptr;\
+ boost_cont_memchain_node *____first____ = (boost_cont_memchain_node *)(FIRST);\
+ boost_cont_memchain_node *____blast____ = (boost_cont_memchain_node *)(BEFORELAST);\
+ size_t ____num____ = (NUM);\
+ if(!____num____){\
+ break;\
+ }\
+ if(____pnode____ == ____chain____->last_node_ptr){\
+ ____chain____->last_node_ptr = ____blast____;\
+ }\
+ ____pnode____->next_node_ptr = ____first____;\
+ ____blast____->next_node_ptr = ____next____;\
+ ____chain____->num_mem += ____num____;\
+ }while(0)\
+/**/
+
+BOOST_CONTAINER_DECL size_t boost_cont_size(const void *p);
+
+BOOST_CONTAINER_DECL void* boost_cont_malloc(size_t bytes);
+
+BOOST_CONTAINER_DECL void boost_cont_free(void* mem);
+
+BOOST_CONTAINER_DECL void* boost_cont_memalign(size_t bytes, size_t alignment);
+
+/*!Indicates the all elements allocated by boost_cont_multialloc_nodes or boost_cont_multialloc_arrays
+ must be contiguous.*/
+#define DL_MULTIALLOC_ALL_CONTIGUOUS ((size_t)(-1))
+
+/*!Indicates the number of contiguous elements allocated by boost_cont_multialloc_nodes or boost_cont_multialloc_arrays
+ should be selected by those functions.*/
+#define DL_MULTIALLOC_DEFAULT_CONTIGUOUS ((size_t)(0))
+
+BOOST_CONTAINER_DECL int boost_cont_multialloc_nodes
+ (size_t n_elements, size_t elem_size, size_t contiguous_elements, boost_cont_memchain *pchain);
+
+BOOST_CONTAINER_DECL int boost_cont_multialloc_arrays
+ (size_t n_elements, const size_t *sizes, size_t sizeof_element, size_t contiguous_elements, boost_cont_memchain *pchain);
+
+BOOST_CONTAINER_DECL void boost_cont_multidealloc(boost_cont_memchain *pchain);
+
+BOOST_CONTAINER_DECL size_t boost_cont_footprint();
+
+BOOST_CONTAINER_DECL size_t boost_cont_allocated_memory();
+
+BOOST_CONTAINER_DECL size_t boost_cont_chunksize(const void *p);
+
+BOOST_CONTAINER_DECL int boost_cont_all_deallocated();
+
+typedef struct boost_cont_malloc_stats_impl
+{
+ size_t max_system_bytes;
+ size_t system_bytes;
+ size_t in_use_bytes;
+} boost_cont_malloc_stats_t;
+
+BOOST_CONTAINER_DECL boost_cont_malloc_stats_t boost_cont_malloc_stats();
+
+BOOST_CONTAINER_DECL size_t boost_cont_in_use_memory();
+
+BOOST_CONTAINER_DECL int boost_cont_trim(size_t pad);
+
+BOOST_CONTAINER_DECL int boost_cont_mallopt
+ (int parameter_number, int parameter_value);
+
+BOOST_CONTAINER_DECL int boost_cont_grow
+ (void* oldmem, size_t minbytes, size_t maxbytes, size_t *received);
+
+BOOST_CONTAINER_DECL int boost_cont_shrink
+ (void* oldmem, size_t minbytes, size_t maxbytes, size_t *received, int do_commit);
+
+BOOST_CONTAINER_DECL void* boost_cont_alloc
+ (size_t minbytes, size_t preferred_bytes, size_t *received_bytes);
+
+BOOST_CONTAINER_DECL int boost_cont_malloc_check();
+
+typedef unsigned int allocation_type;
+
+enum
+{
+ // constants for allocation commands
+ BOOST_CONTAINER_ALLOCATE_NEW = 0X01,
+ BOOST_CONTAINER_EXPAND_FWD = 0X02,
+ BOOST_CONTAINER_EXPAND_BWD = 0X04,
+ BOOST_CONTAINER_SHRINK_IN_PLACE = 0X08,
+ BOOST_CONTAINER_NOTHROW_ALLOCATION = 0X10,
+// BOOST_CONTAINER_ZERO_MEMORY = 0X20,
+ BOOST_CONTAINER_TRY_SHRINK_IN_PLACE = 0X40,
+ BOOST_CONTAINER_EXPAND_BOTH = BOOST_CONTAINER_EXPAND_FWD | BOOST_CONTAINER_EXPAND_BWD,
+ BOOST_CONTAINER_EXPAND_OR_NEW = BOOST_CONTAINER_ALLOCATE_NEW | BOOST_CONTAINER_EXPAND_BOTH
+};
+
+//#define BOOST_CONTAINERDLMALLOC__FOOTERS
+#ifndef BOOST_CONTAINERDLMALLOC__FOOTERS
+enum { BOOST_CONTAINER_ALLOCATION_PAYLOAD = sizeof(size_t) };
+#else
+enum { BOOST_CONTAINER_ALLOCATION_PAYLOAD = sizeof(size_t)*2 };
+#endif
+
+typedef struct boost_cont_command_ret_impl
+{
+ void *first;
+ int second;
+}boost_cont_command_ret_t;
+
+BOOST_CONTAINER_DECL boost_cont_command_ret_t boost_cont_allocation_command
+ ( allocation_type command
+ , size_t sizeof_object
+ , size_t limit_objects
+ , size_t preferred_objects
+ , size_t *received_objects
+ , void *reuse_ptr
+ );
+
+BOOST_CONTAINER_DECL int boost_cont_mallopt(int param_number, int value);
+
+#ifdef __cplusplus
+} //extern "C" {
+#endif
+
+#ifdef _MSC_VER
+#pragma warning (pop)
+#endif
+
+
+#endif //#define BOOST_CONTAINERDLMALLOC__EXT_H
diff --git a/boost/container/detail/alloc_lib_auto_link.hpp b/boost/container/detail/alloc_lib_auto_link.hpp
new file mode 100644
index 0000000000..e0a01b6086
--- /dev/null
+++ b/boost/container/detail/alloc_lib_auto_link.hpp
@@ -0,0 +1,20 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2005-2013. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+#ifndef BOOST_CONTAINER_DETAIL_BOOST_CONT_EXT_AUTO_LINK_HPP
+#define BOOST_CONTAINER_DETAIL_BOOST_CONT_EXT_AUTO_LINK_HPP
+
+#if defined(_MSC_VER)
+# pragma once
+#endif
+
+#include <boost/container/detail/auto_link.hpp>
+#include <boost/container/detail/alloc_lib.h>
+
+#endif //#ifndef BOOST_CONTAINER_DETAIL_BOOST_CONT_EXT_AUTO_LINK_HPP
diff --git a/boost/container/detail/allocation_type.hpp b/boost/container/detail/allocation_type.hpp
index 1ebf20ed70..65d543ad50 100644
--- a/boost/container/detail/allocation_type.hpp
+++ b/boost/container/detail/allocation_type.hpp
@@ -1,6 +1,6 @@
///////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
+// (C) Copyright Ion Gaztanaga 2005-2013. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
@@ -11,19 +11,19 @@
#ifndef BOOST_CONTAINER_ALLOCATION_TYPE_HPP
#define BOOST_CONTAINER_ALLOCATION_TYPE_HPP
-#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#if defined(_MSC_VER)
# pragma once
#endif
-#include "config_begin.hpp"
+#include <boost/container/detail/config_begin.hpp>
#include <boost/container/detail/workaround.hpp>
namespace boost {
namespace container {
-/// @cond
+#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
enum allocation_type_v
-{
+{
// constants for allocation commands
allocate_new_v = 0x01,
expand_fwd_v = 0x02,
@@ -37,7 +37,7 @@ enum allocation_type_v
};
typedef int allocation_type;
-/// @endcond
+#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
static const allocation_type allocate_new = (allocation_type)allocate_new_v;
static const allocation_type expand_fwd = (allocation_type)expand_fwd_v;
static const allocation_type expand_bwd = (allocation_type)expand_bwd_v;
diff --git a/boost/container/detail/allocator_version_traits.hpp b/boost/container/detail/allocator_version_traits.hpp
new file mode 100644
index 0000000000..18bb2ac613
--- /dev/null
+++ b/boost/container/detail/allocator_version_traits.hpp
@@ -0,0 +1,168 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2012-2013. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_CONTAINER_DETAIL_ALLOCATOR_VERSION_TRAITS_HPP
+#define BOOST_CONTAINER_DETAIL_ALLOCATOR_VERSION_TRAITS_HPP
+
+#if defined(_MSC_VER)
+# pragma once
+#endif
+
+#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 <boost/core/no_exceptions_support.hpp> //BOOST_TRY
+
+namespace boost {
+namespace container {
+namespace container_detail {
+
+template<class Allocator, unsigned Version = boost::container::container_detail::version<Allocator>::value>
+struct allocator_version_traits
+{
+ typedef ::boost::container::container_detail::integral_constant
+ <unsigned, Version> alloc_version;
+
+ typedef typename Allocator::multiallocation_chain multiallocation_chain;
+
+ typedef typename boost::container::allocator_traits<Allocator>::pointer pointer;
+ typedef typename boost::container::allocator_traits<Allocator>::size_type size_type;
+
+ //Node allocation interface
+ static pointer allocate_one(Allocator &a)
+ { return a.allocate_one(); }
+
+ static void deallocate_one(Allocator &a, const pointer &p)
+ { a.deallocate_one(p); }
+
+ static void allocate_individual(Allocator &a, size_type n, multiallocation_chain &m)
+ { return a.allocate_individual(n, m); }
+
+ static void deallocate_individual(Allocator &a, multiallocation_chain &holder)
+ { a.deallocate_individual(holder); }
+
+ static std::pair<pointer, bool>
+ allocation_command(Allocator &a, allocation_type command,
+ size_type limit_size, size_type preferred_size,
+ size_type &received_size, const pointer &reuse)
+ {
+ return a.allocation_command
+ (command, limit_size, preferred_size, received_size, reuse);
+ }
+};
+
+template<class Allocator>
+struct allocator_version_traits<Allocator, 1>
+{
+ typedef ::boost::container::container_detail::integral_constant
+ <unsigned, 1> alloc_version;
+
+ typedef typename boost::container::allocator_traits<Allocator>::pointer pointer;
+ typedef typename boost::container::allocator_traits<Allocator>::size_type size_type;
+ typedef typename boost::container::allocator_traits<Allocator>::value_type value_type;
+
+ typedef typename boost::intrusive::pointer_traits<pointer>::
+ template rebind_pointer<void>::type void_ptr;
+ typedef container_detail::basic_multiallocation_chain
+ <void_ptr> multialloc_cached_counted;
+ typedef boost::container::container_detail::
+ transform_multiallocation_chain
+ < multialloc_cached_counted, value_type> multiallocation_chain;
+
+ //Node allocation interface
+ static pointer allocate_one(Allocator &a)
+ { return a.allocate(1); }
+
+ static void deallocate_one(Allocator &a, const pointer &p)
+ { a.deallocate(p, 1); }
+
+ static void deallocate_individual(Allocator &a, multiallocation_chain &holder)
+ {
+ size_type n = holder.size();
+ typename multiallocation_chain::iterator it = holder.begin();
+ while(n--){
+ pointer p = boost::intrusive::pointer_traits<pointer>::pointer_to(*it);
+ ++it;
+ a.deallocate(p, 1);
+ }
+ }
+
+ struct allocate_individual_rollback
+ {
+ allocate_individual_rollback(Allocator &a, multiallocation_chain &chain)
+ : mr_a(a), mp_chain(&chain)
+ {}
+
+ ~allocate_individual_rollback()
+ {
+ if(mp_chain)
+ allocator_version_traits::deallocate_individual(mr_a, *mp_chain);
+ }
+
+ void release()
+ {
+ mp_chain = 0;
+ }
+
+ Allocator &mr_a;
+ multiallocation_chain * mp_chain;
+ };
+
+ static void allocate_individual(Allocator &a, size_type n, multiallocation_chain &m)
+ {
+ allocate_individual_rollback rollback(a, m);
+ while(n--){
+ m.push_front(a.allocate(1));
+ }
+ rollback.release();
+ }
+
+ static std::pair<pointer, bool>
+ allocation_command(Allocator &a, allocation_type command,
+ size_type, size_type preferred_size,
+ size_type &received_size, const pointer &)
+ {
+ std::pair<pointer, bool> ret(pointer(), false);
+ if(!(command & allocate_new)){
+ if(!(command & nothrow_allocation)){
+ throw_logic_error("version 1 allocator without allocate_new flag");
+ }
+ }
+ else{
+ received_size = preferred_size;
+ BOOST_TRY{
+ ret.first = a.allocate(received_size);
+ }
+ BOOST_CATCH(...){
+ if(!(command & nothrow_allocation)){
+ BOOST_RETHROW
+ }
+ }
+ BOOST_CATCH_END
+ }
+ return ret;
+ }
+};
+
+} //namespace container_detail {
+} //namespace container {
+} //namespace boost {
+
+#include <boost/container/detail/config_end.hpp>
+
+#endif // ! defined(BOOST_CONTAINER_DETAIL_ALLOCATOR_VERSION_TRAITS_HPP)
diff --git a/boost/container/detail/auto_link.hpp b/boost/container/detail/auto_link.hpp
new file mode 100644
index 0000000000..2e4733363d
--- /dev/null
+++ b/boost/container/detail/auto_link.hpp
@@ -0,0 +1,38 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2007-2013. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+#ifndef BOOST_CONTAINER_DETAIL_AUTO_LINK_HPP_INCLUDED
+#define BOOST_CONTAINER_DETAIL_AUTO_LINK_HPP_INCLUDED
+
+#if defined(_MSC_VER)
+# pragma once
+#endif
+
+//
+// Automatically link to the correct build variant where possible.
+//
+#if !defined(BOOST_ALL_NO_LIB) && !defined(BOOST_CONTAINER_NO_LIB) && !defined(BOOST_CONTAINER_SOURCE)
+//
+// Set the name of our library, this will get undef'ed by auto_link.hpp
+// once it's done with it:
+//
+#define BOOST_LIB_NAME boost_container
+//
+// If we're importing code from a dll, then tell auto_link.hpp about it:
+//
+#if defined(BOOST_ALL_DYN_LINK) || defined(BOOST_CONTAINER_DYN_LINK)
+# define BOOST_DYN_LINK
+#endif
+//
+// And include the header that does the work:
+//
+#include <boost/config/auto_link.hpp>
+#endif // auto-linking disabled
+
+#endif //#ifndef BOOST_CONTAINER_DETAIL_AUTO_LINK_HPP_INCLUDED
diff --git a/boost/container/detail/config_begin.hpp b/boost/container/detail/config_begin.hpp
index 83c2cfe40c..ca9dd59682 100644
--- a/boost/container/detail/config_begin.hpp
+++ b/boost/container/detail/config_begin.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
+// (C) Copyright Ion Gaztanaga 2005-2013. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
@@ -9,15 +9,13 @@
//////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_CONTAINER_CONTAINER_DETAIL_CONFIG_INCLUDED
#define BOOST_CONTAINER_CONTAINER_DETAIL_CONFIG_INCLUDED
+#ifndef BOOST_CONFIG_HPP
#include <boost/config.hpp>
+#endif
#endif //BOOST_CONTAINER_CONTAINER_DETAIL_CONFIG_INCLUDED
#ifdef BOOST_MSVC
- #ifndef _CRT_SECURE_NO_DEPRECATE
- #define BOOST_CONTAINER_DETAIL_CRT_SECURE_NO_DEPRECATE
- #define _CRT_SECURE_NO_DEPRECATE
- #endif
#pragma warning (push)
#pragma warning (disable : 4702) // unreachable code
#pragma warning (disable : 4706) // assignment within conditional expression
@@ -46,4 +44,5 @@
#pragma warning (disable : 4673) // throwing '' the following types will not be considered at the catch site
#pragma warning (disable : 4671) // the copy constructor is inaccessible
#pragma warning (disable : 4584) // X is already a base-class of Y
+ #pragma warning (disable : 4510) // default constructor could not be generated
#endif //BOOST_MSVC
diff --git a/boost/container/detail/config_end.hpp b/boost/container/detail/config_end.hpp
index 34513718cc..f93c8f6f79 100644
--- a/boost/container/detail/config_end.hpp
+++ b/boost/container/detail/config_end.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
+// (C) Copyright Ion Gaztanaga 2005-2013. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
@@ -9,9 +9,5 @@
//////////////////////////////////////////////////////////////////////////////
#if defined BOOST_MSVC
#pragma warning (pop)
- #ifdef BOOST_CONTAINER_DETAIL_CRT_SECURE_NO_DEPRECATE
- #undef BOOST_CONTAINER_DETAIL_CRT_SECURE_NO_DEPRECATE
- #undef _CRT_SECURE_NO_DEPRECATE
- #endif
#endif
diff --git a/boost/container/detail/destroyers.hpp b/boost/container/detail/destroyers.hpp
index d1b118cdcc..ea9b617437 100644
--- a/boost/container/detail/destroyers.hpp
+++ b/boost/container/detail/destroyers.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2005-2012.
+// (C) Copyright Ion Gaztanaga 2005-2013.
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
@@ -13,12 +13,13 @@
#ifndef BOOST_CONTAINER_DESTROYERS_HPP
#define BOOST_CONTAINER_DESTROYERS_HPP
-#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#if defined(_MSC_VER)
# pragma once
#endif
-#include "config_begin.hpp"
+#include <boost/container/detail/config_begin.hpp>
#include <boost/container/detail/workaround.hpp>
+
#include <boost/container/detail/version_type.hpp>
#include <boost/container/detail/utilities.hpp>
#include <boost/container/allocator_traits.hpp>
@@ -28,6 +29,74 @@ namespace container {
namespace container_detail {
//!A deleter for scoped_ptr that deallocates the memory
+//!allocated for an object using a STL allocator.
+template <class A>
+struct scoped_deallocator
+{
+ typedef allocator_traits<A> allocator_traits_type;
+ typedef typename allocator_traits_type::pointer pointer;
+ typedef container_detail::integral_constant<unsigned,
+ boost::container::container_detail::
+ version<A>::value> alloc_version;
+ typedef container_detail::integral_constant<unsigned, 1> allocator_v1;
+ typedef container_detail::integral_constant<unsigned, 2> allocator_v2;
+
+ private:
+ void priv_deallocate(allocator_v1)
+ { m_alloc.deallocate(m_ptr, 1); }
+
+ void priv_deallocate(allocator_v2)
+ { m_alloc.deallocate_one(m_ptr); }
+
+ BOOST_MOVABLE_BUT_NOT_COPYABLE(scoped_deallocator)
+
+ public:
+
+ pointer m_ptr;
+ A& m_alloc;
+
+ scoped_deallocator(pointer p, A& a)
+ : m_ptr(p), m_alloc(a)
+ {}
+
+ ~scoped_deallocator()
+ { if (m_ptr)priv_deallocate(alloc_version()); }
+
+ scoped_deallocator(BOOST_RV_REF(scoped_deallocator) o)
+ : m_ptr(o.m_ptr), m_alloc(o.m_alloc)
+ { o.release(); }
+
+ pointer get() const
+ { return m_ptr; }
+
+ void set(const pointer &p)
+ { m_ptr = p; }
+
+ void release()
+ { m_ptr = 0; }
+};
+
+template <class Allocator>
+struct null_scoped_deallocator
+{
+ typedef boost::container::allocator_traits<Allocator> AllocTraits;
+ typedef typename AllocTraits::pointer pointer;
+ typedef typename AllocTraits::size_type size_type;
+
+ null_scoped_deallocator(pointer, Allocator&, size_type)
+ {}
+
+ void release()
+ {}
+
+ pointer get() const
+ { return pointer(); }
+
+ void set(const pointer &)
+ {}
+};
+
+//!A deleter for scoped_ptr that deallocates the memory
//!allocated for an array of objects using a STL allocator.
template <class Allocator>
struct scoped_array_deallocator
@@ -126,13 +195,17 @@ struct scoped_destructor_n
void increment_size_backwards(size_type inc)
{ m_n += inc; m_p -= inc; }
-
+
+ void shrink_forward(size_type inc)
+ { m_n -= inc; m_p += inc; }
+
~scoped_destructor_n()
{
if(!m_p) return;
value_type *raw_ptr = container_detail::to_raw_pointer(m_p);
- for(size_type i = 0; i < m_n; ++i, ++raw_ptr)
- AllocTraits::destroy(m_a, raw_ptr);
+ while(m_n--){
+ AllocTraits::destroy(m_a, raw_ptr++);
+ }
}
private:
@@ -159,6 +232,9 @@ struct null_scoped_destructor_n
void increment_size_backwards(size_type)
{}
+ void shrink_forward(size_type)
+ {}
+
void release()
{}
};
@@ -183,6 +259,11 @@ class scoped_destructor
void release()
{ pv_ = 0; }
+
+ void set(value_type *ptr) { pv_ = ptr; }
+
+ value_type *get() const { return pv_; }
+
private:
value_type *pv_;
A &a_;
@@ -239,10 +320,56 @@ class allocator_destroyer
void operator()(const pointer &p)
{
AllocTraits::destroy(a_, container_detail::to_raw_pointer(p));
- priv_deallocate(p, alloc_version());
+ this->priv_deallocate(p, alloc_version());
}
};
+template <class A>
+class allocator_destroyer_and_chain_builder
+{
+ typedef allocator_traits<A> allocator_traits_type;
+ typedef typename allocator_traits_type::value_type value_type;
+ typedef typename A::multiallocation_chain multiallocation_chain;
+
+ A & a_;
+ multiallocation_chain &c_;
+
+ public:
+ allocator_destroyer_and_chain_builder(A &a, multiallocation_chain &c)
+ : a_(a), c_(c)
+ {}
+
+ void operator()(const typename A::pointer &p)
+ {
+ allocator_traits<A>::destroy(a_, container_detail::to_raw_pointer(p));
+ c_.push_back(p);
+ }
+};
+
+template <class A>
+class allocator_multialloc_chain_node_deallocator
+{
+ typedef allocator_traits<A> allocator_traits_type;
+ typedef typename allocator_traits_type::value_type value_type;
+ typedef typename A::multiallocation_chain multiallocation_chain;
+ typedef allocator_destroyer_and_chain_builder<A> chain_builder;
+
+ A & a_;
+ multiallocation_chain c_;
+
+ public:
+ allocator_multialloc_chain_node_deallocator(A &a)
+ : a_(a), c_()
+ {}
+
+ chain_builder get_chain_builder()
+ { return chain_builder(a_, c_); }
+
+ ~allocator_multialloc_chain_node_deallocator()
+ {
+ a_.deallocate_individual(c_);
+ }
+};
} //namespace container_detail {
} //namespace container {
diff --git a/boost/container/detail/flat_tree.hpp b/boost/container/detail/flat_tree.hpp
index 23be0bfd13..a6f7568b43 100644
--- a/boost/container/detail/flat_tree.hpp
+++ b/boost/container/detail/flat_tree.hpp
@@ -1,6 +1,6 @@
////////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
+// (C) Copyright Ion Gaztanaga 2005-2013. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
@@ -11,11 +11,11 @@
#ifndef BOOST_CONTAINER_FLAT_TREE_HPP
#define BOOST_CONTAINER_FLAT_TREE_HPP
-#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#if defined(_MSC_VER)
# pragma once
#endif
-#include "config_begin.hpp"
+#include <boost/container/detail/config_begin.hpp>
#include <boost/container/detail/workaround.hpp>
#include <boost/container/container_fwd.hpp>
@@ -25,7 +25,7 @@
#include <utility>
#include <boost/type_traits/has_trivial_destructor.hpp>
-#include <boost/move/move.hpp>
+#include <boost/move/utility_core.hpp>
#include <boost/container/detail/utilities.hpp>
#include <boost/container/detail/pair.hpp>
@@ -33,7 +33,11 @@
#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>
+#include <boost/move/make_unique.hpp>
namespace boost {
@@ -48,7 +52,7 @@ class flat_tree_value_compare
typedef Value first_argument_type;
typedef Value second_argument_type;
typedef bool return_type;
- public:
+ public:
flat_tree_value_compare()
: Compare()
{}
@@ -65,7 +69,7 @@ class flat_tree_value_compare
const Compare &get_comp() const
{ return *this; }
-
+
Compare &get_comp()
{ return *this; }
};
@@ -73,12 +77,23 @@ class flat_tree_value_compare
template<class Pointer>
struct get_flat_tree_iterators
{
- typedef typename container_detail::
- vector_iterator<Pointer> iterator;
- typedef typename container_detail::
- vector_const_iterator<Pointer> const_iterator;
- typedef std::reverse_iterator<iterator> reverse_iterator;
- typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
+ #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 boost::container::container_detail::
+ vec_iterator<Pointer, false> iterator;
+ typedef typename boost::container::container_detail::
+ vec_iterator<Pointer, true > const_iterator;
+ #endif //BOOST_CONTAINER_VECTOR_ITERATOR_IS_POINTER
+ typedef boost::container::container_detail::
+ reverse_iterator<iterator> reverse_iterator;
+ typedef boost::container::container_detail::
+ reverse_iterator<const_iterator> const_reverse_iterator;
};
template <class Key, class Value, class KeyOfValue,
@@ -103,7 +118,7 @@ class flat_tree
: value_compare(), m_vect()
{}
- Data(const Data &d)
+ explicit Data(const Data &d)
: value_compare(static_cast<const value_compare&>(d)), m_vect(d.m_vect)
{}
@@ -119,15 +134,18 @@ class flat_tree
: value_compare(boost::move(static_cast<value_compare&>(d))), m_vect(boost::move(d.m_vect), a)
{}
- Data(const Compare &comp)
+ explicit Data(const Compare &comp)
: value_compare(comp), m_vect()
{}
- Data(const Compare &comp,
- const allocator_t &alloc)
+ Data(const Compare &comp, const allocator_t &alloc)
: value_compare(comp), m_vect(alloc)
{}
+ explicit Data(const allocator_t &alloc)
+ : value_compare(), m_vect(alloc)
+ {}
+
Data& operator=(BOOST_COPY_ASSIGN_REF(Data) d)
{
this->value_compare::operator=(d);
@@ -145,7 +163,7 @@ class flat_tree
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);
}
@@ -191,6 +209,10 @@ class flat_tree
: m_data(comp, a)
{ }
+ explicit flat_tree(const allocator_type& a)
+ : m_data(a)
+ { }
+
flat_tree(const flat_tree& x)
: m_data(x.m_data)
{ }
@@ -214,8 +236,31 @@ class flat_tree
: m_data(comp, a)
{ this->m_data.m_vect.insert(this->m_data.m_vect.end(), first, last); }
+ template <class InputIterator>
+ flat_tree( bool unique_insertion
+ , InputIterator first, InputIterator last
+ , const Compare& comp = Compare()
+ , const allocator_type& a = allocator_type())
+ : m_data(comp, a)
+ {
+ //Use cend() as hint to achieve linear time for
+ //ordered ranges as required by the standard
+ //for the constructor
+ //Call end() every iteration as reallocation might have invalidated iterators
+ if(unique_insertion){
+ for ( ; first != last; ++first){
+ this->insert_unique(this->cend(), *first);
+ }
+ }
+ else{
+ for ( ; first != last; ++first){
+ this->insert_equal(this->cend(), *first);
+ }
+ }
+ }
+
~flat_tree()
- { }
+ {}
flat_tree& operator=(BOOST_COPY_ASSIGN_REF(flat_tree) x)
{ m_data = x.m_data; return *this; }
@@ -223,11 +268,14 @@ class flat_tree
flat_tree& operator=(BOOST_RV_REF(flat_tree) mx)
{ m_data = boost::move(mx.m_data); return *this; }
- public:
+ public:
// accessors:
Compare key_comp() const
{ return this->m_data.get_comp(); }
+ value_compare value_comp() const
+ { return this->m_data; }
+
allocator_type get_allocator() const
{ return this->m_data.m_vect.get_allocator(); }
@@ -289,21 +337,21 @@ class flat_tree
// insert/erase
std::pair<iterator,bool> insert_unique(const value_type& val)
{
+ std::pair<iterator,bool> ret;
insert_commit_data data;
- std::pair<iterator,bool> ret = priv_insert_unique_prepare(val, data);
- if(ret.second){
- ret.first = priv_insert_commit(data, val);
- }
+ ret.second = this->priv_insert_unique_prepare(val, data);
+ ret.first = ret.second ? this->priv_insert_commit(data, val)
+ : iterator(vector_iterator_get_ptr(data.position));
return ret;
}
std::pair<iterator,bool> insert_unique(BOOST_RV_REF(value_type) val)
{
+ std::pair<iterator,bool> ret;
insert_commit_data data;
- std::pair<iterator,bool> ret = priv_insert_unique_prepare(val, data);
- if(ret.second){
- ret.first = priv_insert_commit(data, boost::move(val));
- }
+ ret.second = this->priv_insert_unique_prepare(val, data);
+ ret.first = ret.second ? this->priv_insert_commit(data, boost::move(val))
+ : iterator(vector_iterator_get_ptr(data.position));
return ret;
}
@@ -323,69 +371,134 @@ class flat_tree
iterator insert_unique(const_iterator pos, const value_type& val)
{
+ std::pair<iterator,bool> ret;
insert_commit_data data;
- std::pair<iterator,bool> ret = priv_insert_unique_prepare(pos, val, data);
- if(ret.second){
- ret.first = priv_insert_commit(data, val);
- }
- return ret.first;
+ return this->priv_insert_unique_prepare(pos, val, data)
+ ? this->priv_insert_commit(data, val)
+ : iterator(vector_iterator_get_ptr(data.position));
}
- iterator insert_unique(const_iterator pos, BOOST_RV_REF(value_type) mval)
+ iterator insert_unique(const_iterator pos, BOOST_RV_REF(value_type) val)
{
+ std::pair<iterator,bool> ret;
insert_commit_data data;
- std::pair<iterator,bool> ret = priv_insert_unique_prepare(pos, mval, data);
- if(ret.second){
- ret.first = priv_insert_commit(data, boost::move(mval));
- }
- return ret.first;
+ return this->priv_insert_unique_prepare(pos, val, data)
+ ? this->priv_insert_commit(data, boost::move(val))
+ : iterator(vector_iterator_get_ptr(data.position));
}
iterator insert_equal(const_iterator pos, const value_type& val)
{
insert_commit_data data;
this->priv_insert_equal_prepare(pos, val, data);
- return priv_insert_commit(data, val);
+ return this->priv_insert_commit(data, val);
}
iterator insert_equal(const_iterator pos, BOOST_RV_REF(value_type) mval)
{
insert_commit_data data;
this->priv_insert_equal_prepare(pos, mval, data);
- return priv_insert_commit(data, boost::move(mval));
+ return this->priv_insert_commit(data, boost::move(mval));
}
template <class InIt>
void insert_unique(InIt first, InIt last)
{
- for ( ; first != last; ++first)
+ for ( ; first != last; ++first){
this->insert_unique(*first);
+ }
}
template <class InIt>
- void insert_equal(InIt first, InIt last)
+ void insert_equal(InIt first, InIt last
+ #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+ , typename container_detail::enable_if_c
+ < container_detail::is_input_iterator<InIt>::value
+ >::type * = 0
+ #endif
+ )
+ { this->priv_insert_equal_loop(first, last); }
+
+ template <class InIt>
+ void insert_equal(InIt first, InIt last
+ #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+ , typename container_detail::enable_if_c
+ < !container_detail::is_input_iterator<InIt>::value
+ >::type * = 0
+ #endif
+ )
{
- typedef typename
- std::iterator_traits<InIt>::iterator_category ItCat;
- this->priv_insert_equal(first, last, ItCat());
+ const size_type len = static_cast<size_type>(std::distance(first, last));
+ this->reserve(this->size()+len);
+ this->priv_insert_equal_loop(first, last);
}
+ //Ordered
+
template <class InIt>
- void insert_equal(ordered_range_t, InIt first, InIt last)
+ void insert_equal(ordered_range_t, InIt first, InIt last
+ #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+ , typename container_detail::enable_if_c
+ < container_detail::is_input_iterator<InIt>::value
+ >::type * = 0
+ #endif
+ )
+ { this->priv_insert_equal_loop_ordered(first, last); }
+
+ template <class FwdIt>
+ void insert_equal(ordered_range_t, FwdIt first, FwdIt last
+ #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+ , typename container_detail::enable_if_c
+ < !container_detail::is_input_iterator<FwdIt>::value &&
+ container_detail::is_forward_iterator<FwdIt>::value
+ >::type * = 0
+ #endif
+ )
{
- typedef typename
- std::iterator_traits<InIt>::iterator_category ItCat;
- this->priv_insert_equal(ordered_range_t(), first, last, ItCat());
+ const size_type len = static_cast<size_type>(std::distance(first, last));
+ this->reserve(this->size()+len);
+ this->priv_insert_equal_loop_ordered(first, last);
}
+ template <class BidirIt>
+ void insert_equal(ordered_range_t, BidirIt first, BidirIt last
+ #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+ , typename container_detail::enable_if_c
+ < !container_detail::is_input_iterator<BidirIt>::value &&
+ !container_detail::is_forward_iterator<BidirIt>::value
+ >::type * = 0
+ #endif
+ )
+ { this->priv_insert_ordered_range(false, first, last); }
+
template <class InIt>
- void insert_unique(ordered_unique_range_t, InIt first, InIt last)
- {
- typedef typename
- std::iterator_traits<InIt>::iterator_category ItCat;
- this->priv_insert_unique(ordered_unique_range_t(), first, last, ItCat());
+ void insert_unique(ordered_unique_range_t, InIt first, InIt last
+ #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+ , typename container_detail::enable_if_c
+ < container_detail::is_input_iterator<InIt>::value ||
+ container_detail::is_forward_iterator<InIt>::value
+ >::type * = 0
+ #endif
+ )
+ {
+ const_iterator pos(this->cend());
+ for ( ; first != last; ++first){
+ pos = this->insert_unique(pos, *first);
+ ++pos;
+ }
}
+ template <class BidirIt>
+ void insert_unique(ordered_unique_range_t, BidirIt first, BidirIt last
+ #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+ , typename container_detail::enable_if_c
+ < !(container_detail::is_input_iterator<BidirIt>::value ||
+ container_detail::is_forward_iterator<BidirIt>::value)
+ >::type * = 0
+ #endif
+ )
+ { this->priv_insert_ordered_range(true, first, last); }
+
#ifdef BOOST_CONTAINER_PERFECT_FORWARDING
template <class... Args>
@@ -396,13 +509,7 @@ class flat_tree
stored_allocator_type &a = this->get_stored_allocator();
stored_allocator_traits::construct(a, &val, ::boost::forward<Args>(args)... );
value_destructor<stored_allocator_type> d(a, val);
- insert_commit_data data;
- std::pair<iterator,bool> ret =
- priv_insert_unique_prepare(val, data);
- if(ret.second){
- ret.first = priv_insert_commit(data, boost::move(val));
- }
- return ret;
+ return this->insert_unique(::boost::move(val));
}
template <class... Args>
@@ -413,12 +520,7 @@ class flat_tree
stored_allocator_type &a = this->get_stored_allocator();
stored_allocator_traits::construct(a, &val, ::boost::forward<Args>(args)... );
value_destructor<stored_allocator_type> d(a, val);
- insert_commit_data data;
- std::pair<iterator,bool> ret = priv_insert_unique_prepare(hint, val, data);
- if(ret.second){
- ret.first = priv_insert_commit(data, boost::move(val));
- }
- return ret.first;
+ return this->insert_unique(hint, ::boost::move(val));
}
template <class... Args>
@@ -429,9 +531,7 @@ class flat_tree
stored_allocator_type &a = this->get_stored_allocator();
stored_allocator_traits::construct(a, &val, ::boost::forward<Args>(args)... );
value_destructor<stored_allocator_type> d(a, val);
- iterator i = this->upper_bound(KeyOfValue()(val));
- i = this->m_data.m_vect.insert(i, boost::move(val));
- return i;
+ return this->insert_equal(::boost::move(val));
}
template <class... Args>
@@ -442,10 +542,7 @@ class flat_tree
stored_allocator_type &a = this->get_stored_allocator();
stored_allocator_traits::construct(a, &val, ::boost::forward<Args>(args)... );
value_destructor<stored_allocator_type> d(a, val);
- insert_commit_data data;
- this->priv_insert_equal_prepare(hint, val, data);
- iterator i = priv_insert_commit(data, boost::move(val));
- return i;
+ return this->insert_equal(hint, ::boost::move(val));
}
#else //#ifdef BOOST_CONTAINER_PERFECT_FORWARDING
@@ -461,12 +558,7 @@ class flat_tree
stored_allocator_traits::construct(a, &val \
BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _) ); \
value_destructor<stored_allocator_type> d(a, val); \
- insert_commit_data data; \
- std::pair<iterator,bool> ret = priv_insert_unique_prepare(val, data); \
- if(ret.second){ \
- ret.first = priv_insert_commit(data, boost::move(val)); \
- } \
- return ret; \
+ return this->insert_unique(::boost::move(val)); \
} \
\
BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, >) \
@@ -478,13 +570,8 @@ class flat_tree
stored_allocator_type &a = this->get_stored_allocator(); \
stored_allocator_traits::construct(a, &val \
BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _) ); \
- value_destructor<stored_allocator_type> d(a, val); \
- insert_commit_data data; \
- std::pair<iterator,bool> ret = priv_insert_unique_prepare(hint, val, data); \
- if(ret.second){ \
- ret.first = priv_insert_commit(data, boost::move(val)); \
- } \
- return ret.first; \
+ value_destructor<stored_allocator_type> d(a, val); \
+ return this->insert_unique(hint, ::boost::move(val)); \
} \
\
BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, >) \
@@ -496,9 +583,7 @@ class flat_tree
stored_allocator_traits::construct(a, &val \
BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _) ); \
value_destructor<stored_allocator_type> d(a, val); \
- iterator i = this->upper_bound(KeyOfValue()(val)); \
- i = this->m_data.m_vect.insert(i, boost::move(val)); \
- return i; \
+ return this->insert_equal(::boost::move(val)); \
} \
\
BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, >) \
@@ -511,12 +596,8 @@ class flat_tree
stored_allocator_traits::construct(a, &val \
BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _) ); \
value_destructor<stored_allocator_type> d(a, val); \
- insert_commit_data data; \
- this->priv_insert_equal_prepare(hint, val, data); \
- iterator i = priv_insert_commit(data, boost::move(val)); \
- return i; \
+ return this->insert_equal(hint, ::boost::move(val)); \
} \
-
//!
#define BOOST_PP_LOCAL_LIMITS (0, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS)
#include BOOST_PP_LOCAL_ITERATE()
@@ -554,26 +635,26 @@ class flat_tree
// set operations:
iterator find(const key_type& k)
{
- const Compare &key_comp = this->m_data.get_comp();
iterator i = this->lower_bound(k);
-
- if (i != this->end() && key_comp(k, KeyOfValue()(*i))){
- i = this->end();
+ iterator end_it = this->end();
+ if (i != end_it && this->m_data.get_comp()(k, KeyOfValue()(*i))){
+ i = end_it;
}
return i;
}
const_iterator find(const key_type& k) const
{
- const Compare &key_comp = this->m_data.get_comp();
const_iterator i = this->lower_bound(k);
- if (i != this->end() && key_comp(k, KeyOfValue()(*i))){
- i = this->end();
+ const_iterator end_it = this->cend();
+ if (i != end_it && this->m_data.get_comp()(k, KeyOfValue()(*i))){
+ i = end_it;
}
return i;
}
+ // set operations:
size_type count(const key_type& k) const
{
std::pair<const_iterator, const_iterator> p = this->equal_range(k);
@@ -585,25 +666,57 @@ class flat_tree
{ return this->priv_lower_bound(this->begin(), this->end(), k); }
const_iterator lower_bound(const key_type& k) const
- { return this->priv_lower_bound(this->begin(), this->end(), k); }
+ { return this->priv_lower_bound(this->cbegin(), this->cend(), k); }
iterator upper_bound(const key_type& k)
{ return this->priv_upper_bound(this->begin(), this->end(), k); }
const_iterator upper_bound(const key_type& k) const
- { return this->priv_upper_bound(this->begin(), this->end(), k); }
+ { return this->priv_upper_bound(this->cbegin(), this->cend(), k); }
std::pair<iterator,iterator> equal_range(const key_type& k)
{ return this->priv_equal_range(this->begin(), this->end(), k); }
std::pair<const_iterator, const_iterator> equal_range(const key_type& k) const
- { return this->priv_equal_range(this->begin(), this->end(), k); }
+ { return this->priv_equal_range(this->cbegin(), this->cend(), k); }
+
+ std::pair<iterator, iterator> lower_bound_range(const key_type& k)
+ { return this->priv_lower_bound_range(this->begin(), this->end(), k); }
+
+ std::pair<const_iterator, const_iterator> lower_bound_range(const key_type& k) const
+ { return this->priv_lower_bound_range(this->cbegin(), this->cend(), k); }
- size_type capacity() const
+ size_type capacity() const
{ return this->m_data.m_vect.capacity(); }
- void reserve(size_type count)
- { this->m_data.m_vect.reserve(count); }
+ void reserve(size_type cnt)
+ { this->m_data.m_vect.reserve(cnt); }
+
+ friend bool operator==(const flat_tree& x, const flat_tree& y)
+ {
+ return x.size() == y.size() && std::equal(x.begin(), x.end(), y.begin());
+ }
+
+ friend bool operator<(const flat_tree& x, const flat_tree& y)
+ {
+ return std::lexicographical_compare(x.begin(), x.end(),
+ y.begin(), y.end());
+ }
+
+ friend bool operator!=(const flat_tree& x, const flat_tree& y)
+ { return !(x == y); }
+
+ friend bool operator>(const flat_tree& x, const flat_tree& y)
+ { return y < x; }
+
+ friend bool operator<=(const flat_tree& x, const flat_tree& y)
+ { return !(y < x); }
+
+ friend bool operator>=(const flat_tree& x, const flat_tree& y)
+ { return !(x < y); }
+
+ friend void swap(flat_tree& x, flat_tree& y)
+ { x.swap(y); }
private:
struct insert_commit_data
@@ -624,10 +737,10 @@ class flat_tree
// insert val before upper_bound(val)
// else
// insert val before lower_bound(val)
- const value_compare &value_comp = this->m_data;
+ const value_compare &val_cmp = this->m_data;
- if(pos == this->cend() || !value_comp(*pos, val)){
- if (pos == this->cbegin() || !value_comp(val, pos[-1])){
+ if(pos == this->cend() || !val_cmp(*pos, val)){
+ if (pos == this->cbegin() || !val_cmp(val, pos[-1])){
data.position = pos;
}
else{
@@ -641,21 +754,19 @@ class flat_tree
}
}
- std::pair<iterator,bool> priv_insert_unique_prepare
- (const_iterator beg, const_iterator end, const value_type& val, insert_commit_data &commit_data)
+ bool priv_insert_unique_prepare
+ (const_iterator b, const_iterator e, const value_type& val, insert_commit_data &commit_data)
{
- const value_compare &value_comp = this->m_data;
- commit_data.position = this->priv_lower_bound(beg, end, KeyOfValue()(val));
- return std::pair<iterator,bool>
- ( *reinterpret_cast<iterator*>(&commit_data.position)
- , commit_data.position == end || value_comp(val, *commit_data.position));
+ const value_compare &val_cmp = this->m_data;
+ commit_data.position = this->priv_lower_bound(b, e, KeyOfValue()(val));
+ return commit_data.position == e || val_cmp(val, *commit_data.position);
}
- std::pair<iterator,bool> priv_insert_unique_prepare
+ bool priv_insert_unique_prepare
(const value_type& val, insert_commit_data &commit_data)
- { return priv_insert_unique_prepare(this->begin(), this->end(), val, commit_data); }
+ { return this->priv_insert_unique_prepare(this->cbegin(), this->cend(), val, commit_data); }
- std::pair<iterator,bool> priv_insert_unique_prepare
+ bool priv_insert_unique_prepare
(const_iterator pos, const value_type& val, insert_commit_data &commit_data)
{
//N1780. Props to Howard Hinnant!
@@ -669,37 +780,32 @@ class flat_tree
// insert val after pos
//else
// insert val before lower_bound(val)
- const value_compare &value_comp = this->m_data;
-
- if(pos == this->cend() || value_comp(val, *pos)){
- 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);
- }
- else{
- return std::pair<iterator,bool>(*reinterpret_cast<iterator*>(&pos), false);
- }
+ const value_compare &val_cmp = this->m_data;
+ const const_iterator cend_it = this->cend();
+ if(pos == cend_it || val_cmp(val, *pos)){ //Check if val should go before end
+ const const_iterator cbeg = this->cbegin();
+ commit_data.position = pos;
+ if(pos == cbeg){ //If container is empty then insert it in the beginning
+ return true;
+ }
+ const_iterator prev(pos);
+ --prev;
+ if(val_cmp(*prev, val)){ //If previous element was less, then it should go between prev and pos
+ return true;
+ }
+ else if(!val_cmp(val, *prev)){ //If previous was equal then insertion should fail
+ commit_data.position = prev;
+ return false;
+ }
+ else{ //Previous was bigger so insertion hint was pointless, dispatch to hintless insertion
+ //but reduce the search between beg and prev as prev is bigger than val
+ return this->priv_insert_unique_prepare(cbeg, prev, val, commit_data);
}
- return this->priv_insert_unique_prepare(this->cbegin(), pos, val, commit_data);
}
-
- // Works, but increases code complexity
- //Next check
- //else if (value_comp(*pos, val) && !value_comp(pos[1], val)){
- // if(value_comp(val, pos[1])){
- // commit_data.position = pos+1;
- // return std::pair<iterator,bool>(pos+1, true);
- // }
- // else{
- // return std::pair<iterator,bool>(pos+1, false);
- // }
- //}
else{
- //[... pos ... val ... ]
//The hint is before the insertion position, so insert it
- //in the remaining range
- return this->priv_insert_unique_prepare(pos, this->end(), val, commit_data);
+ //in the remaining range [pos, end)
+ return this->priv_insert_unique_prepare(pos, cend_it, val, commit_data);
}
}
@@ -713,50 +819,50 @@ class flat_tree
}
template <class RanIt>
- RanIt priv_lower_bound(RanIt first, RanIt last,
+ RanIt priv_lower_bound(RanIt first, const RanIt last,
const key_type & key) const
{
- const Compare &key_comp = this->m_data.get_comp();
+ const Compare &key_cmp = this->m_data.get_comp();
KeyOfValue key_extract;
- difference_type len = last - first, half;
+ size_type len = static_cast<size_type>(last - first);
RanIt middle;
- while (len > 0) {
- half = len >> 1;
+ while (len) {
+ size_type step = len >> 1;
middle = first;
- middle += half;
+ middle += step;
- if (key_comp(key_extract(*middle), key)) {
- ++middle;
- first = middle;
- len = len - half - 1;
+ if (key_cmp(key_extract(*middle), key)) {
+ first = ++middle;
+ len -= step + 1;
+ }
+ else{
+ len = step;
}
- else
- len = half;
}
return first;
}
template <class RanIt>
- RanIt priv_upper_bound(RanIt first, RanIt last,
+ RanIt priv_upper_bound(RanIt first, const RanIt last,
const key_type & key) const
{
- const Compare &key_comp = this->m_data.get_comp();
+ const Compare &key_cmp = this->m_data.get_comp();
KeyOfValue key_extract;
- difference_type len = last - first, half;
+ size_type len = static_cast<size_type>(last - first);
RanIt middle;
- while (len > 0) {
- half = len >> 1;
+ while (len) {
+ size_type step = len >> 1;
middle = first;
- middle += half;
+ middle += step;
- if (key_comp(key, key_extract(*middle))) {
- len = half;
+ if (key_cmp(key, key_extract(*middle))) {
+ len = step;
}
else{
first = ++middle;
- len = len - half - 1;
+ len -= step + 1;
}
}
return first;
@@ -766,189 +872,135 @@ class flat_tree
std::pair<RanIt, RanIt>
priv_equal_range(RanIt first, RanIt last, const key_type& key) const
{
- const Compare &key_comp = this->m_data.get_comp();
+ const Compare &key_cmp = this->m_data.get_comp();
KeyOfValue key_extract;
- difference_type len = last - first, half;
- RanIt middle, left, right;
+ size_type len = static_cast<size_type>(last - first);
+ RanIt middle;
- while (len > 0) {
- half = len >> 1;
+ while (len) {
+ size_type step = len >> 1;
middle = first;
- middle += half;
+ middle += step;
- if (key_comp(key_extract(*middle), key)){
- first = middle;
- ++first;
- len = len - half - 1;
+ if (key_cmp(key_extract(*middle), key)){
+ first = ++middle;
+ len -= step + 1;
}
- else if (key_comp(key, key_extract(*middle))){
- len = half;
+ else if (key_cmp(key, key_extract(*middle))){
+ len = step;
}
else {
- left = this->priv_lower_bound(first, middle, key);
- first += len;
- right = this->priv_upper_bound(++middle, first, key);
- return std::pair<RanIt, RanIt>(left, right);
+ //Middle is equal to key
+ last = first;
+ last += len;
+ return std::pair<RanIt, RanIt>
+ ( this->priv_lower_bound(first, middle, key)
+ , this->priv_upper_bound(++middle, last, key));
}
}
return std::pair<RanIt, RanIt>(first, first);
}
- template <class BidirIt>
- void priv_insert_equal(ordered_range_t, BidirIt first, BidirIt last, std::bidirectional_iterator_tag)
+ template<class RanIt>
+ std::pair<RanIt, RanIt> priv_lower_bound_range(RanIt first, RanIt last, const key_type& k) const
{
- size_type len = static_cast<size_type>(std::distance(first, last));
- const size_type BurstSize = 16;
- size_type positions[BurstSize];
+ const Compare &key_cmp = this->m_data.get_comp();
+ KeyOfValue key_extract;
+ RanIt lb(this->priv_lower_bound(first, last, k)), ub(lb);
+ if(lb != last && static_cast<difference_type>(!key_cmp(k, key_extract(*lb)))){
+ ++ub;
+ }
+ return std::pair<RanIt, RanIt>(lb, ub);
+ }
- //Prereserve all memory so that iterators are not invalidated
- this->reserve(this->size()+len);
- const const_iterator beg(this->cbegin());
- const_iterator pos(beg);
- //Loop in burst sizes
- while(len){
- const size_type burst = len < BurstSize ? len : BurstSize;
- const const_iterator cend(this->cend());
- len -= burst;
- for(size_type i = 0; i != burst; ++i){
- //Get the insertion position for each key
- pos = const_cast<const flat_tree&>(*this).priv_upper_bound(pos, cend, KeyOfValue()(*first));
- positions[i] = static_cast<size_type>(pos - beg);
- ++first;
- }
- //Insert all in a single step in the precalculated positions
- this->m_data.m_vect.insert_ordered_at(burst, positions + burst, first);
- //Next search position updated
- pos += burst;
+ template<class InIt>
+ void priv_insert_equal_loop(InIt first, InIt last)
+ {
+ for ( ; first != last; ++first){
+ this->insert_equal(*first);
+ }
+ }
+
+ template<class InIt>
+ void priv_insert_equal_loop_ordered(InIt first, InIt last)
+ {
+ const_iterator pos(this->cend());
+ for ( ; first != last; ++first){
+ //If ordered, then try hint version
+ //to achieve constant-time complexity per insertion
+ pos = this->insert_equal(pos, *first);
+ ++pos;
}
}
template <class BidirIt>
- void priv_insert_unique(ordered_unique_range_t, BidirIt first, BidirIt last, std::bidirectional_iterator_tag)
+ void priv_insert_ordered_range(const bool unique_values, BidirIt first, BidirIt last)
{
size_type len = static_cast<size_type>(std::distance(first, last));
- const size_type BurstSize = 16;
- size_type positions[BurstSize];
- size_type skips[BurstSize];
-
//Prereserve all memory so that iterators are not invalidated
this->reserve(this->size()+len);
- const const_iterator beg(this->cbegin());
- const_iterator pos(beg);
- const value_compare &value_comp = this->m_data;
+ //Auxiliary data for insertion positions.
+ const size_type BurstSize = len;
+ const ::boost::movelib::unique_ptr<size_type[]> positions =
+ ::boost::movelib::make_unique_definit<size_type[]>(BurstSize);
+
+ const const_iterator b(this->cbegin());
+ const const_iterator ce(this->cend());
+ const_iterator pos(b);
+ const value_compare &val_cmp = this->m_data;
//Loop in burst sizes
- while(len){
- skips[0u] = 0u;
+ bool back_insert = false;
+ while(len && !back_insert){
const size_type burst = len < BurstSize ? len : BurstSize;
size_type unique_burst = 0u;
- const const_iterator cend(this->cend());
- while(unique_burst < burst && len > 0){
- //Get the insertion position for each key
- const value_type & val = *first++;
- --len;
- pos = const_cast<const flat_tree&>(*this).priv_lower_bound(pos, cend, KeyOfValue()(val));
+ size_type checked = 0;
+ for(; checked != burst; ++checked){
+ //Get the insertion position for each key, use std::iterator_traits<BidirIt>::value_type
+ //because it can be different from container::value_type
+ //(e.g. conversion between std::pair<A, B> -> boost::container::pair<A, B>
+ const typename std::iterator_traits<BidirIt>::value_type & val = *first;
+ pos = const_cast<const flat_tree&>(*this).priv_lower_bound(pos, ce, KeyOfValue()(val));
//Check if already present
- if(pos != cend && !value_comp(*pos, val)){
- ++skips[unique_burst];
- continue;
+ if (pos != ce){
+ ++first;
+ --len;
+ positions[checked] = (unique_values && !val_cmp(val, *pos)) ?
+ size_type(-1) : (++unique_burst, static_cast<size_type>(pos - b));
}
-
- //If not present, calculate position
- positions[unique_burst] = static_cast<size_type>(pos - beg);
- if(++unique_burst < burst)
- skips[unique_burst] = 0u;
+ else{ //this element and the remaining should be back inserted
+ back_insert = true;
+ break;
+ }
+ }
+ if(unique_burst){
+ //Insert all in a single step in the precalculated positions
+ this->m_data.m_vect.insert_ordered_at(unique_burst, positions.get() + checked, first);
+ //Next search position updated, iterator still valid because we've preserved the vector
+ pos += unique_burst;
}
- //Insert all in a single step in the precalculated positions
- this->m_data.m_vect.insert_ordered_at(unique_burst, positions + unique_burst, skips + unique_burst, first);
- //Next search position updated
- pos += unique_burst;
}
- }
-/*
- template <class FwdIt>
- void priv_insert_equal_forward(ordered_range_t, FwdIt first, FwdIt last, std::forward_iterator_tag)
- { this->priv_insert_equal(first, last, std::forward_iterator_tag()); }
-*/
- template <class InIt>
- void priv_insert_equal(ordered_range_t, InIt first, InIt last, std::input_iterator_tag)
- { this->priv_insert_equal(first, last, std::input_iterator_tag()); }
-
- template <class InIt>
- void priv_insert_unique(ordered_unique_range_t, InIt first, InIt last, std::input_iterator_tag)
- { this->priv_insert_unique(first, last, std::input_iterator_tag()); }
-/*
- template <class FwdIt>
- void priv_insert_equal_forward(FwdIt first, FwdIt last, std::forward_iterator_tag)
- {
- const size_type len = static_cast<size_type>(std::distance(first, last));
- this->reserve(this->size()+len);
- this->priv_insert_equal(first, last, std::input_iterator_tag());
- }
-*/
- template <class InIt>
- void priv_insert_equal(InIt first, InIt last, std::input_iterator_tag)
- {
- for ( ; first != last; ++first)
- this->insert_equal(*first);
+ //The remaining range should be back inserted
+ if(unique_values){
+ while(len--){
+ BidirIt next(first);
+ ++next;
+ if(next == last || val_cmp(*first, *next)){
+ const bool room = this->m_data.m_vect.stable_emplace_back(*first);
+ (void)room;
+ BOOST_ASSERT(room);
+ }
+ first = next;
+ }
+ BOOST_ASSERT(first == last);
+ }
+ else{
+ BOOST_ASSERT(size_type(std::distance(first, last)) == len);
+ if(len)
+ this->m_data.m_vect.insert(this->m_data.m_vect.cend(), len, first, last);
+ }
}
};
-template <class Key, class Value, class KeyOfValue,
- class Compare, class A>
-inline bool
-operator==(const flat_tree<Key,Value,KeyOfValue,Compare,A>& x,
- const flat_tree<Key,Value,KeyOfValue,Compare,A>& y)
-{
- return x.size() == y.size() &&
- std::equal(x.begin(), x.end(), y.begin());
-}
-
-template <class Key, class Value, class KeyOfValue,
- class Compare, class A>
-inline bool
-operator<(const flat_tree<Key,Value,KeyOfValue,Compare,A>& x,
- const flat_tree<Key,Value,KeyOfValue,Compare,A>& y)
-{
- return std::lexicographical_compare(x.begin(), x.end(),
- y.begin(), y.end());
-}
-
-template <class Key, class Value, class KeyOfValue,
- class Compare, class A>
-inline bool
-operator!=(const flat_tree<Key,Value,KeyOfValue,Compare,A>& x,
- const flat_tree<Key,Value,KeyOfValue,Compare,A>& y)
- { return !(x == y); }
-
-template <class Key, class Value, class KeyOfValue,
- class Compare, class A>
-inline bool
-operator>(const flat_tree<Key,Value,KeyOfValue,Compare,A>& x,
- const flat_tree<Key,Value,KeyOfValue,Compare,A>& y)
- { return y < x; }
-
-template <class Key, class Value, class KeyOfValue,
- class Compare, class A>
-inline bool
-operator<=(const flat_tree<Key,Value,KeyOfValue,Compare,A>& x,
- const flat_tree<Key,Value,KeyOfValue,Compare,A>& y)
- { return !(y < x); }
-
-template <class Key, class Value, class KeyOfValue,
- class Compare, class A>
-inline bool
-operator>=(const flat_tree<Key,Value,KeyOfValue,Compare,A>& x,
- const flat_tree<Key,Value,KeyOfValue,Compare,A>& y)
- { return !(x < y); }
-
-
-template <class Key, class Value, class KeyOfValue,
- class Compare, class A>
-inline void
-swap(flat_tree<Key,Value,KeyOfValue,Compare,A>& x,
- flat_tree<Key,Value,KeyOfValue,Compare,A>& y)
- { x.swap(y); }
-
} //namespace container_detail {
} //namespace container {
@@ -959,7 +1011,7 @@ template <class K, class V, class KOV,
class C, class A>
struct has_trivial_destructor_after_move<boost::container::container_detail::flat_tree<K, V, KOV, C, A> >
{
- static const bool value = has_trivial_destructor<A>::value && has_trivial_destructor<C>::value;
+ static const bool value = has_trivial_destructor_after_move<A>::value && has_trivial_destructor_after_move<C>::value;
};
*/
} //namespace boost {
diff --git a/boost/container/detail/function_detector.hpp b/boost/container/detail/function_detector.hpp
index 5a5f6fd77d..242eb41352 100644
--- a/boost/container/detail/function_detector.hpp
+++ b/boost/container/detail/function_detector.hpp
@@ -1,6 +1,6 @@
/////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2009-2012.
+// (C) Copyright Ion Gaztanaga 2009-2013.
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
@@ -22,6 +22,10 @@
#ifndef BOOST_CONTAINER_DETAIL_FUNCTION_DETECTOR_HPP
#define BOOST_CONTAINER_DETAIL_FUNCTION_DETECTOR_HPP
+#if defined(_MSC_VER)
+# pragma once
+#endif
+
#include <boost/container/detail/config_begin.hpp>
namespace boost {
diff --git a/boost/container/detail/hash_table.hpp b/boost/container/detail/hash_table.hpp
new file mode 100644
index 0000000000..da7bb536e4
--- /dev/null
+++ b/boost/container/detail/hash_table.hpp
@@ -0,0 +1,383 @@
+/*
+template <class Value, unsigned int Options = 0, class Hash = hash<Value>, class Pred = equal_to<Value>,
+ class Alloc = allocator<Value> >
+class hash_set
+{
+public:
+ // types
+ typedef Value key_type;
+ typedef key_type value_type;
+ typedef Hash hasher;
+ typedef Pred key_equal;
+ typedef Alloc allocator_type;
+ typedef value_type& reference;
+ typedef const value_type& const_reference;
+ typedef typename allocator_traits<allocator_type>::pointer pointer;
+ typedef typename allocator_traits<allocator_type>::const_pointer const_pointer;
+ typedef typename allocator_traits<allocator_type>::size_type size_type;
+ typedef typename allocator_traits<allocator_type>::difference_type difference_type;
+
+ typedef /unspecified/ iterator;
+ typedef /unspecified/ const_iterator;
+ typedef /unspecified/ local_iterator;
+ typedef /unspecified/ const_local_iterator;
+
+ hash_set()
+ noexcept(
+ is_nothrow_default_constructible<hasher>::value &&
+ is_nothrow_default_constructible<key_equal>::value &&
+ is_nothrow_default_constructible<allocator_type>::value);
+ explicit hash_set(size_type n, const hasher& hf = hasher(),
+ const key_equal& eql = key_equal(),
+ const allocator_type& a = allocator_type());
+ template <class InputIterator>
+ hash_set(InputIterator f, InputIterator l,
+ size_type n = 0, const hasher& hf = hasher(),
+ const key_equal& eql = key_equal(),
+ const allocator_type& a = allocator_type());
+ explicit hash_set(const allocator_type&);
+ hash_set(const hash_set&);
+ hash_set(const hash_set&, const Allocator&);
+ hash_set(hash_set&&)
+ noexcept(
+ is_nothrow_move_constructible<hasher>::value &&
+ is_nothrow_move_constructible<key_equal>::value &&
+ is_nothrow_move_constructible<allocator_type>::value);
+ hash_set(hash_set&&, const Allocator&);
+ hash_set(initializer_list<value_type>, size_type n = 0,
+ const hasher& hf = hasher(), const key_equal& eql = key_equal(),
+ const allocator_type& a = allocator_type());
+ ~hash_set();
+ hash_set& operator=(const hash_set&);
+ hash_set& operator=(hash_set&&)
+ noexcept(
+ allocator_type::propagate_on_container_move_assignment::value &&
+ is_nothrow_move_assignable<allocator_type>::value &&
+ is_nothrow_move_assignable<hasher>::value &&
+ is_nothrow_move_assignable<key_equal>::value);
+ hash_set& operator=(initializer_list<value_type>);
+
+ allocator_type get_allocator() const noexcept;
+
+ bool empty() const noexcept;
+ size_type size() const noexcept;
+ size_type max_size() const noexcept;
+
+ iterator begin() noexcept;
+ iterator end() noexcept;
+ const_iterator begin() const noexcept;
+ const_iterator end() const noexcept;
+ const_iterator cbegin() const noexcept;
+ const_iterator cend() const noexcept;
+
+ template <class... Args>
+ pair<iterator, bool> emplace(Args&&... args);
+ template <class... Args>
+ iterator emplace_hint(const_iterator position, Args&&... args);
+ pair<iterator, bool> insert(const value_type& obj);
+ pair<iterator, bool> insert(value_type&& obj);
+ iterator insert(const_iterator hint, const value_type& obj);
+ iterator insert(const_iterator hint, value_type&& obj);
+ template <class InputIterator>
+ void insert(InputIterator first, InputIterator last);
+ void insert(initializer_list<value_type>);
+
+ iterator erase(const_iterator position);
+ size_type erase(const key_type& k);
+ iterator erase(const_iterator first, const_iterator last);
+ void clear() noexcept;
+
+ void swap(hash_set&)
+ noexcept(
+ (!allocator_type::propagate_on_container_swap::value ||
+ __is_nothrow_swappable<allocator_type>::value) &&
+ __is_nothrow_swappable<hasher>::value &&
+ __is_nothrow_swappable<key_equal>::value);
+
+ hasher hash_function() const;
+ key_equal key_eq() const;
+
+ iterator find(const key_type& k);
+ const_iterator find(const key_type& k) const;
+ size_type count(const key_type& k) const;
+ pair<iterator, iterator> equal_range(const key_type& k);
+ pair<const_iterator, const_iterator> equal_range(const key_type& k) const;
+
+ size_type bucket_count() const noexcept;
+ size_type max_bucket_count() const noexcept;
+
+ size_type bucket_size(size_type n) const;
+ size_type bucket(const key_type& k) const;
+
+ local_iterator begin(size_type n);
+ local_iterator end(size_type n);
+ const_local_iterator begin(size_type n) const;
+ const_local_iterator end(size_type n) const;
+ const_local_iterator cbegin(size_type n) const;
+ const_local_iterator cend(size_type n) const;
+
+ float load_factor() const noexcept;
+ float max_load_factor() const noexcept;
+ void max_load_factor(float z);
+ void rehash(size_type n);
+ void reserve(size_type n);
+};
+
+template <class Key, class T, unsigned int Options = 0, class Hash = hash<Key>, class Pred = equal_to<Key>,
+ class Alloc = allocator<pair<const Key, T> > >
+class hash_map
+{
+public:
+ // types
+ typedef Key key_type;
+ typedef T mapped_type;
+ typedef Hash hasher;
+ typedef Pred key_equal;
+ typedef Alloc allocator_type;
+ typedef pair<const key_type, mapped_type> value_type;
+ typedef value_type& reference;
+ typedef const value_type& const_reference;
+ typedef typename allocator_traits<allocator_type>::pointer pointer;
+ typedef typename allocator_traits<allocator_type>::const_pointer const_pointer;
+ typedef typename allocator_traits<allocator_type>::size_type size_type;
+ typedef typename allocator_traits<allocator_type>::difference_type difference_type;
+
+ typedef /unspecified/ iterator;
+ typedef /unspecified/ const_iterator;
+ typedef /unspecified/ local_iterator;
+ typedef /unspecified/ const_local_iterator;
+
+ hash_map()
+ noexcept(
+ is_nothrow_default_constructible<hasher>::value &&
+ is_nothrow_default_constructible<key_equal>::value &&
+ is_nothrow_default_constructible<allocator_type>::value);
+ explicit hash_map(size_type n, const hasher& hf = hasher(),
+ const key_equal& eql = key_equal(),
+ const allocator_type& a = allocator_type());
+ template <class InputIterator>
+ hash_map(InputIterator f, InputIterator l,
+ size_type n = 0, const hasher& hf = hasher(),
+ const key_equal& eql = key_equal(),
+ const allocator_type& a = allocator_type());
+ explicit hash_map(const allocator_type&);
+ hash_map(const hash_map&);
+ hash_map(const hash_map&, const Allocator&);
+ hash_map(hash_map&&)
+ noexcept(
+ is_nothrow_move_constructible<hasher>::value &&
+ is_nothrow_move_constructible<key_equal>::value &&
+ is_nothrow_move_constructible<allocator_type>::value);
+ hash_map(hash_map&&, const Allocator&);
+ hash_map(initializer_list<value_type>, size_type n = 0,
+ const hasher& hf = hasher(), const key_equal& eql = key_equal(),
+ const allocator_type& a = allocator_type());
+ ~hash_map();
+ hash_map& operator=(const hash_map&);
+ hash_map& operator=(hash_map&&)
+ noexcept(
+ allocator_type::propagate_on_container_move_assignment::value &&
+ is_nothrow_move_assignable<allocator_type>::value &&
+ is_nothrow_move_assignable<hasher>::value &&
+ is_nothrow_move_assignable<key_equal>::value);
+ hash_map& operator=(initializer_list<value_type>);
+
+ allocator_type get_allocator() const noexcept;
+
+ bool empty() const noexcept;
+ size_type size() const noexcept;
+ size_type max_size() const noexcept;
+
+ iterator begin() noexcept;
+ iterator end() noexcept;
+ const_iterator begin() const noexcept;
+ const_iterator end() const noexcept;
+ const_iterator cbegin() const noexcept;
+ const_iterator cend() const noexcept;
+
+ template <class... Args>
+ pair<iterator, bool> emplace(Args&&... args);
+ template <class... Args>
+ iterator emplace_hint(const_iterator position, Args&&... args);
+ pair<iterator, bool> insert(const value_type& obj);
+ template <class P>
+ pair<iterator, bool> insert(P&& obj);
+ iterator insert(const_iterator hint, const value_type& obj);
+ template <class P>
+ iterator insert(const_iterator hint, P&& obj);
+ template <class InputIterator>
+ void insert(InputIterator first, InputIterator last);
+ void insert(initializer_list<value_type>);
+
+ iterator erase(const_iterator position);
+ size_type erase(const key_type& k);
+ iterator erase(const_iterator first, const_iterator last);
+ void clear() noexcept;
+
+ void swap(hash_map&)
+ noexcept(
+ (!allocator_type::propagate_on_container_swap::value ||
+ __is_nothrow_swappable<allocator_type>::value) &&
+ __is_nothrow_swappable<hasher>::value &&
+ __is_nothrow_swappable<key_equal>::value);
+
+ hasher hash_function() const;
+ key_equal key_eq() const;
+
+ iterator find(const key_type& k);
+ const_iterator find(const key_type& k) const;
+ size_type count(const key_type& k) const;
+ pair<iterator, iterator> equal_range(const key_type& k);
+ pair<const_iterator, const_iterator> equal_range(const key_type& k) const;
+
+ mapped_type& operator[](const key_type& k);
+ mapped_type& operator[](key_type&& k);
+
+ mapped_type& at(const key_type& k);
+ const mapped_type& at(const key_type& k) const;
+
+ size_type bucket_count() const noexcept;
+ size_type max_bucket_count() const noexcept;
+
+ size_type bucket_size(size_type n) const;
+ size_type bucket(const key_type& k) const;
+
+ local_iterator begin(size_type n);
+ local_iterator end(size_type n);
+ const_local_iterator begin(size_type n) const;
+ const_local_iterator end(size_type n) const;
+ const_local_iterator cbegin(size_type n) const;
+ const_local_iterator cend(size_type n) const;
+
+ float load_factor() const noexcept;
+ float max_load_factor() const noexcept;
+ void max_load_factor(float z);
+ void rehash(size_type n);
+ void reserve(size_type n);
+};
+
+*/
+
+template <class Key, class Value, class KeyOfValue, unsigned int Options = 0, class Hash = hash<Key>, class Pred = equal_to<Key>,
+ class Alloc = allocator<Value> >
+class hash_table
+{
+public:
+ // types
+ typedef Value key_type;
+ typedef key_type value_type;
+ typedef Hash hasher;
+ typedef Pred key_equal;
+ typedef Alloc allocator_type;
+ typedef value_type& reference;
+ typedef const value_type& const_reference;
+ typedef typename allocator_traits<allocator_type>::pointer pointer;
+ typedef typename allocator_traits<allocator_type>::const_pointer const_pointer;
+ typedef typename allocator_traits<allocator_type>::size_type size_type;
+ typedef typename allocator_traits<allocator_type>::difference_type difference_type;
+
+ typedef /unspecified/ iterator;
+ typedef /unspecified/ const_iterator;
+ typedef /unspecified/ local_iterator;
+ typedef /unspecified/ const_local_iterator;
+
+ hash_set()
+ noexcept(
+ is_nothrow_default_constructible<hasher>::value &&
+ is_nothrow_default_constructible<key_equal>::value &&
+ is_nothrow_default_constructible<allocator_type>::value);
+ explicit hash_set(size_type n, const hasher& hf = hasher(),
+ const key_equal& eql = key_equal(),
+ const allocator_type& a = allocator_type());
+ template <class InputIterator>
+ hash_set(InputIterator f, InputIterator l,
+ size_type n = 0, const hasher& hf = hasher(),
+ const key_equal& eql = key_equal(),
+ const allocator_type& a = allocator_type());
+ explicit hash_set(const allocator_type&);
+ hash_set(const hash_set&);
+ hash_set(const hash_set&, const Allocator&);
+ hash_set(hash_set&&)
+ noexcept(
+ is_nothrow_move_constructible<hasher>::value &&
+ is_nothrow_move_constructible<key_equal>::value &&
+ is_nothrow_move_constructible<allocator_type>::value);
+ hash_set(hash_set&&, const Allocator&);
+ hash_set(initializer_list<value_type>, size_type n = 0,
+ const hasher& hf = hasher(), const key_equal& eql = key_equal(),
+ const allocator_type& a = allocator_type());
+ ~hash_set();
+ hash_set& operator=(const hash_set&);
+ hash_set& operator=(hash_set&&)
+ noexcept(
+ allocator_type::propagate_on_container_move_assignment::value &&
+ is_nothrow_move_assignable<allocator_type>::value &&
+ is_nothrow_move_assignable<hasher>::value &&
+ is_nothrow_move_assignable<key_equal>::value);
+ hash_set& operator=(initializer_list<value_type>);
+
+ allocator_type get_allocator() const noexcept;
+
+ bool empty() const noexcept;
+ size_type size() const noexcept;
+ size_type max_size() const noexcept;
+
+ iterator begin() noexcept;
+ iterator end() noexcept;
+ const_iterator begin() const noexcept;
+ const_iterator end() const noexcept;
+ const_iterator cbegin() const noexcept;
+ const_iterator cend() const noexcept;
+
+ template <class... Args>
+ pair<iterator, bool> emplace(Args&&... args);
+ template <class... Args>
+ iterator emplace_hint(const_iterator position, Args&&... args);
+ pair<iterator, bool> insert(const value_type& obj);
+ pair<iterator, bool> insert(value_type&& obj);
+ iterator insert(const_iterator hint, const value_type& obj);
+ iterator insert(const_iterator hint, value_type&& obj);
+ template <class InputIterator>
+ void insert(InputIterator first, InputIterator last);
+ void insert(initializer_list<value_type>);
+
+ iterator erase(const_iterator position);
+ size_type erase(const key_type& k);
+ iterator erase(const_iterator first, const_iterator last);
+ void clear() noexcept;
+
+ void swap(hash_set&)
+ noexcept(
+ (!allocator_type::propagate_on_container_swap::value ||
+ __is_nothrow_swappable<allocator_type>::value) &&
+ __is_nothrow_swappable<hasher>::value &&
+ __is_nothrow_swappable<key_equal>::value);
+
+ hasher hash_function() const;
+ key_equal key_eq() const;
+
+ iterator find(const key_type& k);
+ const_iterator find(const key_type& k) const;
+ size_type count(const key_type& k) const;
+ pair<iterator, iterator> equal_range(const key_type& k);
+ pair<const_iterator, const_iterator> equal_range(const key_type& k) const;
+
+ size_type bucket_count() const noexcept;
+ size_type max_bucket_count() const noexcept;
+
+ size_type bucket_size(size_type n) const;
+ size_type bucket(const key_type& k) const;
+
+ local_iterator begin(size_type n);
+ local_iterator end(size_type n);
+ const_local_iterator begin(size_type n) const;
+ const_local_iterator end(size_type n) const;
+ const_local_iterator cbegin(size_type n) const;
+ const_local_iterator cend(size_type n) const;
+
+ float load_factor() const noexcept;
+ float max_load_factor() const noexcept;
+ void max_load_factor(float z);
+ void rehash(size_type n);
+ void reserve(size_type n);
+};
diff --git a/boost/container/detail/iterators.hpp b/boost/container/detail/iterators.hpp
index 374b55c836..0dabd3c73e 100644
--- a/boost/container/detail/iterators.hpp
+++ b/boost/container/detail/iterators.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2005-2012.
+// (C) Copyright Ion Gaztanaga 2005-2013.
// (C) Copyright Gennaro Prota 2003 - 2004.
//
// Distributed under the Boost Software License, Version 1.0.
@@ -14,18 +14,20 @@
#ifndef BOOST_CONTAINER_DETAIL_ITERATORS_HPP
#define BOOST_CONTAINER_DETAIL_ITERATORS_HPP
-#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#if defined(_MSC_VER)
# pragma once
#endif
-#include "config_begin.hpp"
+#include <boost/container/detail/config_begin.hpp>
#include <boost/container/detail/workaround.hpp>
-#include <boost/move/move.hpp>
#include <boost/container/allocator_traits.hpp>
+#include <boost/container/detail/type_traits.hpp>
+#include <boost/static_assert.hpp>
+#include <boost/move/utility_core.hpp>
+#include <boost/intrusive/detail/reverse_iterator.hpp>
#ifdef BOOST_CONTAINER_PERFECT_FORWARDING
#include <boost/container/detail/variadic_templates_tools.hpp>
-#include <boost/container/detail/stored_ref.hpp>
#else
#include <boost/container/detail/preprocessor.hpp>
#endif
@@ -52,7 +54,7 @@ class constant_iterator
constant_iterator& operator++()
{ increment(); return *this; }
-
+
constant_iterator operator++(int)
{
constant_iterator result (*this);
@@ -62,7 +64,7 @@ class constant_iterator
constant_iterator& operator--()
{ decrement(); return *this; }
-
+
constant_iterator operator--(int)
{
constant_iterator result (*this);
@@ -114,7 +116,7 @@ class constant_iterator
const T& operator*() const
{ return dereference(); }
- const T& operator[] (Difference n) const
+ const T& operator[] (Difference ) const
{ return dereference(); }
const T* operator->() const
@@ -146,90 +148,199 @@ class constant_iterator
{ return m_num - other.m_num; }
};
-template <class T, class Difference = std::ptrdiff_t>
-class default_construct_iterator
+template <class T, class Difference>
+class value_init_construct_iterator
: public std::iterator
<std::random_access_iterator_tag, T, Difference, const T*, const T &>
{
- typedef default_construct_iterator<T, Difference> this_type;
+ typedef value_init_construct_iterator<T, Difference> this_type;
public:
- explicit default_construct_iterator(Difference range_size)
+ explicit value_init_construct_iterator(Difference range_size)
: m_num(range_size){}
//Constructors
- default_construct_iterator()
+ value_init_construct_iterator()
: m_num(0){}
- default_construct_iterator& operator++()
+ value_init_construct_iterator& operator++()
{ increment(); return *this; }
-
- default_construct_iterator operator++(int)
+
+ value_init_construct_iterator operator++(int)
{
- default_construct_iterator result (*this);
+ value_init_construct_iterator result (*this);
increment();
return result;
}
- default_construct_iterator& operator--()
+ value_init_construct_iterator& operator--()
{ decrement(); return *this; }
-
- default_construct_iterator operator--(int)
+
+ value_init_construct_iterator operator--(int)
{
- default_construct_iterator result (*this);
+ value_init_construct_iterator result (*this);
decrement();
return result;
}
- friend bool operator== (const default_construct_iterator& i, const default_construct_iterator& i2)
+ friend bool operator== (const value_init_construct_iterator& i, const value_init_construct_iterator& i2)
{ return i.equal(i2); }
- friend bool operator!= (const default_construct_iterator& i, const default_construct_iterator& i2)
+ friend bool operator!= (const value_init_construct_iterator& i, const value_init_construct_iterator& i2)
{ return !(i == i2); }
- friend bool operator< (const default_construct_iterator& i, const default_construct_iterator& i2)
+ friend bool operator< (const value_init_construct_iterator& i, const value_init_construct_iterator& i2)
{ return i.less(i2); }
- friend bool operator> (const default_construct_iterator& i, const default_construct_iterator& i2)
+ friend bool operator> (const value_init_construct_iterator& i, const value_init_construct_iterator& i2)
{ return i2 < i; }
- friend bool operator<= (const default_construct_iterator& i, const default_construct_iterator& i2)
+ friend bool operator<= (const value_init_construct_iterator& i, const value_init_construct_iterator& i2)
{ return !(i > i2); }
- friend bool operator>= (const default_construct_iterator& i, const default_construct_iterator& i2)
+ friend bool operator>= (const value_init_construct_iterator& i, const value_init_construct_iterator& i2)
{ return !(i < i2); }
- friend Difference operator- (const default_construct_iterator& i, const default_construct_iterator& i2)
+ friend Difference operator- (const value_init_construct_iterator& i, const value_init_construct_iterator& i2)
{ return i2.distance_to(i); }
//Arithmetic
- default_construct_iterator& operator+=(Difference off)
+ value_init_construct_iterator& operator+=(Difference off)
{ this->advance(off); return *this; }
- default_construct_iterator operator+(Difference off) const
+ value_init_construct_iterator operator+(Difference off) const
{
- default_construct_iterator other(*this);
+ value_init_construct_iterator other(*this);
other.advance(off);
return other;
}
- friend default_construct_iterator operator+(Difference off, const default_construct_iterator& right)
+ friend value_init_construct_iterator operator+(Difference off, const value_init_construct_iterator& right)
{ return right + off; }
- default_construct_iterator& operator-=(Difference off)
+ value_init_construct_iterator& operator-=(Difference off)
{ this->advance(-off); return *this; }
- default_construct_iterator operator-(Difference off) const
+ value_init_construct_iterator operator-(Difference off) const
{ return *this + (-off); }
- const T& operator*() const
- { return dereference(); }
+ //This pseudo-iterator's dereference operations have no sense since value is not
+ //constructed until ::boost::container::construct_in_place is called.
+ //So comment them to catch bad uses
+ //const T& operator*() const;
+ //const T& operator[](difference_type) const;
+ //const T* operator->() const;
- const T* operator->() const
- { return &(dereference()); }
+ private:
+ Difference m_num;
- const T& operator[] (Difference n) const
- { return dereference(); }
+ void increment()
+ { --m_num; }
+
+ void decrement()
+ { ++m_num; }
+
+ bool equal(const this_type &other) const
+ { return m_num == other.m_num; }
+
+ bool less(const this_type &other) const
+ { return other.m_num < m_num; }
+
+ const T & dereference() const
+ {
+ static T dummy;
+ return dummy;
+ }
+
+ void advance(Difference n)
+ { m_num -= n; }
+
+ Difference distance_to(const this_type &other)const
+ { return m_num - other.m_num; }
+};
+
+template <class T, class Difference>
+class default_init_construct_iterator
+ : public std::iterator
+ <std::random_access_iterator_tag, T, Difference, const T*, const T &>
+{
+ typedef default_init_construct_iterator<T, Difference> this_type;
+
+ public:
+ explicit default_init_construct_iterator(Difference range_size)
+ : m_num(range_size){}
+
+ //Constructors
+ default_init_construct_iterator()
+ : m_num(0){}
+
+ default_init_construct_iterator& operator++()
+ { increment(); return *this; }
+
+ default_init_construct_iterator operator++(int)
+ {
+ default_init_construct_iterator result (*this);
+ increment();
+ return result;
+ }
+
+ default_init_construct_iterator& operator--()
+ { decrement(); return *this; }
+
+ default_init_construct_iterator operator--(int)
+ {
+ default_init_construct_iterator result (*this);
+ decrement();
+ return result;
+ }
+
+ friend bool operator== (const default_init_construct_iterator& i, const default_init_construct_iterator& i2)
+ { return i.equal(i2); }
+
+ friend bool operator!= (const default_init_construct_iterator& i, const default_init_construct_iterator& i2)
+ { return !(i == i2); }
+
+ friend bool operator< (const default_init_construct_iterator& i, const default_init_construct_iterator& i2)
+ { return i.less(i2); }
+
+ friend bool operator> (const default_init_construct_iterator& i, const default_init_construct_iterator& i2)
+ { return i2 < i; }
+
+ friend bool operator<= (const default_init_construct_iterator& i, const default_init_construct_iterator& i2)
+ { return !(i > i2); }
+
+ friend bool operator>= (const default_init_construct_iterator& i, const default_init_construct_iterator& i2)
+ { return !(i < i2); }
+
+ friend Difference operator- (const default_init_construct_iterator& i, const default_init_construct_iterator& i2)
+ { return i2.distance_to(i); }
+
+ //Arithmetic
+ default_init_construct_iterator& operator+=(Difference off)
+ { this->advance(off); return *this; }
+
+ default_init_construct_iterator operator+(Difference off) const
+ {
+ default_init_construct_iterator other(*this);
+ other.advance(off);
+ return other;
+ }
+
+ friend default_init_construct_iterator operator+(Difference off, const default_init_construct_iterator& right)
+ { return right + off; }
+
+ default_init_construct_iterator& operator-=(Difference off)
+ { this->advance(-off); return *this; }
+
+ default_init_construct_iterator operator-(Difference off) const
+ { return *this + (-off); }
+
+ //This pseudo-iterator's dereference operations have no sense since value is not
+ //constructed until ::boost::container::construct_in_place is called.
+ //So comment them to catch bad uses
+ //const T& operator*() const;
+ //const T& operator[](difference_type) const;
+ //const T* operator->() const;
private:
Difference m_num;
@@ -259,6 +370,7 @@ class default_construct_iterator
{ return m_num - other.m_num; }
};
+
template <class T, class Difference = std::ptrdiff_t>
class repeat_iterator
: public std::iterator
@@ -275,7 +387,7 @@ class repeat_iterator
this_type& operator++()
{ increment(); return *this; }
-
+
this_type operator++(int)
{
this_type result (*this);
@@ -285,7 +397,7 @@ class repeat_iterator
this_type& operator--()
{ increment(); return *this; }
-
+
this_type operator--(int)
{
this_type result (*this);
@@ -337,7 +449,7 @@ class repeat_iterator
T& operator*() const
{ return dereference(); }
- T& operator[] (Difference n) const
+ T& operator[] (Difference ) const
{ return dereference(); }
T *operator->() const
@@ -386,7 +498,7 @@ class emplace_iterator
this_type& operator++()
{ increment(); return *this; }
-
+
this_type operator++(int)
{
this_type result (*this);
@@ -396,7 +508,7 @@ class emplace_iterator
this_type& operator--()
{ decrement(); return *this; }
-
+
this_type operator--(int)
{
this_type result (*this);
@@ -445,14 +557,12 @@ class emplace_iterator
this_type operator-(difference_type off) const
{ return *this + (-off); }
- const T& operator*() const
- { return dereference(); }
-
- const T& operator[](difference_type) const
- { return dereference(); }
-
- const T* operator->() const
- { return &(dereference()); }
+ //This pseudo-iterator's dereference operations have no sense since value is not
+ //constructed until ::boost::container::construct_in_place is called.
+ //So comment them to catch bad uses
+ //const T& operator*() const;
+ //const T& operator[](difference_type) const;
+ //const T* operator->() const;
template<class A>
void construct_in_place(A &a, T* ptr)
@@ -506,8 +616,7 @@ struct emplace_functor
void inplace_impl(A &a, T* ptr, const container_detail::index_tuple<IdxPack...>&)
{
allocator_traits<A>::construct
- (a, ptr, container_detail::stored_ref<Args>::forward
- (container_detail::get<IdxPack>(args_))...);
+ (a, ptr, ::boost::forward<Args>(container_detail::get<IdxPack>(args_))...);
}
container_detail::tuple<Args&...> args_;
@@ -539,10 +648,174 @@ struct emplace_functor
#endif
+namespace container_detail {
+
+template<class T>
+struct has_iterator_category
+{
+ template <typename X>
+ static char test(int, typename X::iterator_category*);
+
+ template <typename X>
+ static int test(int, ...);
+
+ static const bool value = (1 == sizeof(test<T>(0, 0)));
+};
+
+
+template<class T, bool = has_iterator_category<T>::value >
+struct is_input_iterator
+{
+ static const bool value = is_same<typename T::iterator_category, std::input_iterator_tag>::value;
+};
+
+template<class T>
+struct is_input_iterator<T, false>
+{
+ static const bool value = false;
+};
+
+template<class T, bool = has_iterator_category<T>::value >
+struct is_forward_iterator
+{
+ static const bool value = is_same<typename T::iterator_category, std::forward_iterator_tag>::value;
+};
+
+template<class T>
+struct is_forward_iterator<T, false>
+{
+ static const bool value = false;
+};
+
+template<class T, bool = has_iterator_category<T>::value >
+struct is_bidirectional_iterator
+{
+ static const bool value = is_same<typename T::iterator_category, std::bidirectional_iterator_tag>::value;
+};
+
+template<class T>
+struct is_bidirectional_iterator<T, false>
+{
+ static const bool value = false;
+};
+
+template<class IINodeType>
+struct iiterator_node_value_type {
+ typedef typename IINodeType::value_type type;
+};
+
+template<class IIterator>
+struct iiterator_types
+{
+ typedef typename IIterator::value_type it_value_type;
+ typedef typename iiterator_node_value_type<it_value_type>::type value_type;
+ typedef typename std::iterator_traits<IIterator>::pointer it_pointer;
+ typedef typename std::iterator_traits<IIterator>::difference_type difference_type;
+ typedef typename ::boost::intrusive::pointer_traits<it_pointer>::
+ template rebind_pointer<value_type>::type pointer;
+ typedef typename ::boost::intrusive::pointer_traits<it_pointer>::
+ template rebind_pointer<const value_type>::type const_pointer;
+ typedef typename ::boost::intrusive::
+ pointer_traits<pointer>::reference reference;
+ typedef typename ::boost::intrusive::
+ pointer_traits<const_pointer>::reference const_reference;
+ typedef typename IIterator::iterator_category iterator_category;
+};
+
+template<class IIterator, bool IsConst>
+struct std_iterator
+{
+ typedef typename std::iterator
+ < typename iiterator_types<IIterator>::iterator_category
+ , typename iiterator_types<IIterator>::value_type
+ , typename iiterator_types<IIterator>::difference_type
+ , typename iiterator_types<IIterator>::const_pointer
+ , typename iiterator_types<IIterator>::const_reference> type;
+};
+
+template<class IIterator>
+struct std_iterator<IIterator, false>
+{
+ typedef typename std::iterator
+ < typename iiterator_types<IIterator>::iterator_category
+ , typename iiterator_types<IIterator>::value_type
+ , typename iiterator_types<IIterator>::difference_type
+ , typename iiterator_types<IIterator>::pointer
+ , typename iiterator_types<IIterator>::reference> type;
+};
+
+template<class IIterator, bool IsConst>
+class iterator
+{
+ typedef typename std_iterator<IIterator, IsConst>::type types_t;
+
+ public:
+ typedef typename types_t::pointer pointer;
+ typedef typename types_t::reference reference;
+ typedef typename types_t::difference_type difference_type;
+ typedef typename types_t::iterator_category iterator_category;
+ typedef typename types_t::value_type value_type;
+
+ iterator()
+ {}
+
+ explicit iterator(IIterator iit) BOOST_CONTAINER_NOEXCEPT
+ : m_iit(iit)
+ {}
+
+ iterator(iterator<IIterator, false> const& other) BOOST_CONTAINER_NOEXCEPT
+ : m_iit(other.get())
+ {}
+
+ iterator& operator++() BOOST_CONTAINER_NOEXCEPT
+ { ++this->m_iit; return *this; }
+
+ iterator operator++(int) BOOST_CONTAINER_NOEXCEPT
+ {
+ iterator result (*this);
+ ++this->m_iit;
+ return result;
+ }
+
+ iterator& operator--() BOOST_CONTAINER_NOEXCEPT
+ {
+ //If the iterator is not a bidirectional iterator, operator-- should not exist
+ BOOST_STATIC_ASSERT((is_bidirectional_iterator<iterator>::value));
+ --this->m_iit; return *this;
+ }
+
+ iterator operator--(int) BOOST_CONTAINER_NOEXCEPT
+ {
+ iterator result (*this);
+ --this->m_iit;
+ return result;
+ }
+
+ friend bool operator== (const iterator& l, const iterator& r) BOOST_CONTAINER_NOEXCEPT
+ { return l.m_iit == r.m_iit; }
+
+ friend bool operator!= (const iterator& l, const iterator& r) BOOST_CONTAINER_NOEXCEPT
+ { return !(l == r); }
+
+ reference operator*() const BOOST_CONTAINER_NOEXCEPT
+ { return (*this->m_iit).get_data(); }
+
+ pointer operator->() const BOOST_CONTAINER_NOEXCEPT
+ { return ::boost::intrusive::pointer_traits<pointer>::pointer_to(this->operator*()); }
+
+ const IIterator &get() const BOOST_CONTAINER_NOEXCEPT
+ { return this->m_iit; }
+
+ private:
+ IIterator m_iit;
+};
+
+using ::boost::intrusive::detail::reverse_iterator;
+
+} //namespace container_detail {
} //namespace container {
} //namespace boost {
#include <boost/container/detail/config_end.hpp>
#endif //#ifndef BOOST_CONTAINER_DETAIL_ITERATORS_HPP
-
diff --git a/boost/container/detail/math_functions.hpp b/boost/container/detail/math_functions.hpp
index fe8386be69..6853b9c59f 100644
--- a/boost/container/detail/math_functions.hpp
+++ b/boost/container/detail/math_functions.hpp
@@ -1,7 +1,7 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Stephen Cleary 2000.
-// (C) Copyright Ion Gaztanaga 2007-2012.
+// (C) Copyright Ion Gaztanaga 2007-2013.
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
@@ -16,7 +16,13 @@
#ifndef BOOST_CONTAINER_DETAIL_MATH_FUNCTIONS_HPP
#define BOOST_CONTAINER_DETAIL_MATH_FUNCTIONS_HPP
-#include "config_begin.hpp"
+#if defined(_MSC_VER)
+# pragma once
+#endif
+
+#include <boost/container/detail/config_begin.hpp>
+#include <boost/container/detail/workaround.hpp>
+
#include <climits>
#include <boost/static_assert.hpp>
@@ -94,7 +100,7 @@ inline std::size_t floor_log2 (std::size_t x)
std::size_t n = x;
std::size_t log2 = 0;
-
+
for(std::size_t shift = Bits >> 1; shift; shift >>= 1){
std::size_t tmp = n >> shift;
if (tmp)
diff --git a/boost/container/detail/memory_util.hpp b/boost/container/detail/memory_util.hpp
index c00172c60c..7f055cb55b 100644
--- a/boost/container/detail/memory_util.hpp
+++ b/boost/container/detail/memory_util.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2011-2012. Distributed under the Boost
+// (C) Copyright Ion Gaztanaga 2011-2013. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
@@ -11,26 +11,28 @@
#ifndef BOOST_CONTAINER_ALLOCATOR_MEMORY_UTIL_HPP
#define BOOST_CONTAINER_ALLOCATOR_MEMORY_UTIL_HPP
-#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#if defined(_MSC_VER)
# pragma once
#endif
#include <boost/container/detail/config_begin.hpp>
#include <boost/container/detail/workaround.hpp>
+
#include <boost/container/detail/preprocessor.hpp>
+#include <boost/intrusive/detail/mpl.hpp>
#include <boost/intrusive/detail/has_member_function_callable_with.hpp>
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME allocate
#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, 2, <boost/intrusive/detail/has_member_function_callable_with.hpp>))
+#define BOOST_PP_ITERATION_PARAMS_1 (3, (2, 2, <boost/intrusive/detail/has_member_function_callable_with.hpp>))
#include BOOST_PP_ITERATE()
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME destroy
#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, 3, <boost/intrusive/detail/has_member_function_callable_with.hpp>))
+#define BOOST_PP_ITERATION_PARAMS_1 (3, (1, 1, <boost/intrusive/detail/has_member_function_callable_with.hpp>))
#include BOOST_PP_ITERATE()
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME max_size
@@ -48,14 +50,23 @@
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME construct
#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, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS+1, <boost/intrusive/detail/has_member_function_callable_with.hpp>))
+#ifdef BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_SINGLE_ITERATION
+# define BOOST_PP_ITERATION_PARAMS_1 (3, (1, 1, <boost/intrusive/detail/has_member_function_callable_with.hpp>))
+#else
+# define BOOST_PP_ITERATION_PARAMS_1 (3, (1, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS+1, <boost/intrusive/detail/has_member_function_callable_with.hpp>))
+#endif
+#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, (1, 1, <boost/intrusive/detail/has_member_function_callable_with.hpp>))
#include BOOST_PP_ITERATE()
namespace boost {
namespace container {
namespace container_detail {
-
BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(pointer)
BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(const_pointer)
BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(reference)
@@ -67,6 +78,8 @@ BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(propagate_on_container_copy_assig
BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(propagate_on_container_move_assignment)
BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(propagate_on_container_swap)
BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(difference_type)
+BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(value_compare)
+BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(wrapped_value_compare)
} //namespace container_detail {
} //namespace container {
diff --git a/boost/container/detail/mpl.hpp b/boost/container/detail/mpl.hpp
index 74a1ce0e67..ceac52a371 100644
--- a/boost/container/detail/mpl.hpp
+++ b/boost/container/detail/mpl.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2005-2012.
+// (C) Copyright Ion Gaztanaga 2005-2013.
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
@@ -13,10 +13,13 @@
#ifndef BOOST_CONTAINER_CONTAINER_DETAIL_MPL_HPP
#define BOOST_CONTAINER_CONTAINER_DETAIL_MPL_HPP
-#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#if defined(_MSC_VER)
# pragma once
#endif
+#include <boost/container/detail/config_begin.hpp>
+#include <boost/container/detail/workaround.hpp>
+
#include <cstddef>
namespace boost {
@@ -66,18 +69,32 @@ struct disable_if : public enable_if_c<!Cond::value, T> {};
template <bool B, class T = void>
struct disable_if_c : public enable_if_c<!B, T> {};
+#if defined(_MSC_VER) && (_MSC_VER >= 1400)
+
+template <class T, class U>
+struct is_convertible
+{
+ static const bool value = __is_convertible_to(T, U);
+};
+
+#else
+
template <class T, class U>
class is_convertible
{
typedef char true_t;
class false_t { char dummy[2]; };
- static true_t dispatch(U);
+ //use any_conversion as first parameter since in MSVC
+ //overaligned types can't go through ellipsis
static false_t dispatch(...);
- static T trigger();
+ static true_t dispatch(U);
+ static T &trigger();
public:
- enum { value = sizeof(dispatch(trigger())) == sizeof(true_t) };
+ static const bool value = sizeof(dispatch(trigger())) == sizeof(true_t);
};
+#endif
+
template<
bool C
, typename T1
@@ -110,8 +127,10 @@ struct if_
template <class Pair>
struct select1st
-// : public std::unary_function<Pair, typename Pair::first_type>
{
+ typedef Pair argument_type;
+ typedef typename Pair::first_type result_type;
+
template<class OtherPair>
const typename Pair::first_type& operator()(const OtherPair& x) const
{ return x.first; }
@@ -123,8 +142,10 @@ struct select1st
// identity is an extension: it is not part of the standard.
template <class T>
struct identity
-// : public std::unary_function<T,T>
{
+ typedef T argument_type;
+ typedef T result_type;
+
typedef T type;
const T& operator()(const T& x) const
{ return x; }
@@ -156,5 +177,7 @@ template <> struct unvoid<const void> { struct type { }; };
} //namespace container {
} //namespace boost {
+#include <boost/container/detail/config_end.hpp>
+
#endif //#ifndef BOOST_CONTAINER_CONTAINER_DETAIL_MPL_HPP
diff --git a/boost/container/detail/multiallocation_chain.hpp b/boost/container/detail/multiallocation_chain.hpp
index c9952535eb..96f6202671 100644
--- a/boost/container/detail/multiallocation_chain.hpp
+++ b/boost/container/detail/multiallocation_chain.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
+// (C) Copyright Ion Gaztanaga 2005-2013. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
@@ -11,7 +11,13 @@
#ifndef BOOST_CONTAINER_DETAIL_MULTIALLOCATION_CHAIN_HPP
#define BOOST_CONTAINER_DETAIL_MULTIALLOCATION_CHAIN_HPP
-#include "config_begin.hpp"
+#if defined(_MSC_VER)
+# pragma once
+#endif
+
+#include <boost/container/detail/config_begin.hpp>
+#include <boost/container/detail/workaround.hpp>
+
#include <boost/container/container_fwd.hpp>
#include <boost/container/detail/utilities.hpp>
#include <boost/container/detail/type_traits.hpp>
@@ -19,7 +25,7 @@
#include <boost/intrusive/slist.hpp>
#include <boost/intrusive/pointer_traits.hpp>
#include <boost/type_traits/make_unsigned.hpp>
-#include <boost/move/move.hpp>
+#include <boost/move/utility_core.hpp>
namespace boost {
namespace container {
@@ -45,30 +51,43 @@ class basic_multiallocation_chain
> slist_impl_t;
slist_impl_t slist_impl_;
- static node & to_node(VoidPointer p)
- { return *static_cast<node*>(static_cast<void*>(container_detail::to_raw_pointer(p))); }
+ typedef typename boost::intrusive::pointer_traits
+ <VoidPointer>::template rebind_pointer<node>::type node_ptr;
+ typedef typename boost::intrusive::
+ pointer_traits<node_ptr> node_ptr_traits;
+
+ static node & to_node(const VoidPointer &p)
+ { return *static_cast<node*>(static_cast<void*>(container_detail::to_raw_pointer(p))); }
+
+ static VoidPointer from_node(node &n)
+ { return node_ptr_traits::pointer_to(n); }
+
+ static node_ptr to_node_ptr(const VoidPointer &p)
+ { return node_ptr_traits::static_cast_from(p); }
BOOST_MOVABLE_BUT_NOT_COPYABLE(basic_multiallocation_chain)
public:
-
- typedef VoidPointer void_pointer;
- typedef typename slist_impl_t::iterator iterator;
- typedef typename slist_impl_t::size_type size_type;
+ typedef VoidPointer void_pointer;
+ typedef typename slist_impl_t::iterator iterator;
+ typedef typename slist_impl_t::size_type size_type;
basic_multiallocation_chain()
: slist_impl_()
{}
+ basic_multiallocation_chain(const void_pointer &b, const void_pointer &before_e, size_type n)
+ : slist_impl_(to_node_ptr(b), to_node_ptr(before_e), n)
+ {}
+
basic_multiallocation_chain(BOOST_RV_REF(basic_multiallocation_chain) other)
- : slist_impl_()
- { slist_impl_.swap(other.slist_impl_); }
+ : slist_impl_(::boost::move(other.slist_impl_))
+ {}
basic_multiallocation_chain& operator=(BOOST_RV_REF(basic_multiallocation_chain) other)
{
- basic_multiallocation_chain tmp(boost::move(other));
- this->swap(tmp);
+ slist_impl_ = ::boost::move(other.slist_impl_);
return *this;
}
@@ -96,37 +115,52 @@ class basic_multiallocation_chain
iterator insert_after(iterator it, void_pointer m)
{ return slist_impl_.insert_after(it, to_node(m)); }
- void push_front(void_pointer m)
- { return slist_impl_.push_front(to_node(m)); }
+ void push_front(const void_pointer &m)
+ { return slist_impl_.push_front(to_node(m)); }
- void push_back(void_pointer m)
+ void push_back(const void_pointer &m)
{ return slist_impl_.push_back(to_node(m)); }
- void pop_front()
- { return slist_impl_.pop_front(); }
-
- void *front()
- { return &*slist_impl_.begin(); }
-
- void splice_after(iterator after_this, basic_multiallocation_chain &x, iterator before_begin, iterator before_end)
- { slist_impl_.splice_after(after_this, x.slist_impl_, before_begin, before_end); }
+ void_pointer pop_front()
+ {
+ node & n = slist_impl_.front();
+ void_pointer ret = from_node(n);
+ slist_impl_.pop_front();
+ return ret;
+ }
- void splice_after(iterator after_this, basic_multiallocation_chain &x, iterator before_begin, iterator before_end, size_type n)
- { slist_impl_.splice_after(after_this, x.slist_impl_, before_begin, before_end, n); }
+ void splice_after(iterator after_this, basic_multiallocation_chain &x, iterator before_b, iterator before_e, size_type n)
+ { slist_impl_.splice_after(after_this, x.slist_impl_, before_b, before_e, n); }
void splice_after(iterator after_this, basic_multiallocation_chain &x)
{ slist_impl_.splice_after(after_this, x.slist_impl_); }
- void incorporate_after(iterator after_this, void_pointer begin , iterator before_end)
- { slist_impl_.incorporate_after(after_this, &to_node(begin), &to_node(before_end)); }
+ void erase_after(iterator before_b, iterator e, size_type n)
+ { slist_impl_.erase_after(before_b, e, n); }
- void incorporate_after(iterator after_this, void_pointer begin, void_pointer before_end, size_type n)
- { slist_impl_.incorporate_after(after_this, &to_node(begin), &to_node(before_end), n); }
+ void_pointer incorporate_after(iterator after_this, const void_pointer &b, size_type unit_bytes, size_type num_units)
+ {
+ typedef typename boost::intrusive::pointer_traits<char_ptr> char_pointer_traits;
+ char_ptr elem = char_pointer_traits::static_cast_from(b);
+ if(num_units){
+ char_ptr prev_elem = elem;
+ elem += unit_bytes;
+ for(size_type i = 0; i != num_units-1; ++i, elem += unit_bytes){
+ ::new (container_detail::to_raw_pointer(prev_elem)) void_pointer(elem);
+ prev_elem = elem;
+ }
+ slist_impl_.incorporate_after(after_this, to_node_ptr(b), to_node_ptr(prev_elem), num_units);
+ }
+ return elem;
+ }
+
+ void incorporate_after(iterator after_this, void_pointer b, void_pointer before_e, size_type n)
+ { slist_impl_.incorporate_after(after_this, to_node_ptr(b), to_node_ptr(before_e), n); }
void swap(basic_multiallocation_chain &x)
{ slist_impl_.swap(x.slist_impl_); }
- static iterator iterator_to(void_pointer p)
+ static iterator iterator_to(const void_pointer &p)
{ return slist_impl_t::s_iterator_to(to_node(p)); }
std::pair<void_pointer, void_pointer> extract_data()
@@ -150,72 +184,75 @@ struct cast_functor
template<class MultiallocationChain, class T>
class transform_multiallocation_chain
+ : public MultiallocationChain
{
private:
BOOST_MOVABLE_BUT_NOT_COPYABLE(transform_multiallocation_chain)
+ //transform_multiallocation_chain(const transform_multiallocation_chain &);
+ //transform_multiallocation_chain & operator=(const transform_multiallocation_chain &);
- MultiallocationChain holder_;
typedef typename MultiallocationChain::void_pointer void_pointer;
typedef typename boost::intrusive::pointer_traits
- <void_pointer>::template rebind_pointer<T>::type pointer;
+ <void_pointer> void_pointer_traits;
+ typedef typename void_pointer_traits::template
+ rebind_pointer<T>::type pointer;
+ typedef typename boost::intrusive::pointer_traits
+ <pointer> pointer_traits;
- static pointer cast(void_pointer p)
- {
- return pointer(static_cast<T*>(container_detail::to_raw_pointer(p)));
- }
+ static pointer cast(const void_pointer &p)
+ { return pointer_traits::static_cast_from(p); }
public:
typedef transform_iterator
< typename MultiallocationChain::iterator
- , container_detail::cast_functor <T> > iterator;
- typedef typename MultiallocationChain::size_type size_type;
+ , container_detail::cast_functor <T> > iterator;
+ typedef typename MultiallocationChain::size_type size_type;
transform_multiallocation_chain()
- : holder_()
+ : MultiallocationChain()
{}
transform_multiallocation_chain(BOOST_RV_REF(transform_multiallocation_chain) other)
- : holder_()
- { this->swap(other); }
+ : MultiallocationChain(::boost::move(static_cast<MultiallocationChain&>(other)))
+ {}
transform_multiallocation_chain(BOOST_RV_REF(MultiallocationChain) other)
- : holder_(boost::move(other))
+ : MultiallocationChain(::boost::move(static_cast<MultiallocationChain&>(other)))
{}
transform_multiallocation_chain& operator=(BOOST_RV_REF(transform_multiallocation_chain) other)
{
- transform_multiallocation_chain tmp(boost::move(other));
- this->swap(tmp);
- return *this;
+ return static_cast<MultiallocationChain&>
+ (this->MultiallocationChain::operator=(::boost::move(static_cast<MultiallocationChain&>(other))));
}
-
- void push_front(pointer mem)
+/*
+ void push_front(const pointer &mem)
{ holder_.push_front(mem); }
+ void push_back(const pointer &mem)
+ { return holder_.push_back(mem); }
+
void swap(transform_multiallocation_chain &other_chain)
{ holder_.swap(other_chain.holder_); }
- void splice_after(iterator after_this, transform_multiallocation_chain &x, iterator before_begin, iterator before_end, size_type n)
- { holder_.splice_after(after_this.base(), x.holder_, before_begin.base(), before_end.base(), n); }
-
- void incorporate_after(iterator after_this, void_pointer begin, void_pointer before_end, size_type n)
- { holder_.incorporate_after(after_this.base(), begin, before_end, n); }
-
- void pop_front()
- { holder_.pop_front(); }
-
- pointer front()
- { return cast(holder_.front()); }
+ void splice_after(iterator after_this, transform_multiallocation_chain &x, iterator before_b, iterator before_e, size_type n)
+ { holder_.splice_after(after_this.base(), x.holder_, before_b.base(), before_e.base(), n); }
+ void incorporate_after(iterator after_this, pointer b, pointer before_e, size_type n)
+ { holder_.incorporate_after(after_this.base(), b, before_e, n); }
+*/
+ pointer pop_front()
+ { return cast(this->MultiallocationChain::pop_front()); }
+/*
bool empty() const
{ return holder_.empty(); }
iterator before_begin()
{ return iterator(holder_.before_begin()); }
-
+*/
iterator begin()
- { return iterator(holder_.begin()); }
-
+ { return iterator(this->MultiallocationChain::begin()); }
+/*
iterator end()
{ return iterator(holder_.end()); }
@@ -227,20 +264,21 @@ class transform_multiallocation_chain
void clear()
{ holder_.clear(); }
-
+*/
iterator insert_after(iterator it, pointer m)
- { return iterator(holder_.insert_after(it.base(), m)); }
+ { return iterator(this->MultiallocationChain::insert_after(it.base(), m)); }
- static iterator iterator_to(pointer p)
+ static iterator iterator_to(const pointer &p)
{ return iterator(MultiallocationChain::iterator_to(p)); }
- std::pair<void_pointer, void_pointer> extract_data()
- { return holder_.extract_data(); }
-
- MultiallocationChain extract_multiallocation_chain()
+ std::pair<pointer, pointer> extract_data()
{
- return MultiallocationChain(boost::move(holder_));
+ std::pair<void_pointer, void_pointer> data(this->MultiallocationChain::extract_data());
+ return std::pair<pointer, pointer>(cast(data.first), cast(data.second));
}
+/*
+ MultiallocationChain &extract_multiallocation_chain()
+ { return holder_; }*/
};
}}}
diff --git a/boost/container/detail/mutex.hpp b/boost/container/detail/mutex.hpp
new file mode 100644
index 0000000000..c53afa1f42
--- /dev/null
+++ b/boost/container/detail/mutex.hpp
@@ -0,0 +1,284 @@
+// Copyright (C) 2000 Stephen Cleary
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org for updates, documentation, and revision history.
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2007-2013. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_CONTAINER_MUTEX_HPP
+#define BOOST_CONTAINER_MUTEX_HPP
+
+#if defined(_MSC_VER)
+# pragma once
+#endif
+
+//#define BOOST_CONTAINER_NO_MT
+//#define BOOST_CONTAINER_NO_SPINLOCKS
+
+#include <boost/container/detail/config_begin.hpp>
+#include <boost/container/detail/workaround.hpp>
+
+// Extremely Light-Weight wrapper classes for OS thread synchronization
+
+#define BOOST_MUTEX_HELPER_NONE 0
+#define BOOST_MUTEX_HELPER_WIN32 1
+#define BOOST_MUTEX_HELPER_PTHREAD 2
+#define BOOST_MUTEX_HELPER_SPINLOCKS 3
+
+#if !defined(BOOST_HAS_THREADS) && !defined(BOOST_NO_MT)
+# define BOOST_NO_MT
+#endif
+
+#if defined(BOOST_NO_MT) || defined(BOOST_CONTAINER_NO_MT)
+ // No multithreading -> make locks into no-ops
+ #define BOOST_MUTEX_HELPER BOOST_MUTEX_HELPER_NONE
+#else
+ //Taken from dlmalloc
+ #if !defined(BOOST_CONTAINER_NO_SPINLOCKS) && \
+ ((defined(__GNUC__) && \
+ ((__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 1)) || \
+ defined(__i386__) || defined(__x86_64__))) || \
+ (defined(_MSC_VER) && _MSC_VER>=1310))
+ #define BOOST_MUTEX_HELPER BOOST_MUTEX_HELPER_SPINLOCKS
+ #endif
+
+ #if defined(BOOST_WINDOWS)
+ #include <windows.h>
+ #ifndef BOOST_MUTEX_HELPER
+ #define BOOST_MUTEX_HELPER BOOST_MUTEX_HELPER_WIN32
+ #endif
+ #elif defined(BOOST_HAS_UNISTD_H)
+ #include <unistd.h>
+ #if !defined(BOOST_MUTEX_HELPER) && (defined(_POSIX_THREADS) || defined(BOOST_HAS_PTHREADS))
+ #define BOOST_MUTEX_HELPER BOOST_MUTEX_HELPER_PTHREAD
+ #endif
+ #endif
+#endif
+
+#ifndef BOOST_MUTEX_HELPER
+ #error Unable to determine platform mutex type; #define BOOST_NO_MT to assume single-threaded
+#endif
+
+#if BOOST_MUTEX_HELPER == BOOST_MUTEX_HELPER_NONE
+ //...
+#elif BOOST_MUTEX_HELPER == BOOST_MUTEX_HELPER_SPINLOCKS
+ #if defined(_MSC_VER)
+ #ifndef _M_AMD64
+ /* These are already defined on AMD64 builds */
+ #ifdef __cplusplus
+ extern "C" {
+ #endif /* __cplusplus */
+ long __cdecl _InterlockedCompareExchange(long volatile *Dest, long Exchange, long Comp);
+ long __cdecl _InterlockedExchange(long volatile *Target, long Value);
+ #ifdef __cplusplus
+ }
+ #endif /* __cplusplus */
+ #endif /* _M_AMD64 */
+ #pragma intrinsic (_InterlockedCompareExchange)
+ #pragma intrinsic (_InterlockedExchange)
+ #define interlockedcompareexchange _InterlockedCompareExchange
+ #define interlockedexchange _InterlockedExchange
+ #elif defined(WIN32) && defined(__GNUC__)
+ #define interlockedcompareexchange(a, b, c) __sync_val_compare_and_swap(a, c, b)
+ #define interlockedexchange __sync_lock_test_and_set
+ #endif /* Win32 */
+
+ /* First, define CAS_LOCK and CLEAR_LOCK on ints */
+ /* Note CAS_LOCK defined to return 0 on success */
+
+ #if defined(__GNUC__)&& (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 1))
+ #define BOOST_CONTAINER_CAS_LOCK(sl) __sync_lock_test_and_set(sl, 1)
+ #define BOOST_CONTAINER_CLEAR_LOCK(sl) __sync_lock_release(sl)
+
+ #elif (defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)))
+ /* Custom spin locks for older gcc on x86 */
+ static FORCEINLINE int boost_container_x86_cas_lock(int *sl) {
+ int ret;
+ int val = 1;
+ int cmp = 0;
+ __asm__ __volatile__ ("lock; cmpxchgl %1, %2"
+ : "=a" (ret)
+ : "r" (val), "m" (*(sl)), "0"(cmp)
+ : "memory", "cc");
+ return ret;
+ }
+
+ static FORCEINLINE void boost_container_x86_clear_lock(int* sl) {
+ assert(*sl != 0);
+ int prev = 0;
+ int ret;
+ __asm__ __volatile__ ("lock; xchgl %0, %1"
+ : "=r" (ret)
+ : "m" (*(sl)), "0"(prev)
+ : "memory");
+ }
+
+ #define BOOST_CONTAINER_CAS_LOCK(sl) boost_container_x86_cas_lock(sl)
+ #define BOOST_CONTAINER_CLEAR_LOCK(sl) boost_container_x86_clear_lock(sl)
+
+ #else /* Win32 MSC */
+ #define BOOST_CONTAINER_CAS_LOCK(sl) interlockedexchange((long volatile*)sl, (long)1)
+ #define BOOST_CONTAINER_CLEAR_LOCK(sl) interlockedexchange((long volatile*)sl, (long)0)
+ #endif
+
+ /* How to yield for a spin lock */
+ #define SPINS_PER_YIELD 63
+ #if defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
+ #define SLEEP_EX_DURATION 50 /* delay for yield/sleep */
+ #define SPIN_LOCK_YIELD SleepEx(SLEEP_EX_DURATION, FALSE)
+ #elif defined (__SVR4) && defined (__sun) /* solaris */
+ #include <thread.h>
+ #define SPIN_LOCK_YIELD thr_yield();
+ #elif !defined(LACKS_SCHED_H)
+ #include <sched.h>
+ #define SPIN_LOCK_YIELD sched_yield();
+ #else
+ #define SPIN_LOCK_YIELD
+ #endif /* ... yield ... */
+
+ #define BOOST_CONTAINER_SPINS_PER_YIELD 63
+ inline int boost_interprocess_spin_acquire_lock(int *sl) {
+ int spins = 0;
+ while (*(volatile int *)sl != 0 ||
+ BOOST_CONTAINER_CAS_LOCK(sl)) {
+ if ((++spins & BOOST_CONTAINER_SPINS_PER_YIELD) == 0) {
+ SPIN_LOCK_YIELD;
+ }
+ }
+ return 0;
+ }
+ #define BOOST_CONTAINER_MLOCK_T int
+ #define BOOST_CONTAINER_TRY_LOCK(sl) !BOOST_CONTAINER_CAS_LOCK(sl)
+ #define BOOST_CONTAINER_RELEASE_LOCK(sl) BOOST_CONTAINER_CLEAR_LOCK(sl)
+ #define BOOST_CONTAINER_ACQUIRE_LOCK(sl) (BOOST_CONTAINER_CAS_LOCK(sl)? boost_interprocess_spin_acquire_lock(sl) : 0)
+ #define BOOST_CONTAINER_INITIAL_LOCK(sl) (*sl = 0)
+ #define BOOST_CONTAINER_DESTROY_LOCK(sl) (0)
+#elif BOOST_MUTEX_HELPER == BOOST_MUTEX_HELPER_WIN32
+ //
+#elif BOOST_MUTEX_HELPER == BOOST_MUTEX_HELPER_PTHREAD
+ #include <pthread.h>
+#endif
+
+namespace boost {
+namespace container {
+namespace container_detail {
+
+#if BOOST_MUTEX_HELPER == BOOST_MUTEX_HELPER_NONE
+ class null_mutex
+ {
+ private:
+ null_mutex(const null_mutex &);
+ void operator=(const null_mutex &);
+
+ public:
+ null_mutex() { }
+
+ static void lock() { }
+ static void unlock() { }
+ };
+
+ typedef null_mutex default_mutex;
+#elif BOOST_MUTEX_HELPER == BOOST_MUTEX_HELPER_SPINLOCKS
+
+ class spin_mutex
+ {
+ private:
+ BOOST_CONTAINER_MLOCK_T sl;
+ spin_mutex(const spin_mutex &);
+ void operator=(const spin_mutex &);
+
+ public:
+ spin_mutex() { BOOST_CONTAINER_INITIAL_LOCK(&sl); }
+
+ void lock() { BOOST_CONTAINER_ACQUIRE_LOCK(&sl); }
+ void unlock() { BOOST_CONTAINER_RELEASE_LOCK(&sl); }
+ };
+ typedef spin_mutex default_mutex;
+#elif BOOST_MUTEX_HELPER == BOOST_MUTEX_HELPER_WIN32
+ class mutex
+ {
+ private:
+ CRITICAL_SECTION mtx;
+
+ mutex(const mutex &);
+ void operator=(const mutex &);
+
+ public:
+ mutex()
+ { InitializeCriticalSection(&mtx); }
+
+ ~mutex()
+ { DeleteCriticalSection(&mtx); }
+
+ void lock()
+ { EnterCriticalSection(&mtx); }
+
+ void unlock()
+ { LeaveCriticalSection(&mtx); }
+ };
+
+ typedef mutex default_mutex;
+#elif BOOST_MUTEX_HELPER == BOOST_MUTEX_HELPER_PTHREAD
+ class mutex
+ {
+ private:
+ pthread_mutex_t mtx;
+
+ mutex(const mutex &);
+ void operator=(const mutex &);
+
+ public:
+ mutex()
+ { pthread_mutex_init(&mtx, 0); }
+
+ ~mutex()
+ { pthread_mutex_destroy(&mtx); }
+
+ void lock()
+ { pthread_mutex_lock(&mtx); }
+
+ void unlock()
+ { pthread_mutex_unlock(&mtx); }
+ };
+
+ typedef mutex default_mutex;
+#endif
+
+template<class Mutex>
+class scoped_lock
+{
+ public:
+ scoped_lock(Mutex &m)
+ : m_(m)
+ { m_.lock(); }
+ ~scoped_lock()
+ { m_.unlock(); }
+
+ private:
+ Mutex &m_;
+};
+
+} // namespace container_detail
+} // namespace container
+} // namespace boost
+
+#undef BOOST_MUTEX_HELPER_WIN32
+#undef BOOST_MUTEX_HELPER_PTHREAD
+#undef BOOST_MUTEX_HELPER_NONE
+#undef BOOST_MUTEX_HELPER
+#undef BOOST_MUTEX_HELPER_SPINLOCKS
+
+#include <boost/container/detail/config_end.hpp>
+
+#endif
diff --git a/boost/container/detail/node_alloc_holder.hpp b/boost/container/detail/node_alloc_holder.hpp
index 9797f1fbd5..250c559765 100644
--- a/boost/container/detail/node_alloc_holder.hpp
+++ b/boost/container/detail/node_alloc_holder.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
+// (C) Copyright Ion Gaztanaga 2005-2013. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
@@ -11,163 +11,89 @@
#ifndef BOOST_CONTAINER_DETAIL_NODE_ALLOC_HPP_
#define BOOST_CONTAINER_DETAIL_NODE_ALLOC_HPP_
-#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#if defined(_MSC_VER)
# pragma once
#endif
-#include "config_begin.hpp"
+#include <boost/container/detail/config_begin.hpp>
#include <boost/container/detail/workaround.hpp>
#include <utility>
#include <functional>
-#include <boost/move/move.hpp>
+#include <boost/move/utility_core.hpp>
#include <boost/intrusive/options.hpp>
#include <boost/container/detail/version_type.hpp>
#include <boost/container/detail/type_traits.hpp>
#include <boost/container/detail/utilities.hpp>
#include <boost/container/allocator_traits.hpp>
+#include <boost/container/detail/allocator_version_traits.hpp>
#include <boost/container/detail/mpl.hpp>
#include <boost/container/detail/destroyers.hpp>
+#include <boost/container/detail/memory_util.hpp>
+#include <boost/container/detail/placement_new.hpp>
+#include <boost/core/no_exceptions_support.hpp>
#ifndef BOOST_CONTAINER_PERFECT_FORWARDING
#include <boost/container/detail/preprocessor.hpp>
#endif
#include <boost/container/detail/algorithms.hpp>
-#include <new>
+
namespace boost {
namespace container {
namespace container_detail {
-//!A deleter for scoped_ptr that deallocates the memory
-//!allocated for an object using a STL allocator.
-template <class A>
-struct scoped_deallocator
-{
- typedef allocator_traits<A> allocator_traits_type;
- typedef typename allocator_traits_type::pointer pointer;
- typedef container_detail::integral_constant<unsigned,
- boost::container::container_detail::
- version<A>::value> alloc_version;
- typedef container_detail::integral_constant<unsigned, 1> allocator_v1;
- typedef container_detail::integral_constant<unsigned, 2> allocator_v2;
-
- private:
- void priv_deallocate(allocator_v1)
- { m_alloc.deallocate(m_ptr, 1); }
-
- void priv_deallocate(allocator_v2)
- { m_alloc.deallocate_one(m_ptr); }
-
- BOOST_MOVABLE_BUT_NOT_COPYABLE(scoped_deallocator)
-
- public:
-
- pointer m_ptr;
- A& m_alloc;
-
- scoped_deallocator(pointer p, A& a)
- : m_ptr(p), m_alloc(a)
- {}
-
- ~scoped_deallocator()
- { if (m_ptr)priv_deallocate(alloc_version()); }
-
- scoped_deallocator(BOOST_RV_REF(scoped_deallocator) o)
- : m_ptr(o.m_ptr), m_alloc(o.m_alloc)
- { o.release(); }
-
- pointer get() const
- { return m_ptr; }
-
- void release()
- { m_ptr = 0; }
-};
-
-template <class A>
-class allocator_destroyer_and_chain_builder
-{
- typedef allocator_traits<A> allocator_traits_type;
- typedef typename allocator_traits_type::value_type value_type;
- typedef typename A::multiallocation_chain multiallocation_chain;
-
- A & a_;
- multiallocation_chain &c_;
-
- public:
- allocator_destroyer_and_chain_builder(A &a, multiallocation_chain &c)
- : a_(a), c_(c)
- {}
-
- void operator()(const typename A::pointer &p)
- {
- allocator_traits<A>::destroy(a_, container_detail::to_raw_pointer(p));
- c_.push_front(p);
- }
-};
-
-template <class A>
-class allocator_multialloc_chain_node_deallocator
-{
- typedef allocator_traits<A> allocator_traits_type;
- typedef typename allocator_traits_type::value_type value_type;
- typedef typename A::multiallocation_chain multiallocation_chain;
- typedef allocator_destroyer_and_chain_builder<A> chain_builder;
-
- A & a_;
- multiallocation_chain c_;
-
- public:
- allocator_multialloc_chain_node_deallocator(A &a)
- : a_(a), c_()
- {}
-
- chain_builder get_chain_builder()
- { return chain_builder(a_, c_); }
-
- ~allocator_multialloc_chain_node_deallocator()
- {
- if(!c_.empty())
- a_.deallocate_individual(boost::move(c_));
- }
-};
-
template<class ValueCompare, class Node>
struct node_compare
: private ValueCompare
{
- typedef typename ValueCompare::key_type key_type;
- typedef typename ValueCompare::value_type value_type;
- typedef typename ValueCompare::key_of_value key_of_value;
+ typedef ValueCompare wrapped_value_compare;
+ typedef typename wrapped_value_compare::key_type key_type;
+ typedef typename wrapped_value_compare::value_type value_type;
+ typedef typename wrapped_value_compare::key_of_value key_of_value;
+
+ explicit node_compare(const wrapped_value_compare &pred)
+ : wrapped_value_compare(pred)
+ {}
- node_compare(const ValueCompare &pred)
- : ValueCompare(pred)
+ node_compare()
+ : wrapped_value_compare()
{}
- ValueCompare &value_comp()
- { return static_cast<ValueCompare &>(*this); }
+ wrapped_value_compare &value_comp()
+ { return static_cast<wrapped_value_compare &>(*this); }
- ValueCompare &value_comp() const
- { return static_cast<const ValueCompare &>(*this); }
+ wrapped_value_compare &value_comp() const
+ { return static_cast<const wrapped_value_compare &>(*this); }
bool operator()(const Node &a, const Node &b) const
- { return ValueCompare::operator()(a.get_data(), b.get_data()); }
+ { return wrapped_value_compare::operator()(a.get_data(), b.get_data()); }
};
-template<class A, class ICont, class Pred = container_detail::nat>
+template<class A, class ICont>
struct node_alloc_holder
{
+ //If the intrusive container is an associative container, obtain the predicate, which will
+ //be of type node_compare<>. If not an associative container value_compare will be a "nat" type.
+ typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT(boost::container::container_detail::, ICont,
+ value_compare, container_detail::nat) intrusive_value_compare;
+ //In that case obtain the value predicate from the node predicate via wrapped_value_compare
+ //if intrusive_value_compare is node_compare<>, nat otherwise
+ typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT(boost::container::container_detail::, ICont,
+ wrapped_value_compare, container_detail::nat) value_compare;
+
typedef allocator_traits<A> allocator_traits_type;
- typedef node_alloc_holder<A, ICont> self_t;
typedef typename allocator_traits_type::value_type value_type;
+ typedef ICont intrusive_container;
typedef typename ICont::value_type Node;
typedef typename allocator_traits_type::template
portable_rebind_alloc<Node>::type NodeAlloc;
typedef allocator_traits<NodeAlloc> node_allocator_traits_type;
+ typedef container_detail::allocator_version_traits<NodeAlloc> node_allocator_version_traits_type;
typedef A ValAlloc;
typedef typename node_allocator_traits_type::pointer NodePtr;
typedef container_detail::scoped_deallocator<NodeAlloc> Deallocator;
@@ -182,6 +108,7 @@ struct node_alloc_holder
typedef typename ICont::const_iterator icont_citerator;
typedef allocator_destroyer<NodeAlloc> Destroyer;
typedef allocator_traits<NodeAlloc> NodeAllocTraits;
+ typedef allocator_version_traits<NodeAlloc> AllocVersionTraits;
private:
BOOST_COPYABLE_AND_MOVABLE(node_alloc_holder)
@@ -206,25 +133,25 @@ struct node_alloc_holder
{ this->icont().swap(x.icont()); }
//Constructors for associative containers
- explicit node_alloc_holder(const ValAlloc &a, const Pred &c)
+ explicit node_alloc_holder(const ValAlloc &a, const value_compare &c)
: members_(a, c)
{}
- explicit node_alloc_holder(const node_alloc_holder &x, const Pred &c)
+ explicit node_alloc_holder(const node_alloc_holder &x, const value_compare &c)
: members_(NodeAllocTraits::select_on_container_copy_construction(x.node_alloc()), c)
{}
- explicit node_alloc_holder(const Pred &c)
+ explicit node_alloc_holder(const value_compare &c)
: members_(c)
{}
//helpers for move assignments
- explicit node_alloc_holder(BOOST_RV_REF(node_alloc_holder) x, const Pred &c)
+ explicit node_alloc_holder(BOOST_RV_REF(node_alloc_holder) x, const value_compare &c)
: members_(boost::move(x.node_alloc()), c)
{ this->icont().swap(x.icont()); }
void copy_assign_alloc(const node_alloc_holder &x)
- {
+ {
container_detail::bool_<allocator_traits_type::propagate_on_container_copy_assignment::value> flag;
container_detail::assign_alloc( static_cast<NodeAlloc &>(this->members_)
, static_cast<const NodeAlloc &>(x.members_), flag);
@@ -244,22 +171,10 @@ struct node_alloc_holder
{ return allocator_traits_type::max_size(this->node_alloc()); }
NodePtr allocate_one()
- { return this->allocate_one(alloc_version()); }
-
- NodePtr allocate_one(allocator_v1)
- { return this->node_alloc().allocate(1); }
-
- NodePtr allocate_one(allocator_v2)
- { return this->node_alloc().allocate_one(); }
+ { return AllocVersionTraits::allocate_one(this->node_alloc()); }
void deallocate_one(const NodePtr &p)
- { return this->deallocate_one(p, alloc_version()); }
-
- void deallocate_one(const NodePtr &p, allocator_v1)
- { this->node_alloc().deallocate(p, 1); }
-
- void deallocate_one(const NodePtr &p, allocator_v2)
- { this->node_alloc().deallocate_one(p); }
+ { AllocVersionTraits::deallocate_one(this->node_alloc(), p); }
#ifdef BOOST_CONTAINER_PERFECT_FORWARDING
@@ -274,7 +189,7 @@ struct node_alloc_holder
node_deallocator.release();
//This does not throw
typedef typename Node::hook_type hook_type;
- ::new(static_cast<hook_type*>(container_detail::to_raw_pointer(p))) hook_type;
+ ::new(static_cast<hook_type*>(container_detail::to_raw_pointer(p)), boost_container_new_t()) hook_type;
return (p);
}
@@ -292,7 +207,7 @@ struct node_alloc_holder
BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _)); \
node_deallocator.release(); \
typedef typename Node::hook_type hook_type; \
- ::new(static_cast<hook_type*>(container_detail::to_raw_pointer(p))) hook_type; \
+ ::new(static_cast<hook_type*>(container_detail::to_raw_pointer(p)), boost_container_new_t()) hook_type; \
return (p); \
} \
//!
@@ -310,7 +225,7 @@ struct node_alloc_holder
node_deallocator.release();
//This does not throw
typedef typename Node::hook_type hook_type;
- ::new(static_cast<hook_type*>(container_detail::to_raw_pointer(p))) hook_type;
+ ::new(static_cast<hook_type*>(container_detail::to_raw_pointer(p)), boost_container_new_t()) hook_type;
return (p);
}
@@ -328,41 +243,49 @@ struct node_alloc_holder
}
template<class FwdIterator, class Inserter>
- FwdIterator allocate_many_and_construct
+ void allocate_many_and_construct
(FwdIterator beg, difference_type n, Inserter inserter)
{
if(n){
- typedef typename NodeAlloc::multiallocation_chain multiallocation_chain;
+ typedef typename node_allocator_version_traits_type::multiallocation_chain multiallocation_chain;
//Try to allocate memory in a single block
- multiallocation_chain mem(this->node_alloc().allocate_individual(n));
- int constructed = 0;
+ typedef typename multiallocation_chain::iterator multialloc_iterator;
+ multiallocation_chain mem;
+ NodeAlloc &nalloc = this->node_alloc();
+ node_allocator_version_traits_type::allocate_individual(nalloc, n, mem);
+ multialloc_iterator itbeg(mem.begin()), itlast(mem.last());
+ mem.clear();
Node *p = 0;
BOOST_TRY{
- for(difference_type i = 0; i < n; ++i, ++beg, --constructed){
- p = container_detail::to_raw_pointer(mem.front());
- mem.pop_front();
+ Deallocator node_deallocator(NodePtr(), nalloc);
+ container_detail::scoped_destructor<NodeAlloc> sdestructor(nalloc, 0);
+ while(n--){
+ p = container_detail::to_raw_pointer(iterator_to_pointer(itbeg));
+ node_deallocator.set(p);
+ ++itbeg;
//This can throw
- constructed = 0;
- boost::container::construct_in_place(this->node_alloc(), container_detail::addressof(p->m_data), beg);
- ++constructed;
+ boost::container::construct_in_place(nalloc, container_detail::addressof(p->m_data), beg);
+ sdestructor.set(p);
+ ++beg;
//This does not throw
typedef typename Node::hook_type hook_type;
- ::new(static_cast<hook_type*>(container_detail::to_raw_pointer(p))) hook_type;
- //This can throw in some containers (predicate might throw)
+ ::new(static_cast<hook_type*>(p), boost_container_new_t()) hook_type;
+ //This can throw in some containers (predicate might throw).
+ //(sdestructor will destruct the node and node_deallocator will deallocate it in case of exception)
inserter(*p);
+ sdestructor.set(0);
}
+ sdestructor.release();
+ node_deallocator.release();
}
BOOST_CATCH(...){
- if(constructed){
- allocator_traits<NodeAlloc>::destroy(this->node_alloc(), container_detail::to_raw_pointer(p));
- }
- this->node_alloc().deallocate_individual(boost::move(mem));
+ mem.incorporate_after(mem.last(), &*itbeg, &*itlast, n);
+ node_allocator_version_traits_type::deallocate_individual(this->node_alloc(), mem);
BOOST_RETHROW
}
BOOST_CATCH_END
}
- return beg;
}
void clear(allocator_v1)
@@ -375,7 +298,7 @@ struct node_alloc_holder
this->icont().clear_and_dispose(builder);
//BOOST_STATIC_ASSERT((::boost::has_move_emulation_enabled<typename NodeAlloc::multiallocation_chain>::value == true));
if(!chain.empty())
- this->node_alloc().deallocate_individual(boost::move(chain));
+ this->node_alloc().deallocate_individual(chain);
}
icont_iterator erase_range(const icont_iterator &first, const icont_iterator &last, allocator_v1)
@@ -383,8 +306,13 @@ struct node_alloc_holder
icont_iterator erase_range(const icont_iterator &first, const icont_iterator &last, allocator_v2)
{
- allocator_multialloc_chain_node_deallocator<NodeAlloc> chain_holder(this->node_alloc());
- return this->icont().erase_and_dispose(first, last, chain_holder.get_chain_builder());
+ typedef typename NodeAlloc::multiallocation_chain multiallocation_chain;
+ NodeAlloc & nalloc = this->node_alloc();
+ multiallocation_chain chain;
+ allocator_destroyer_and_chain_builder<NodeAlloc> chain_builder(nalloc, chain);
+ icont_iterator ret_it = this->icont().erase_and_dispose(first, last, chain_builder);
+ nalloc.deallocate_individual(chain);
+ return ret_it;
}
template<class Key, class Comparator>
@@ -430,12 +358,12 @@ struct node_alloc_holder
{}
template<class ConvertibleToAlloc>
- members_holder(BOOST_FWD_REF(ConvertibleToAlloc) c2alloc, const Pred &c)
+ members_holder(BOOST_FWD_REF(ConvertibleToAlloc) c2alloc, const value_compare &c)
: NodeAlloc(boost::forward<ConvertibleToAlloc>(c2alloc))
, m_icont(typename ICont::value_compare(c))
{}
- explicit members_holder(const Pred &c)
+ explicit members_holder(const value_compare &c)
: NodeAlloc()
, m_icont(typename ICont::value_compare(c))
{}
diff --git a/boost/container/detail/node_pool.hpp b/boost/container/detail/node_pool.hpp
new file mode 100644
index 0000000000..60d826675a
--- /dev/null
+++ b/boost/container/detail/node_pool.hpp
@@ -0,0 +1,156 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2005-2013. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_CONTAINER_DETAIL_NODE_POOL_HPP
+#define BOOST_CONTAINER_DETAIL_NODE_POOL_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif
+
+#include <boost/container/detail/config_begin.hpp>
+#include <boost/container/detail/workaround.hpp>
+
+#include <boost/container/detail/mutex.hpp>
+#include <boost/container/detail/pool_common_alloc.hpp>
+#include <boost/container/detail/node_pool_impl.hpp>
+#include <boost/container/detail/mutex.hpp>
+#include <boost/intrusive/slist.hpp>
+#include <boost/move/utility_core.hpp>
+#include <cstddef>
+#include <functional> //std::unary_function
+#include <algorithm> //std::swap
+#include <cassert>
+
+namespace boost {
+namespace container {
+namespace container_detail {
+
+//!Pooled memory allocator using single segregated storage. Includes
+//!a reference count but the class does not delete itself, this is
+//!responsibility of user classes. Node size (NodeSize) and the number of
+//!nodes allocated per block (NodesPerBlock) are known at compile time
+template< std::size_t NodeSize, std::size_t NodesPerBlock >
+class private_node_pool
+ //Inherit from the implementation to avoid template bloat
+ : public boost::container::container_detail::
+ private_node_pool_impl<fake_segment_manager>
+{
+ typedef boost::container::container_detail::
+ private_node_pool_impl<fake_segment_manager> base_t;
+ //Non-copyable
+ private_node_pool(const private_node_pool &);
+ private_node_pool &operator=(const private_node_pool &);
+
+ public:
+ typedef typename base_t::multiallocation_chain multiallocation_chain;
+ static const std::size_t nodes_per_block = NodesPerBlock;
+
+ //!Constructor from a segment manager. Never throws
+ private_node_pool()
+ : base_t(0, NodeSize, NodesPerBlock)
+ {}
+
+};
+
+template< std::size_t NodeSize
+ , std::size_t NodesPerBlock
+ >
+class shared_node_pool
+ : public private_node_pool<NodeSize, NodesPerBlock>
+{
+ private:
+ typedef private_node_pool<NodeSize, NodesPerBlock> private_node_allocator_t;
+
+ public:
+ typedef typename private_node_allocator_t::free_nodes_t free_nodes_t;
+ typedef typename private_node_allocator_t::multiallocation_chain multiallocation_chain;
+
+ //!Constructor from a segment manager. Never throws
+ shared_node_pool()
+ : private_node_allocator_t(){}
+
+ //!Destructor. Deallocates all allocated blocks. Never throws
+ ~shared_node_pool()
+ {}
+
+ //!Allocates array of count elements. Can throw std::bad_alloc
+ void *allocate_node()
+ {
+ //-----------------------
+ scoped_lock<default_mutex> guard(mutex_);
+ //-----------------------
+ return private_node_allocator_t::allocate_node();
+ }
+
+ //!Deallocates an array pointed by ptr. Never throws
+ void deallocate_node(void *ptr)
+ {
+ //-----------------------
+ scoped_lock<default_mutex> guard(mutex_);
+ //-----------------------
+ private_node_allocator_t::deallocate_node(ptr);
+ }
+
+ //!Allocates a singly linked list of n nodes ending in null pointer.
+ //!can throw std::bad_alloc
+ void allocate_nodes(const std::size_t n, multiallocation_chain &chain)
+ {
+ //-----------------------
+ scoped_lock<default_mutex> guard(mutex_);
+ //-----------------------
+ return private_node_allocator_t::allocate_nodes(n, chain);
+ }
+
+ void deallocate_nodes(multiallocation_chain &chain)
+ {
+ //-----------------------
+ scoped_lock<default_mutex> guard(mutex_);
+ //-----------------------
+ private_node_allocator_t::deallocate_nodes(chain);
+ }
+
+ //!Deallocates all the free blocks of memory. Never throws
+ void deallocate_free_blocks()
+ {
+ //-----------------------
+ scoped_lock<default_mutex> guard(mutex_);
+ //-----------------------
+ private_node_allocator_t::deallocate_free_blocks();
+ }
+
+ //!Deallocates all blocks. Never throws
+ void purge_blocks()
+ {
+ //-----------------------
+ scoped_lock<default_mutex> guard(mutex_);
+ //-----------------------
+ private_node_allocator_t::purge_blocks();
+ }
+
+ std::size_t num_free_nodes()
+ {
+ //-----------------------
+ scoped_lock<default_mutex> guard(mutex_);
+ //-----------------------
+ return private_node_allocator_t::num_free_nodes();
+ }
+
+ private:
+ default_mutex mutex_;
+};
+
+} //namespace container_detail {
+} //namespace container {
+} //namespace boost {
+
+#include <boost/container/detail/config_end.hpp>
+
+#endif //#ifndef BOOST_CONTAINER_DETAIL_NODE_POOL_HPP
diff --git a/boost/container/detail/node_pool_impl.hpp b/boost/container/detail/node_pool_impl.hpp
index 63c1278238..2450e5103e 100644
--- a/boost/container/detail/node_pool_impl.hpp
+++ b/boost/container/detail/node_pool_impl.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
+// (C) Copyright Ion Gaztanaga 2005-2013. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
@@ -11,13 +11,14 @@
#ifndef BOOST_CONTAINER_DETAIL_NODE_POOL_IMPL_HPP
#define BOOST_CONTAINER_DETAIL_NODE_POOL_IMPL_HPP
-#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#if defined(_MSC_VER)
# pragma once
#endif
-#include "config_begin.hpp"
-#include <boost/container/container_fwd.hpp>
+#include <boost/container/detail/config_begin.hpp>
#include <boost/container/detail/workaround.hpp>
+
+#include <boost/container/container_fwd.hpp>
#include <boost/container/detail/utilities.hpp>
#include <boost/intrusive/pointer_traits.hpp>
#include <boost/intrusive/set.hpp>
@@ -26,9 +27,9 @@
#include <boost/container/detail/math_functions.hpp>
#include <boost/container/detail/mpl.hpp>
#include <boost/container/detail/pool_common.hpp>
+#include <boost/core/no_exceptions_support.hpp>
#include <boost/assert.hpp>
#include <cstddef>
-#include <functional> //std::unary_function
namespace boost {
namespace container {
@@ -85,19 +86,19 @@ class private_node_pool_impl
{ return container_detail::to_raw_pointer(mp_segment_mngr_base); }
void *allocate_node()
- { return priv_alloc_node(); }
-
+ { return this->priv_alloc_node(); }
+
//!Deallocates an array pointed by ptr. Never throws
void deallocate_node(void *ptr)
- { priv_dealloc_node(ptr); }
+ { this->priv_dealloc_node(ptr); }
//!Allocates a singly linked list of n nodes ending in null pointer.
- multiallocation_chain allocate_nodes(const size_type n)
+ void allocate_nodes(const size_type n, multiallocation_chain &chain)
{
//Preallocate all needed blocks to fulfill the request
size_type cur_nodes = m_freelist.size();
if(cur_nodes < n){
- priv_alloc_block(((n - cur_nodes) - 1)/m_nodes_per_block + 1);
+ this->priv_alloc_block(((n - cur_nodes) - 1)/m_nodes_per_block + 1);
}
//We just iterate the needed nodes to get the last we'll erase
@@ -118,20 +119,18 @@ class private_node_pool_impl
//Now take the last erased node and just splice it in the end
//of the intrusive list that will be traversed by the multialloc iterator.
- multiallocation_chain chain;
chain.incorporate_after(chain.before_begin(), &*first_node, &*last_node, n);
m_allocated += n;
- return boost::move(chain);
}
- void deallocate_nodes(multiallocation_chain chain)
+ void deallocate_nodes(multiallocation_chain &chain)
{
typedef typename multiallocation_chain::iterator iterator;
iterator it(chain.begin()), itend(chain.end());
while(it != itend){
void *pElem = &*it;
++it;
- priv_dealloc_node(pElem);
+ this->priv_dealloc_node(pElem);
}
}
@@ -208,8 +207,6 @@ class private_node_pool_impl
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()){
@@ -238,7 +235,7 @@ class private_node_pool_impl
push_in_list(free_nodes_t &l, typename free_nodes_t::iterator &it)
: slist_(l), last_it_(it)
{}
-
+
void operator()(typename free_nodes_t::pointer p) const
{
slist_.push_front(*p);
@@ -253,12 +250,14 @@ class private_node_pool_impl
};
struct is_between
- : std::unary_function<typename free_nodes_t::value_type, bool>
{
+ typedef typename free_nodes_t::value_type argument_type;
+ typedef bool result_type;
+
is_between(const void *addr, std::size_t size)
: beg_(static_cast<const char *>(addr)), end_(beg_+size)
{}
-
+
bool operator()(typename free_nodes_t::const_reference v) const
{
return (beg_ <= reinterpret_cast<const char *>(&v) &&
@@ -275,7 +274,7 @@ class private_node_pool_impl
{
//If there are no free nodes we allocate a new block
if (m_freelist.empty())
- priv_alloc_block();
+ this->priv_alloc_block(1);
//We take the first free node
node_t *n = (node_t*)&m_freelist.front();
m_freelist.pop_front();
@@ -295,14 +294,13 @@ class private_node_pool_impl
}
//!Allocates several blocks of nodes. Can throw
- void priv_alloc_block(size_type num_blocks = 1)
+ void priv_alloc_block(size_type num_blocks)
{
- if(!num_blocks)
- return;
+ BOOST_ASSERT(num_blocks > 0);
size_type blocksize =
get_rounded_size(m_real_node_size*m_nodes_per_block, (size_type)alignment_of<node_t>::value);
- try{
+ BOOST_TRY{
for(size_type i = 0; i != num_blocks; ++i){
//We allocate a new NodeBlock and put it as first
//element in the free Node list
@@ -313,15 +311,16 @@ class private_node_pool_impl
//We initialize all Nodes in Node Block to insert
//them in the free Node list
- for(size_type i = 0; i < m_nodes_per_block; ++i, pNode += m_real_node_size){
+ for(size_type j = 0; j < m_nodes_per_block; ++j, pNode += m_real_node_size){
m_freelist.push_front(*new (pNode) node_t);
}
}
}
- catch(...){
+ BOOST_CATCH(...){
//to-do: if possible, an efficient way to deallocate allocated blocks
- throw;
+ BOOST_RETHROW
}
+ BOOST_CATCH_END
}
//!Deprecated, use deallocate_free_blocks
@@ -335,13 +334,13 @@ class private_node_pool_impl
private:
//!Returns a reference to the block hook placed in the end of the block
static node_t & get_block_hook (void *block, size_type blocksize)
- {
- return *reinterpret_cast<node_t*>(reinterpret_cast<char*>(block) + blocksize);
+ {
+ return *reinterpret_cast<node_t*>(reinterpret_cast<char*>(block) + blocksize);
}
//!Returns the starting address of the block reference to the block hook placed in the end of the block
void *get_block_from_hook (node_t *hook, size_type blocksize)
- {
+ {
return (reinterpret_cast<char*>(hook) - blocksize);
}
diff --git a/boost/container/detail/pair.hpp b/boost/container/detail/pair.hpp
index 2a20ed13ec..b7ad84c80e 100644
--- a/boost/container/detail/pair.hpp
+++ b/boost/container/detail/pair.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2005-2012.
+// (C) Copyright Ion Gaztanaga 2005-2013.
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
@@ -13,11 +13,11 @@
#ifndef BOOST_CONTAINER_CONTAINER_DETAIL_PAIR_HPP
#define BOOST_CONTAINER_CONTAINER_DETAIL_PAIR_HPP
-#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#if defined(_MSC_VER)
# pragma once
#endif
-#include "config_begin.hpp"
+#include <boost/container/detail/config_begin.hpp>
#include <boost/container/detail/workaround.hpp>
#include <boost/container/detail/mpl.hpp>
@@ -26,9 +26,10 @@
#include <boost/container/detail/type_traits.hpp>
#include <utility> //std::pair
+#include <algorithm> //std::swap
+
+#include <boost/move/utility_core.hpp>
-#include <boost/move/move.hpp>
-#include <boost/type_traits/is_class.hpp>
#ifndef BOOST_CONTAINER_PERFECT_FORWARDING
#include <boost/container/detail/preprocessor.hpp>
@@ -329,22 +330,42 @@ struct is_enum< ::boost::container::container_detail::pair<T, U> >
static const bool value = false;
};
+template <class T>
+struct is_class;
+
//This specialization is needed to avoid instantiation of pair in
//is_class, and allow recursive maps.
template <class T1, class T2>
struct is_class< ::boost::container::container_detail::pair<T1, T2> >
- : public ::boost::true_type
-{};
+{
+ static const bool value = true;
+};
-#ifdef BOOST_NO_RVALUE_REFERENCES
+#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES
template<class T1, class T2>
struct has_move_emulation_enabled< ::boost::container::container_detail::pair<T1, T2> >
- : ::boost::true_type
-{};
+{
+ static const bool value = true;
+};
#endif
+namespace move_detail{
+
+template<class T>
+struct is_class_or_union;
+
+template <class T1, class T2>
+struct is_class_or_union< ::boost::container::container_detail::pair<T1, T2> >
+//This specialization is needed to avoid instantiation of pair in
+//is_class, and allow recursive maps.
+{
+ static const bool value = true;
+};
+
+
+} //namespace move_detail{
} //namespace boost {
diff --git a/boost/container/detail/placement_new.hpp b/boost/container/detail/placement_new.hpp
new file mode 100644
index 0000000000..2489d8a45e
--- /dev/null
+++ b/boost/container/detail/placement_new.hpp
@@ -0,0 +1,27 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2014-2014. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/container for documentation.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_CONTAINER_DETAIL_PLACEMENT_NEW_HPP
+#define BOOST_CONTAINER_DETAIL_PLACEMENT_NEW_HPP
+
+#if defined(_MSC_VER)
+# pragma once
+#endif
+
+struct boost_container_new_t{};
+
+//avoid including <new>
+inline void *operator new(std::size_t, void *p, boost_container_new_t)
+{ return p; }
+
+inline void operator delete(void *, void *, boost_container_new_t)
+{}
+
+#endif //BOOST_CONTAINER_DETAIL_PLACEMENT_NEW_HPP
diff --git a/boost/container/detail/pool_common.hpp b/boost/container/detail/pool_common.hpp
index 500b9124d5..11fb6c2e50 100644
--- a/boost/container/detail/pool_common.hpp
+++ b/boost/container/detail/pool_common.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
+// (C) Copyright Ion Gaztanaga 2005-2013. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
@@ -8,16 +8,17 @@
//
//////////////////////////////////////////////////////////////////////////////
-#ifndef BOOST_CONTAINER_DETAIL_NODE_POOL_COMMON_HPP
-#define BOOST_CONTAINER_DETAIL_NODE_POOL_COMMON_HPP
+#ifndef BOOST_CONTAINER_DETAIL_POOL_COMMON_HPP
+#define BOOST_CONTAINER_DETAIL_POOL_COMMON_HPP
-#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#if defined(_MSC_VER)
# pragma once
#endif
-#include "config_begin.hpp"
+#include <boost/container/detail/config_begin.hpp>
+#include <boost/container/detail/workaround.hpp>
+
#include <boost/intrusive/slist.hpp>
-#include <new>
namespace boost {
namespace container {
@@ -34,7 +35,7 @@ struct node_slist
typedef slist_hook_t node_t;
typedef typename bi::make_slist
- <node_t, bi::linear<true>, bi::base_hook<slist_hook_t> >::type node_slist_t;
+ <node_t, bi::linear<true>, bi::cache_last<true>, bi::base_hook<slist_hook_t> >::type node_slist_t;
};
template<class T>
diff --git a/boost/container/detail/pool_common_alloc.hpp b/boost/container/detail/pool_common_alloc.hpp
new file mode 100644
index 0000000000..dfae7efd13
--- /dev/null
+++ b/boost/container/detail/pool_common_alloc.hpp
@@ -0,0 +1,98 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2005-2013. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_CONTAINER_DETAIL_POOL_COMMON_ALLOC_HPP
+#define BOOST_CONTAINER_DETAIL_POOL_COMMON_ALLOC_HPP
+
+#if defined(_MSC_VER)
+# pragma once
+#endif
+
+#include <boost/container/detail/config_begin.hpp>
+#include <boost/container/detail/workaround.hpp>
+#include <boost/container/throw_exception.hpp>
+
+#include <boost/intrusive/slist.hpp>
+#include <boost/container/detail/pool_common.hpp>
+#include <boost/container/detail/alloc_lib.h>
+#include <cstddef>
+
+namespace boost{
+namespace container{
+namespace container_detail{
+
+struct node_slist_helper
+ : public boost::container::container_detail::node_slist<void*>
+{};
+
+struct fake_segment_manager
+{
+ typedef void * void_pointer;
+ static const std::size_t PayloadPerAllocation = BOOST_CONTAINER_ALLOCATION_PAYLOAD;
+
+ typedef boost::container::container_detail::
+ basic_multiallocation_chain<void*> multiallocation_chain;
+ static void deallocate(void_pointer p)
+ { boost_cont_free(p); }
+
+ static void deallocate_many(multiallocation_chain &chain)
+ {
+ std::size_t size = chain.size();
+ std::pair<void*, void*> ptrs = chain.extract_data();
+ boost_cont_memchain dlchain;
+ BOOST_CONTAINER_MEMCHAIN_INIT_FROM(&dlchain, ptrs.first, ptrs.second, size);
+ boost_cont_multidealloc(&dlchain);
+ }
+
+ typedef std::ptrdiff_t difference_type;
+ typedef std::size_t size_type;
+
+ static void *allocate_aligned(std::size_t nbytes, std::size_t alignment)
+ {
+ void *ret = boost_cont_memalign(nbytes, alignment);
+ if(!ret)
+ boost::container::throw_bad_alloc();
+ return ret;
+ }
+
+ static void *allocate(std::size_t nbytes)
+ {
+ void *ret = boost_cont_malloc(nbytes);
+ if(!ret)
+ boost::container::throw_bad_alloc();
+ return ret;
+ }
+};
+
+} //namespace boost{
+} //namespace container{
+} //namespace container_detail{
+
+namespace boost {
+namespace container {
+namespace container_detail {
+
+template<class T>
+struct is_stateless_segment_manager;
+
+template<>
+struct is_stateless_segment_manager
+ <boost::container::container_detail::fake_segment_manager>
+{
+ static const bool value = true;
+};
+
+} //namespace container_detail {
+} //namespace container {
+} //namespace boost {
+
+#include <boost/container/detail/config_end.hpp>
+
+#endif //BOOST_CONTAINER_DETAIL_POOL_COMMON_ALLOC_HPP
diff --git a/boost/container/detail/preprocessor.hpp b/boost/container/detail/preprocessor.hpp
index 1818094be1..838eff2ca1 100644
--- a/boost/container/detail/preprocessor.hpp
+++ b/boost/container/detail/preprocessor.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2008-2012. Distributed under the Boost
+// (C) Copyright Ion Gaztanaga 2008-2013. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
@@ -11,17 +11,13 @@
#ifndef BOOST_CONTAINER_DETAIL_PREPROCESSOR_HPP
#define BOOST_CONTAINER_DETAIL_PREPROCESSOR_HPP
-#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#if defined(_MSC_VER)
# pragma once
#endif
#include <boost/container/detail/config_begin.hpp>
-
-#ifndef BOOST_NO_RVALUE_REFERENCES
-#include <boost/container/detail/stored_ref.hpp>
-#endif //#ifndef BOOST_NO_RVALUE_REFERENCES
-
#include <boost/container/detail/workaround.hpp>
+#include <boost/move/utility_core.hpp>
#ifdef BOOST_CONTAINER_PERFECT_FORWARDING
//#error "This file is not needed when perfect forwarding is available"
@@ -36,10 +32,7 @@
#include <boost/preprocessor/repetition/enum_params.hpp>
#include <boost/preprocessor/repetition/enum_trailing_params.hpp>
#include <boost/preprocessor/repetition/enum_trailing.hpp>
-#include <boost/preprocessor/repetition/enum_shifted_params.hpp>
-#include <boost/preprocessor/repetition/enum_shifted.hpp>
#include <boost/preprocessor/repetition/repeat.hpp>
-#include <boost/preprocessor/logical/not.hpp>
#include <boost/preprocessor/arithmetic/sub.hpp>
#include <boost/preprocessor/arithmetic/add.hpp>
#include <boost/preprocessor/iteration/iterate.hpp>
@@ -52,7 +45,7 @@
//This cast is ugly but it is necessary until "perfect forwarding"
//is achieved in C++0x. Meanwhile, if we want to be able to
//bind rvalues with non-const references, we have to be ugly
-#ifndef BOOST_NO_RVALUE_REFERENCES
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
#define BOOST_CONTAINER_PP_PARAM_LIST(z, n, data) \
BOOST_PP_CAT(P, n) && BOOST_PP_CAT(p, n) \
//!
@@ -60,13 +53,13 @@
#define BOOST_CONTAINER_PP_PARAM_LIST(z, n, data) \
const BOOST_PP_CAT(P, n) & BOOST_PP_CAT(p, n) \
//!
-#endif //#ifndef BOOST_NO_RVALUE_REFERENCES
+#endif //#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
#define BOOST_CONTAINER_PP_CONST_REF_PARAM_LIST_Q(z, n, Data) \
const BOOST_PP_CAT(Q, n) & BOOST_PP_CAT(q, n) \
//!
-#ifndef BOOST_NO_RVALUE_REFERENCES
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
#define BOOST_CONTAINER_PP_PARAM(U, u) \
U && u \
//!
@@ -74,36 +67,87 @@ const BOOST_PP_CAT(Q, n) & BOOST_PP_CAT(q, n) \
#define BOOST_CONTAINER_PP_PARAM(U, u) \
const U & u \
//!
-#endif //#ifndef BOOST_NO_RVALUE_REFERENCES
-
-#ifndef BOOST_NO_RVALUE_REFERENCES
-
- #if defined(BOOST_MOVE_MSVC_10_MEMBER_RVALUE_REF_BUG)
+#endif //#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
- #define BOOST_CONTAINER_PP_PARAM_INIT(z, n, data) \
- BOOST_PP_CAT(m_p, n) (static_cast<BOOST_PP_CAT(P, n)>( BOOST_PP_CAT(p, n) )) \
-
- #else //#if defined(BOOST_MOVE_MSVC_10_MEMBER_RVALUE_REF_BUG)
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
#define BOOST_CONTAINER_PP_PARAM_INIT(z, n, data) \
BOOST_PP_CAT(m_p, n) (::boost::forward< BOOST_PP_CAT(P, n) >( BOOST_PP_CAT(p, n) )) \
//!
- #endif //BOOST_MOVE_OLD_RVALUE_REF_BINDING_RULES
-
-#else //BOOST_NO_RVALUE_REFERENCES
+#else //BOOST_NO_CXX11_RVALUE_REFERENCES
#define BOOST_CONTAINER_PP_PARAM_INIT(z, n, data) \
BOOST_PP_CAT(m_p, n) (const_cast<BOOST_PP_CAT(P, n) &>(BOOST_PP_CAT(p, n))) \
//!
-#endif //#ifndef BOOST_NO_RVALUE_REFERENCES
+#endif //#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
-#ifndef BOOST_NO_RVALUE_REFERENCES
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
#if defined(BOOST_MOVE_MSVC_10_MEMBER_RVALUE_REF_BUG)
+ namespace boost {
+ namespace container {
+ namespace container_detail {
+ template<class T>
+ struct ref_holder;
+
+ template<class T>
+ struct ref_holder<T &>
+ {
+ explicit ref_holder(T &t)
+ : t_(t)
+ {}
+ T &t_;
+ T & get() { return t_; }
+ };
+
+ template<class T>
+ struct ref_holder<const T>
+ {
+ explicit ref_holder(const T &t)
+ : t_(t)
+ {}
+ const T &t_;
+ const T & get() { return t_; }
+ };
+
+ template<class T>
+ struct ref_holder<const T &&>
+ {
+ explicit ref_holder(const T &t)
+ : t_(t)
+ {}
+ const T &t_;
+ const T & get() { return t_; }
+ };
+
+ template<class T>
+ struct ref_holder
+ {
+ explicit ref_holder(T &&t)
+ : t_(t)
+ {}
+ T &t_;
+ T && get() { return ::boost::move(t_); }
+ };
+
+ template<class T>
+ struct ref_holder<T &&>
+ {
+ explicit ref_holder(T &&t)
+ : t_(t)
+ {}
+ T &t_;
+ T && get() { return ::boost::move(t_); }
+ };
+
+ } //namespace container_detail {
+ } //namespace container {
+ } //namespace boost {
+
#define BOOST_CONTAINER_PP_PARAM_DEFINE(z, n, data) \
- BOOST_PP_CAT(P, n) & BOOST_PP_CAT(m_p, n); \
+ ::boost::container::container_detail::ref_holder<BOOST_PP_CAT(P, n)> BOOST_PP_CAT(m_p, n); \
//!
#else //BOOST_MOVE_MSVC_10_MEMBER_RVALUE_REF_BUG
@@ -114,26 +158,25 @@ const BOOST_PP_CAT(Q, n) & BOOST_PP_CAT(q, n) \
#endif //defined(BOOST_MOVE_MSVC_10_MEMBER_RVALUE_REF_BUG)
-#else //BOOST_NO_RVALUE_REFERENCES
+#else //BOOST_NO_CXX11_RVALUE_REFERENCES
#define BOOST_CONTAINER_PP_PARAM_DEFINE(z, n, data) \
BOOST_PP_CAT(P, n) & BOOST_PP_CAT(m_p, n); \
//!
-#endif //#ifndef BOOST_NO_RVALUE_REFERENCES
+#endif //#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
-#if !defined(BOOST_NO_RVALUE_REFERENCES) && defined(BOOST_MOVE_MSVC_10_MEMBER_RVALUE_REF_BUG)
+#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && defined(BOOST_MOVE_MSVC_10_MEMBER_RVALUE_REF_BUG)
- #define BOOST_CONTAINER_PP_MEMBER_FORWARD(z, n, data) \
- ::boost::container::container_detail::stored_ref< BOOST_PP_CAT(P, n) >::forward( BOOST_PP_CAT(this->m_p, n) ) \
+ #define BOOST_CONTAINER_PP_MEMBER_FORWARD(z, n, data) BOOST_PP_CAT(this->m_p, n).get() \
//!
-#else //!defined(BOOST_NO_RVALUE_REFERENCES) && defined(BOOST_MOVE_MSVC_10_MEMBER_RVALUE_REF_BUG)
+#else //!defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && defined(BOOST_MOVE_MSVC_10_MEMBER_RVALUE_REF_BUG)
#define BOOST_CONTAINER_PP_MEMBER_FORWARD(z, n, data) \
::boost::forward< BOOST_PP_CAT(P, n) >( BOOST_PP_CAT(this->m_p, n) ) \
//!
-#endif //!defined(BOOST_NO_RVALUE_REFERENCES) && defined(BOOST_MOVE_MSVC_10_MEMBER_RVALUE_REF_BUG)
+#endif //!defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && defined(BOOST_MOVE_MSVC_10_MEMBER_RVALUE_REF_BUG)
#define BOOST_CONTAINER_PP_PARAM_INC(z, n, data) \
BOOST_PP_CAT(++this->m_p, n) \
diff --git a/boost/container/detail/singleton.hpp b/boost/container/detail/singleton.hpp
new file mode 100644
index 0000000000..a2372c3a96
--- /dev/null
+++ b/boost/container/detail/singleton.hpp
@@ -0,0 +1,117 @@
+// Copyright (C) 2000 Stephen Cleary
+// Copyright (C) 2008 Ion Gaztanaga
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org for updates, documentation, and revision history.
+//
+// This file is a modified file from Boost.Pool
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2007-2013. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_CONTAINER_DETAIL_SINGLETON_DETAIL_HPP
+#define BOOST_CONTAINER_DETAIL_SINGLETON_DETAIL_HPP
+
+#if defined(_MSC_VER)
+# pragma once
+#endif
+
+#include <boost/container/detail/config_begin.hpp>
+#include <boost/container/detail/workaround.hpp>
+
+//
+// The following helper classes are placeholders for a generic "singleton"
+// class. The classes below support usage of singletons, including use in
+// program startup/shutdown code, AS LONG AS there is only one thread
+// running before main() begins, and only one thread running after main()
+// exits.
+//
+// This class is also limited in that it can only provide singleton usage for
+// classes with default constructors.
+//
+
+// The design of this class is somewhat twisted, but can be followed by the
+// calling inheritance. Let us assume that there is some user code that
+// calls "singleton_default<T>::instance()". The following (convoluted)
+// sequence ensures that the same function will be called before main():
+// instance() contains a call to create_object.do_nothing()
+// Thus, object_creator is implicitly instantiated, and create_object
+// must exist.
+// Since create_object is a static member, its constructor must be
+// called before main().
+// The constructor contains a call to instance(), thus ensuring that
+// instance() will be called before main().
+// The first time instance() is called (i.e., before main()) is the
+// latest point in program execution where the object of type T
+// can be created.
+// Thus, any call to instance() will auto-magically result in a call to
+// instance() before main(), unless already present.
+// Furthermore, since the instance() function contains the object, instead
+// of the singleton_default class containing a static instance of the
+// object, that object is guaranteed to be constructed (at the latest) in
+// the first call to instance(). This permits calls to instance() from
+// static code, even if that code is called before the file-scope objects
+// in this file have been initialized.
+
+namespace boost {
+namespace container {
+namespace container_detail {
+
+// T must be: no-throw default constructible and no-throw destructible
+template <typename T>
+struct singleton_default
+{
+ private:
+ struct object_creator
+ {
+ // This constructor does nothing more than ensure that instance()
+ // is called before main() begins, thus creating the static
+ // T object before multithreading race issues can come up.
+ object_creator() { singleton_default<T>::instance(); }
+ inline void do_nothing() const { }
+ };
+ static object_creator create_object;
+
+ singleton_default();
+
+ public:
+ typedef T object_type;
+
+ // If, at any point (in user code), singleton_default<T>::instance()
+ // is called, then the following function is instantiated.
+ static object_type & instance()
+ {
+ // This is the object that we return a reference to.
+ // It is guaranteed to be created before main() begins because of
+ // the next line.
+ static object_type obj;
+
+ // The following line does nothing else than force the instantiation
+ // of singleton_default<T>::create_object, whose constructor is
+ // called before main() begins.
+ create_object.do_nothing();
+
+ return obj;
+ }
+};
+template <typename T>
+typename singleton_default<T>::object_creator
+singleton_default<T>::create_object;
+
+} // namespace container_detail
+} // namespace container
+} // namespace boost
+
+#include <boost/container/detail/config_end.hpp>
+
+#endif //BOOST_CONTAINER_DETAIL_SINGLETON_DETAIL_HPP
diff --git a/boost/container/detail/std_fwd.hpp b/boost/container/detail/std_fwd.hpp
new file mode 100644
index 0000000000..a2edeccff1
--- /dev/null
+++ b/boost/container/detail/std_fwd.hpp
@@ -0,0 +1,59 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2014-2014. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_CONTAINER_DETAIL_STD_FWD_HPP
+#define BOOST_CONTAINER_DETAIL_STD_FWD_HPP
+
+#if defined(_MSC_VER)
+# pragma once
+#endif
+
+//////////////////////////////////////////////////////////////////////////////
+// Standard predeclarations
+//////////////////////////////////////////////////////////////////////////////
+
+#if defined(__clang__) && defined(_LIBCPP_VERSION)
+ #define BOOST_CONTAINER_CLANG_INLINE_STD_NS
+ #pragma GCC diagnostic push
+ #pragma GCC diagnostic ignored "-Wc++11-extensions"
+ #define BOOST_CONTAINER_STD_NS_BEG _LIBCPP_BEGIN_NAMESPACE_STD
+ #define BOOST_CONTAINER_STD_NS_END _LIBCPP_END_NAMESPACE_STD
+#else
+ #define BOOST_CONTAINER_STD_NS_BEG namespace std{
+ #define BOOST_CONTAINER_STD_NS_END }
+#endif
+
+BOOST_CONTAINER_STD_NS_BEG
+
+template<class T>
+class allocator;
+
+template<class T>
+struct less;
+
+template<class T1, class T2>
+struct pair;
+
+template<class T>
+struct char_traits;
+
+struct input_iterator_tag;
+struct forward_iterator_tag;
+struct bidirectional_iterator_tag;
+struct random_access_iterator_tag;
+
+BOOST_CONTAINER_STD_NS_END
+
+#ifdef BOOST_CONTAINER_CLANG_INLINE_STD_NS
+ #pragma GCC diagnostic pop
+ #undef BOOST_CONTAINER_CLANG_INLINE_STD_NS
+#endif //BOOST_CONTAINER_CLANG_INLINE_STD_NS
+
+#endif //#ifndef BOOST_CONTAINER_DETAIL_STD_FWD_HPP
diff --git a/boost/container/detail/stored_ref.hpp b/boost/container/detail/stored_ref.hpp
deleted file mode 100644
index 80fda89615..0000000000
--- a/boost/container/detail/stored_ref.hpp
+++ /dev/null
@@ -1,92 +0,0 @@
-//////////////////////////////////////////////////////////////////////////////
-//
-// (C) Copyright Ion Gaztanaga 2008-2012. Distributed under the Boost
-// Software License, Version 1.0. (See accompanying file
-// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
-//
-// See http://www.boost.org/libs/container for documentation.
-//
-//////////////////////////////////////////////////////////////////////////////
-
-#ifndef BOOST_CONTAINER_DETAIL_STORED_REF_HPP
-#define BOOST_CONTAINER_DETAIL_STORED_REF_HPP
-
-#include "config_begin.hpp"
-#include <boost/container/detail/workaround.hpp>
-
-#ifndef BOOST_NO_RVALUE_REFERENCES
-
-namespace boost{
-namespace container{
-namespace container_detail{
-
-template<class T>
-struct stored_ref
-{
-
- static T && forward(T &t)
- #ifdef BOOST_MOVE_OLD_RVALUE_REF_BINDING_RULES
- { return t; }
- #else
- { return boost::move(t); }
- #endif
-};
-
-template<class T>
-struct stored_ref<const T>
-{
- static const T && forward(const T &t)
- #ifdef BOOST_MOVE_OLD_RVALUE_REF_BINDING_RULES
- { return t; }
- #else
- { return static_cast<const T&&>(t); }
- #endif
-};
-
-template<class T>
-struct stored_ref<T&&>
-{
- static T && forward(T &t)
- #ifdef BOOST_MOVE_OLD_RVALUE_REF_BINDING_RULES
- { return t; }
- #else
- { return boost::move(t); }
- #endif
-};
-
-template<class T>
-struct stored_ref<const T&&>
-{
- static const T && forward(const T &t)
- #ifdef BOOST_MOVE_OLD_RVALUE_REF_BINDING_RULES
- { return t; }
- #else
- { return static_cast<const T &&>(t); }
- #endif
-};
-
-template<class T>
-struct stored_ref<const T&>
-{
- static const T & forward(const T &t)
- { return t; }
-};
-
-template<class T>
-struct stored_ref<T&>
-{
- static T & forward(T &t)
- { return t; }
-};
-
-} //namespace container_detail{
-} //namespace container{
-} //namespace boost{
-
-#else
-#error "This header can be included only for compiler with rvalue references"
-#endif //BOOST_NO_RVALUE_REFERENCES
-
-#include <boost/container/detail/config_end.hpp>
-
-#endif //BOOST_CONTAINER_DETAIL_STORED_REF_HPP
diff --git a/boost/container/detail/transform_iterator.hpp b/boost/container/detail/transform_iterator.hpp
index 98f5c04d60..c4e746c389 100644
--- a/boost/container/detail/transform_iterator.hpp
+++ b/boost/container/detail/transform_iterator.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2005-2012.
+// (C) Copyright Ion Gaztanaga 2005-2013.
// (C) Copyright Gennaro Prota 2003 - 2004.
//
// Distributed under the Boost Software License, Version 1.0.
@@ -14,12 +14,13 @@
#ifndef BOOST_CONTAINER_DETAIL_TRANSFORM_ITERATORS_HPP
#define BOOST_CONTAINER_DETAIL_TRANSFORM_ITERATORS_HPP
-#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#if defined(_MSC_VER)
# pragma once
#endif
-#include "config_begin.hpp"
+#include <boost/container/detail/config_begin.hpp>
#include <boost/container/detail/workaround.hpp>
+
#include <boost/container/detail/type_traits.hpp>
#include <iterator>
@@ -33,10 +34,10 @@ struct operator_arrow_proxy
: m_value(px)
{}
+ typedef PseudoReference element_type;
+
PseudoReference* operator->() const { return &m_value; }
- // This function is needed for MWCW and BCC, which won't call operator->
- // again automatically per 13.3.1.2 para 8
-// operator T*() const { return &m_value; }
+
mutable PseudoReference m_value;
};
@@ -47,10 +48,10 @@ struct operator_arrow_proxy<T&>
: m_value(px)
{}
+ typedef T element_type;
+
T* operator->() const { return const_cast<T*>(&m_value); }
- // This function is needed for MWCW and BCC, which won't call operator->
- // again automatically per 13.3.1.2 para 8
-// operator T*() const { return &m_value; }
+
T &m_value;
};
diff --git a/boost/container/detail/tree.hpp b/boost/container/detail/tree.hpp
index 3ab1536204..e59bca0887 100644
--- a/boost/container/detail/tree.hpp
+++ b/boost/container/detail/tree.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
+// (C) Copyright Ion Gaztanaga 2005-2013. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
@@ -11,23 +11,35 @@
#ifndef BOOST_CONTAINER_TREE_HPP
#define BOOST_CONTAINER_TREE_HPP
-#include "config_begin.hpp"
+#if defined(_MSC_VER)
+# pragma once
+#endif
+
+#include <boost/container/detail/config_begin.hpp>
#include <boost/container/detail/workaround.hpp>
#include <boost/container/container_fwd.hpp>
-#include <boost/move/move.hpp>
-#include <boost/intrusive/pointer_traits.hpp>
-#include <boost/type_traits/has_trivial_destructor.hpp>
-#include <boost/detail/no_exceptions_support.hpp>
-#include <boost/intrusive/rbtree.hpp>
-
#include <boost/container/detail/utilities.hpp>
+#include <boost/container/detail/iterators.hpp>
#include <boost/container/detail/algorithms.hpp>
#include <boost/container/detail/node_alloc_holder.hpp>
#include <boost/container/detail/destroyers.hpp>
#include <boost/container/detail/pair.hpp>
#include <boost/container/detail/type_traits.hpp>
#include <boost/container/allocator_traits.hpp>
+#include <boost/container/options.hpp>
+
+//
+#include <boost/intrusive/pointer_traits.hpp>
+#include <boost/intrusive/rbtree.hpp>
+#include <boost/intrusive/avltree.hpp>
+#include <boost/intrusive/splaytree.hpp>
+#include <boost/intrusive/sgtree.hpp>
+//
+#include <boost/move/utility_core.hpp>
+#include <boost/type_traits/has_trivial_destructor.hpp>
+#include <boost/core/no_exceptions_support.hpp>
+//
#ifndef BOOST_CONTAINER_PERFECT_FORWARDING
#include <boost/container/detail/preprocessor.hpp>
#endif
@@ -41,7 +53,7 @@ namespace container {
namespace container_detail {
template<class Key, class Value, class KeyCompare, class KeyOfValue>
-struct value_compare_impl
+struct tree_value_compare
: public KeyCompare
{
typedef Value value_type;
@@ -49,8 +61,12 @@ struct value_compare_impl
typedef KeyOfValue key_of_value;
typedef Key key_type;
- value_compare_impl(const key_compare &kcomp)
- : key_compare(kcomp)
+ explicit tree_value_compare(const key_compare &kcomp)
+ : KeyCompare(kcomp)
+ {}
+
+ tree_value_compare()
+ : KeyCompare()
{}
const key_compare &key_comp() const
@@ -80,47 +96,78 @@ struct value_compare_impl
{ return key_compare::operator()(this->key_forward(key1), this->key_forward(key2)); }
};
-template<class VoidPointer>
-struct rbtree_hook
+template<class VoidPointer, boost::container::tree_type_enum tree_type_value, bool OptimizeSize>
+struct intrusive_tree_hook;
+
+template<class VoidPointer, bool OptimizeSize>
+struct intrusive_tree_hook<VoidPointer, boost::container::red_black_tree, OptimizeSize>
{
typedef typename container_detail::bi::make_set_base_hook
< container_detail::bi::void_pointer<VoidPointer>
, container_detail::bi::link_mode<container_detail::bi::normal_link>
- , container_detail::bi::optimize_size<true>
+ , container_detail::bi::optimize_size<OptimizeSize>
+ >::type type;
+};
+
+template<class VoidPointer, bool OptimizeSize>
+struct intrusive_tree_hook<VoidPointer, boost::container::avl_tree, OptimizeSize>
+{
+ typedef typename container_detail::bi::make_avl_set_base_hook
+ < container_detail::bi::void_pointer<VoidPointer>
+ , container_detail::bi::link_mode<container_detail::bi::normal_link>
+ , container_detail::bi::optimize_size<OptimizeSize>
+ >::type type;
+};
+
+template<class VoidPointer, bool OptimizeSize>
+struct intrusive_tree_hook<VoidPointer, boost::container::scapegoat_tree, OptimizeSize>
+{
+ typedef typename container_detail::bi::make_bs_set_base_hook
+ < container_detail::bi::void_pointer<VoidPointer>
+ , container_detail::bi::link_mode<container_detail::bi::normal_link>
+ >::type type;
+};
+
+template<class VoidPointer, bool OptimizeSize>
+struct intrusive_tree_hook<VoidPointer, boost::container::splay_tree, OptimizeSize>
+{
+ typedef typename container_detail::bi::make_bs_set_base_hook
+ < container_detail::bi::void_pointer<VoidPointer>
+ , container_detail::bi::link_mode<container_detail::bi::normal_link>
>::type type;
};
//This trait is used to type-pun std::pair because in C++03
//compilers std::pair is useless for C++11 features
template<class T>
-struct rbtree_internal_data_type
+struct tree_internal_data_type
{
typedef T type;
};
template<class T1, class T2>
-struct rbtree_internal_data_type< std::pair<T1, T2> >
+struct tree_internal_data_type< std::pair<T1, T2> >
{
typedef pair<T1, T2> type;
};
-
//The node to be store in the tree
-template <class T, class VoidPointer>
-struct rbtree_node
- : public rbtree_hook<VoidPointer>::type
+template <class T, class VoidPointer, boost::container::tree_type_enum tree_type_value, bool OptimizeSize>
+struct tree_node
+ : public intrusive_tree_hook<VoidPointer, tree_type_value, OptimizeSize>::type
{
private:
- //BOOST_COPYABLE_AND_MOVABLE(rbtree_node)
- rbtree_node();
+ //BOOST_COPYABLE_AND_MOVABLE(tree_node)
+ tree_node();
public:
- typedef typename rbtree_hook<VoidPointer>::type hook_type;
-
+ typedef typename intrusive_tree_hook
+ <VoidPointer, tree_type_value, OptimizeSize>::type hook_type;
typedef T value_type;
- typedef typename rbtree_internal_data_type<T>::type internal_type;
+ typedef typename tree_internal_data_type<T>::type internal_type;
- typedef rbtree_node<T, VoidPointer> node_type;
+ typedef tree_node< T, VoidPointer
+ , tree_type_value, OptimizeSize> node_type;
T &get_data()
{
@@ -173,56 +220,261 @@ struct rbtree_node
{ m_data = ::boost::move(v); }
};
+template <class T, class VoidPointer, boost::container::tree_type_enum tree_type_value, bool OptimizeSize>
+struct iiterator_node_value_type< tree_node<T, VoidPointer, tree_type_value, OptimizeSize> > {
+ typedef T type;
+};
+
+template<class Node, class Icont>
+class insert_equal_end_hint_functor
+{
+ Icont &icont_;
+
+ public:
+ insert_equal_end_hint_functor(Icont &icont)
+ : icont_(icont)
+ {}
+
+ void operator()(Node &n)
+ { this->icont_.insert_equal(this->icont_.cend(), n); }
+};
+
+template<class Node, class Icont>
+class push_back_functor
+{
+ Icont &icont_;
+
+ public:
+ push_back_functor(Icont &icont)
+ : icont_(icont)
+ {}
+
+ void operator()(Node &n)
+ { this->icont_.push_back(n); }
+};
+
}//namespace container_detail {
namespace container_detail {
-template<class A, class ValueCompare>
-struct intrusive_rbtree_type
+template< class NodeType, class NodeCompareType
+ , class SizeType, class HookType
+ , boost::container::tree_type_enum tree_type_value>
+struct intrusive_tree_dispatch;
+
+template<class NodeType, class NodeCompareType, class SizeType, class HookType>
+struct intrusive_tree_dispatch
+ <NodeType, NodeCompareType, SizeType, HookType, boost::container::red_black_tree>
{
+ typedef typename container_detail::bi::make_rbtree
+ <NodeType
+ ,container_detail::bi::compare<NodeCompareType>
+ ,container_detail::bi::base_hook<HookType>
+ ,container_detail::bi::constant_time_size<true>
+ ,container_detail::bi::size_type<SizeType>
+ >::type type;
+};
+
+template<class NodeType, class NodeCompareType, class SizeType, class HookType>
+struct intrusive_tree_dispatch
+ <NodeType, NodeCompareType, SizeType, HookType, boost::container::avl_tree>
+{
+ typedef typename container_detail::bi::make_avltree
+ <NodeType
+ ,container_detail::bi::compare<NodeCompareType>
+ ,container_detail::bi::base_hook<HookType>
+ ,container_detail::bi::constant_time_size<true>
+ ,container_detail::bi::size_type<SizeType>
+ >::type type;
+};
+
+template<class NodeType, class NodeCompareType, class SizeType, class HookType>
+struct intrusive_tree_dispatch
+ <NodeType, NodeCompareType, SizeType, HookType, boost::container::scapegoat_tree>
+{
+ typedef typename container_detail::bi::make_sgtree
+ <NodeType
+ ,container_detail::bi::compare<NodeCompareType>
+ ,container_detail::bi::base_hook<HookType>
+ ,container_detail::bi::floating_point<true>
+ ,container_detail::bi::size_type<SizeType>
+ >::type type;
+};
+
+template<class NodeType, class NodeCompareType, class SizeType, class HookType>
+struct intrusive_tree_dispatch
+ <NodeType, NodeCompareType, SizeType, HookType, boost::container::splay_tree>
+{
+ typedef typename container_detail::bi::make_splaytree
+ <NodeType
+ ,container_detail::bi::compare<NodeCompareType>
+ ,container_detail::bi::base_hook<HookType>
+ ,container_detail::bi::constant_time_size<true>
+ ,container_detail::bi::size_type<SizeType>
+ >::type type;
+};
+
+template<class A, class ValueCompare, boost::container::tree_type_enum tree_type_value, bool OptimizeSize>
+struct intrusive_tree_type
+{
+ private:
typedef typename boost::container::
allocator_traits<A>::value_type value_type;
typedef typename boost::container::
allocator_traits<A>::void_pointer void_pointer;
typedef typename boost::container::
allocator_traits<A>::size_type size_type;
- typedef typename container_detail::rbtree_node
- <value_type, void_pointer> node_type;
+ typedef typename container_detail::tree_node
+ < value_type, void_pointer
+ , tree_type_value, OptimizeSize> node_type;
typedef node_compare<ValueCompare, node_type> node_compare_type;
- typedef typename container_detail::bi::make_rbtree
- <node_type
- ,container_detail::bi::compare<node_compare_type>
- ,container_detail::bi::base_hook<typename rbtree_hook<void_pointer>::type>
- ,container_detail::bi::constant_time_size<true>
- ,container_detail::bi::size_type<size_type>
- >::type container_type;
- typedef container_type type ;
+ //Deducing the hook type from node_type (e.g. node_type::hook_type) would
+ //provoke an early instantiation of node_type that could ruin recursive
+ //tree definitions, so retype the complete type to avoid any problem.
+ typedef typename intrusive_tree_hook
+ <void_pointer, tree_type_value
+ , OptimizeSize>::type hook_type;
+ public:
+ typedef typename intrusive_tree_dispatch
+ < node_type, node_compare_type
+ , size_type, hook_type
+ , tree_type_value>::type type;
+};
+
+//Trait to detect manually rebalanceable tree types
+template<boost::container::tree_type_enum tree_type_value>
+struct is_manually_balanceable
+{ static const bool value = true; };
+
+template<> struct is_manually_balanceable<red_black_tree>
+{ static const bool value = false; };
+
+template<> struct is_manually_balanceable<avl_tree>
+{ static const bool value = false; };
+
+//Proxy traits to implement different operations depending on the
+//is_manually_balanceable<>::value
+template< boost::container::tree_type_enum tree_type_value
+ , bool IsManuallyRebalanceable = is_manually_balanceable<tree_type_value>::value>
+struct intrusive_tree_proxy
+{
+ template<class Icont>
+ static void rebalance(Icont &) {}
+};
+
+template<boost::container::tree_type_enum tree_type_value>
+struct intrusive_tree_proxy<tree_type_value, true>
+{
+ template<class Icont>
+ static void rebalance(Icont &c)
+ { c.rebalance(); }
};
} //namespace container_detail {
namespace container_detail {
+//This functor will be used with Intrusive clone functions to obtain
+//already allocated nodes from a intrusive container instead of
+//allocating new ones. When the intrusive container runs out of nodes
+//the node holder is used instead.
+template<class AllocHolder, bool DoMove>
+class RecyclingCloner
+{
+ typedef typename AllocHolder::intrusive_container intrusive_container;
+ typedef typename AllocHolder::Node node_type;
+ typedef typename AllocHolder::NodePtr node_ptr_type;
+
+ public:
+ RecyclingCloner(AllocHolder &holder, intrusive_container &itree)
+ : m_holder(holder), m_icont(itree)
+ {}
+
+ static void do_assign(node_ptr_type &p, const node_type &other, bool_<true>)
+ { p->do_assign(other.m_data); }
+
+ static void do_assign(node_ptr_type &p, const node_type &other, bool_<false>)
+ { p->do_move_assign(const_cast<node_type &>(other).m_data); }
+
+ node_ptr_type operator()(const node_type &other) const
+ {
+ if(node_ptr_type p = m_icont.unlink_leftmost_without_rebalance()){
+ //First recycle a node (this can't throw)
+ BOOST_TRY{
+ //This can throw
+ this->do_assign(p, other, bool_<DoMove>());
+ return p;
+ }
+ BOOST_CATCH(...){
+ //If there is an exception destroy the whole source
+ m_holder.destroy_node(p);
+ while((p = m_icont.unlink_leftmost_without_rebalance())){
+ m_holder.destroy_node(p);
+ }
+ BOOST_RETHROW
+ }
+ BOOST_CATCH_END
+ }
+ else{
+ return m_holder.create_node(other.m_data);
+ }
+ }
+
+ AllocHolder &m_holder;
+ intrusive_container &m_icont;
+};
+
+template<class KeyValueCompare, class Node>
+//where KeyValueCompare is tree_value_compare<Key, Value, KeyCompare, KeyOfValue>
+struct key_node_compare
+ : private KeyValueCompare
+{
+ explicit key_node_compare(const KeyValueCompare &comp)
+ : KeyValueCompare(comp)
+ {}
+
+ template<class T>
+ struct is_node
+ {
+ static const bool value = is_same<T, Node>::value;
+ };
+
+ template<class T>
+ typename enable_if_c<is_node<T>::value, const typename KeyValueCompare::value_type &>::type
+ key_forward(const T &node) const
+ { return node.get_data(); }
+
+ template<class T>
+ typename enable_if_c<!is_node<T>::value, const T &>::type
+ key_forward(const T &key) const
+ { return key; }
+
+ template<class KeyType, class KeyType2>
+ bool operator()(const KeyType &key1, const KeyType2 &key2) const
+ { return KeyValueCompare::operator()(this->key_forward(key1), this->key_forward(key2)); }
+};
+
template <class Key, class Value, class KeyOfValue,
- class KeyCompare, class A>
-class rbtree
+ class KeyCompare, class A,
+ class Options = tree_assoc_defaults>
+class tree
: protected container_detail::node_alloc_holder
< A
- , typename container_detail::intrusive_rbtree_type
- <A, value_compare_impl<Key, Value, KeyCompare, KeyOfValue>
- >::type
- , KeyCompare
+ , typename container_detail::intrusive_tree_type
+ < A, tree_value_compare<Key, Value, KeyCompare, KeyOfValue> //ValComp
+ , Options::tree_type, Options::optimize_size>::type
>
{
- typedef typename container_detail::intrusive_rbtree_type
- < A, value_compare_impl
- <Key, Value, KeyCompare, KeyOfValue>
- >::type Icont;
- typedef container_detail::node_alloc_holder
- <A, Icont, KeyCompare> AllocHolder;
+ typedef tree_value_compare
+ <Key, Value, KeyCompare, KeyOfValue> ValComp;
+ typedef typename container_detail::intrusive_tree_type
+ < A, ValComp, Options::tree_type
+ , Options::optimize_size>::type Icont;
+ typedef container_detail::node_alloc_holder
+ <A, Icont> AllocHolder;
typedef typename AllocHolder::NodePtr NodePtr;
- typedef rbtree < Key, Value, KeyOfValue
- , KeyCompare, A> ThisType;
+ typedef tree < Key, Value, KeyOfValue
+ , KeyCompare, A, Options> ThisType;
typedef typename AllocHolder::NodeAlloc NodeAlloc;
typedef typename AllocHolder::ValAlloc ValAlloc;
typedef typename AllocHolder::Node Node;
@@ -232,82 +484,9 @@ class rbtree
typedef typename AllocHolder::allocator_v1 allocator_v1;
typedef typename AllocHolder::allocator_v2 allocator_v2;
typedef typename AllocHolder::alloc_version alloc_version;
+ typedef intrusive_tree_proxy<Options::tree_type> intrusive_tree_proxy_t;
- class RecyclingCloner;
- friend class RecyclingCloner;
-
- class RecyclingCloner
- {
- public:
- RecyclingCloner(AllocHolder &holder, Icont &irbtree)
- : m_holder(holder), m_icont(irbtree)
- {}
-
- NodePtr operator()(const Node &other) const
- {
- if(NodePtr p = m_icont.unlink_leftmost_without_rebalance()){
- //First recycle a node (this can't throw)
- try{
- //This can throw
- p->do_assign(other.m_data);
- return p;
- }
- catch(...){
- //If there is an exception destroy the whole source
- m_holder.destroy_node(p);
- while((p = m_icont.unlink_leftmost_without_rebalance())){
- m_holder.destroy_node(p);
- }
- throw;
- }
- }
- else{
- return m_holder.create_node(other.m_data);
- }
- }
-
- AllocHolder &m_holder;
- Icont &m_icont;
- };
-
- class RecyclingMoveCloner;
- friend class RecyclingMoveCloner;
-
- class RecyclingMoveCloner
- {
- public:
- RecyclingMoveCloner(AllocHolder &holder, Icont &irbtree)
- : m_holder(holder), m_icont(irbtree)
- {}
-
- NodePtr operator()(const Node &other) const
- {
- if(NodePtr p = m_icont.unlink_leftmost_without_rebalance()){
- //First recycle a node (this can't throw)
- try{
- //This can throw
- p->do_move_assign(const_cast<Node &>(other).m_data);
- return p;
- }
- catch(...){
- //If there is an exception destroy the whole source
- m_holder.destroy_node(p);
- while((p = m_icont.unlink_leftmost_without_rebalance())){
- m_holder.destroy_node(p);
- }
- throw;
- }
- }
- else{
- return m_holder.create_node(other.m_data);
- }
- }
-
- AllocHolder &m_holder;
- Icont &m_icont;
- };
-
- BOOST_COPYABLE_AND_MOVABLE(rbtree)
+ BOOST_COPYABLE_AND_MOVABLE(tree)
public:
@@ -315,8 +494,7 @@ class rbtree
typedef Value value_type;
typedef A allocator_type;
typedef KeyCompare key_compare;
- typedef value_compare_impl< Key, Value
- , KeyCompare, KeyOfValue> value_compare;
+ typedef ValComp value_compare;
typedef typename boost::container::
allocator_traits<A>::pointer pointer;
typedef typename boost::container::
@@ -329,190 +507,147 @@ class rbtree
allocator_traits<A>::size_type size_type;
typedef typename boost::container::
allocator_traits<A>::difference_type difference_type;
- typedef difference_type rbtree_difference_type;
- typedef pointer rbtree_pointer;
- typedef const_pointer rbtree_const_pointer;
- typedef reference rbtree_reference;
- typedef const_reference rbtree_const_reference;
+ typedef difference_type tree_difference_type;
+ typedef pointer tree_pointer;
+ typedef const_pointer tree_const_pointer;
+ typedef reference tree_reference;
+ typedef const_reference tree_const_reference;
typedef NodeAlloc stored_allocator_type;
private:
- template<class KeyValueCompare>
- struct key_node_compare
- : private KeyValueCompare
- {
- key_node_compare(const KeyValueCompare &comp)
- : KeyValueCompare(comp)
- {}
-
- template<class T>
- struct is_node
- {
- static const bool value = is_same<T, Node>::value;
- };
-
- template<class T>
- typename enable_if_c<is_node<T>::value, const value_type &>::type
- key_forward(const T &node) const
- { return node.get_data(); }
-
- template<class T>
- typename enable_if_c<!is_node<T>::value, const T &>::type
- key_forward(const T &key) const
- { return key; }
-
- template<class KeyType, class KeyType2>
- bool operator()(const KeyType &key1, const KeyType2 &key2) const
- { return KeyValueCompare::operator()(this->key_forward(key1), this->key_forward(key2)); }
- };
-
- typedef key_node_compare<value_compare> KeyNodeCompare;
+ typedef key_node_compare<value_compare, Node> KeyNodeCompare;
public:
- //rbtree const_iterator
- class const_iterator
- : public std::iterator
- < std::bidirectional_iterator_tag
- , value_type , rbtree_difference_type
- , rbtree_const_pointer , rbtree_const_reference>
- {
- protected:
- typedef typename Icont::iterator iiterator;
- iiterator m_it;
- explicit const_iterator(iiterator it) : m_it(it){}
- void prot_incr() { ++m_it; }
- void prot_decr() { --m_it; }
-
- private:
- iiterator get()
- { return this->m_it; }
-
- public:
- friend class rbtree <Key, Value, KeyOfValue, KeyCompare, A>;
- typedef rbtree_difference_type difference_type;
+ typedef container_detail::iterator<iiterator, false> iterator;
+ typedef container_detail::iterator<iiterator, true > const_iterator;
+ typedef container_detail::reverse_iterator<iterator> reverse_iterator;
+ typedef container_detail::reverse_iterator<const_iterator> const_reverse_iterator;
- //Constructors
- const_iterator()
- : m_it()
- {}
-
- //Pointer like operators
- const_reference operator*() const
- { return m_it->get_data(); }
-
- const_pointer operator->() const
- { return const_pointer(&m_it->get_data()); }
-
- //Increment / Decrement
- const_iterator& operator++()
- { prot_incr(); return *this; }
-
- const_iterator operator++(int)
- { iiterator tmp = m_it; ++*this; return const_iterator(tmp); }
-
- const_iterator& operator--()
- { prot_decr(); return *this; }
-
- const_iterator operator--(int)
- { iiterator tmp = m_it; --*this; return const_iterator(tmp); }
+ tree()
+ : AllocHolder(ValComp(key_compare()))
+ {}
- //Comparison operators
- bool operator== (const const_iterator& r) const
- { return m_it == r.m_it; }
+ explicit tree(const key_compare& comp, const allocator_type& a = allocator_type())
+ : AllocHolder(a, ValComp(comp))
+ {}
- bool operator!= (const const_iterator& r) const
- { return m_it != r.m_it; }
- };
+ explicit tree(const allocator_type& a)
+ : AllocHolder(a)
+ {}
- //rbtree iterator
- class iterator : public const_iterator
+ template <class InputIterator>
+ tree(bool unique_insertion, InputIterator first, InputIterator last, const key_compare& comp,
+ const allocator_type& a
+ #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+ , typename container_detail::enable_if_c
+ < container_detail::is_input_iterator<InputIterator>::value
+ || container_detail::is_same<alloc_version, allocator_v1>::value
+ >::type * = 0
+ #endif
+ )
+ : AllocHolder(a, value_compare(comp))
{
- private:
- explicit iterator(iiterator it)
- : const_iterator(it)
- {}
-
- iiterator get()
- { return this->m_it; }
-
- public:
- friend class rbtree <Key, Value, KeyOfValue, KeyCompare, A>;
- typedef rbtree_pointer pointer;
- typedef rbtree_reference reference;
-
- //Constructors
- iterator(){}
-
- //Pointer like operators
- reference operator*() const
- { return this->m_it->get_data(); }
- pointer operator->() const
- { return boost::intrusive::pointer_traits<pointer>::pointer_to(this->m_it->get_data()); }
-
- //Increment / Decrement
- iterator& operator++()
- { this->prot_incr(); return *this; }
-
- iterator operator++(int)
- { iiterator tmp = this->m_it; ++*this; return iterator(tmp); }
-
- iterator& operator--()
- { this->prot_decr(); return *this; }
-
- iterator operator--(int)
- { iterator tmp = *this; --*this; return tmp; }
- };
-
- typedef std::reverse_iterator<iterator> reverse_iterator;
- typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
-
- rbtree()
- : AllocHolder(key_compare())
- {}
+ //Use cend() as hint to achieve linear time for
+ //ordered ranges as required by the standard
+ //for the constructor
+ const const_iterator end_it(this->cend());
+ if(unique_insertion){
+ for ( ; first != last; ++first){
+ this->insert_unique(end_it, *first);
+ }
+ }
+ else{
+ for ( ; first != last; ++first){
+ this->insert_equal(end_it, *first);
+ }
+ }
+ }
- rbtree(const key_compare& comp, const allocator_type& a = allocator_type())
- : AllocHolder(a, comp)
- {}
+ template <class InputIterator>
+ tree(bool unique_insertion, InputIterator first, InputIterator last, const key_compare& comp,
+ const allocator_type& a
+ #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+ , typename container_detail::enable_if_c
+ < !(container_detail::is_input_iterator<InputIterator>::value
+ || container_detail::is_same<alloc_version, allocator_v1>::value)
+ >::type * = 0
+ #endif
+ )
+ : AllocHolder(a, value_compare(comp))
+ {
+ if(unique_insertion){
+ //Use cend() as hint to achieve linear time for
+ //ordered ranges as required by the standard
+ //for the constructor
+ const const_iterator end_it(this->cend());
+ for ( ; first != last; ++first){
+ this->insert_unique(end_it, *first);
+ }
+ }
+ else{
+ //Optimized allocation and construction
+ this->allocate_many_and_construct
+ ( first, std::distance(first, last)
+ , insert_equal_end_hint_functor<Node, Icont>(this->icont()));
+ }
+ }
template <class InputIterator>
- rbtree(InputIterator first, InputIterator last, const key_compare& comp,
- const allocator_type& a, bool unique_insertion)
- : AllocHolder(a, comp)
+ tree( ordered_range_t, InputIterator first, InputIterator last
+ , const key_compare& comp = key_compare(), const allocator_type& a = allocator_type()
+ #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+ , typename container_detail::enable_if_c
+ < container_detail::is_input_iterator<InputIterator>::value
+ || container_detail::is_same<alloc_version, allocator_v1>::value
+ >::type * = 0
+ #endif
+ )
+ : AllocHolder(a, value_compare(comp))
{
- typedef typename std::iterator_traits<InputIterator>::iterator_category ItCat;
- priv_create_and_insert_nodes(first, last, unique_insertion, alloc_version(), ItCat());
+ for ( ; first != last; ++first){
+ this->push_back_impl(*first);
+ }
}
template <class InputIterator>
- rbtree( ordered_range_t, InputIterator first, InputIterator last
- , const key_compare& comp = key_compare(), const allocator_type& a = allocator_type())
- : AllocHolder(a, comp)
+ tree( ordered_range_t, InputIterator first, InputIterator last
+ , const key_compare& comp = key_compare(), const allocator_type& a = allocator_type()
+ #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+ , typename container_detail::enable_if_c
+ < !(container_detail::is_input_iterator<InputIterator>::value
+ || container_detail::is_same<alloc_version, allocator_v1>::value)
+ >::type * = 0
+ #endif
+ )
+ : AllocHolder(a, value_compare(comp))
{
- typedef typename std::iterator_traits<InputIterator>::iterator_category ItCat;
- priv_create_and_insert_ordered_nodes(first, last, alloc_version(), ItCat());
+ //Optimized allocation and construction
+ this->allocate_many_and_construct
+ ( first, std::distance(first, last)
+ , container_detail::push_back_functor<Node, Icont>(this->icont()));
}
- rbtree(const rbtree& x)
- : AllocHolder(x, x.key_comp())
+ tree(const tree& x)
+ : AllocHolder(x, x.value_comp())
{
this->icont().clone_from
(x.icont(), typename AllocHolder::cloner(*this), Destroyer(this->node_alloc()));
}
- rbtree(BOOST_RV_REF(rbtree) x)
- : AllocHolder(::boost::move(static_cast<AllocHolder&>(x)), x.key_comp())
+ tree(BOOST_RV_REF(tree) x)
+ : AllocHolder(::boost::move(static_cast<AllocHolder&>(x)), x.value_comp())
{}
- rbtree(const rbtree& x, const allocator_type &a)
- : AllocHolder(a, x.key_comp())
+ tree(const tree& x, const allocator_type &a)
+ : AllocHolder(a, x.value_comp())
{
this->icont().clone_from
(x.icont(), typename AllocHolder::cloner(*this), Destroyer(this->node_alloc()));
}
- rbtree(BOOST_RV_REF(rbtree) x, const allocator_type &a)
- : AllocHolder(a, x.key_comp())
+ tree(BOOST_RV_REF(tree) x, const allocator_type &a)
+ : AllocHolder(a, x.value_comp())
{
if(this->node_alloc() == x.node_alloc()){
this->icont().swap(x.icont());
@@ -523,10 +658,10 @@ class rbtree
}
}
- ~rbtree()
+ ~tree()
{} //AllocHolder clears the tree
- rbtree& operator=(BOOST_COPY_ASSIGN_REF(rbtree) x)
+ tree& operator=(BOOST_COPY_ASSIGN_REF(tree) x)
{
if (&x != this){
NodeAlloc &this_alloc = this->get_stored_allocator();
@@ -545,7 +680,7 @@ class rbtree
//Now recreate the source tree reusing nodes stored by other_tree
this->icont().clone_from
(x.icont()
- , RecyclingCloner(*this, other_tree)
+ , RecyclingCloner<AllocHolder, false>(*this, other_tree)
, Destroyer(this->node_alloc()));
//If there are remaining nodes, destroy them
@@ -557,43 +692,47 @@ class rbtree
return *this;
}
- rbtree& operator=(BOOST_RV_REF(rbtree) x)
+ tree& operator=(BOOST_RV_REF(tree) x)
{
- if (&x != this){
- NodeAlloc &this_alloc = this->node_alloc();
- NodeAlloc &x_alloc = x.node_alloc();
- //If allocators are equal we can just swap pointers
- if(this_alloc == x_alloc){
- //Destroy and swap pointers
- this->clear();
- this->icont() = ::boost::move(x.icont());
- //Move allocator if needed
- this->AllocHolder::move_assign_alloc(x);
- }
- //If unequal allocators, then do a one by one move
- else{
- //Transfer all the nodes to a temporary tree
- //If anything goes wrong, all the nodes will be destroyed
- //automatically
- Icont other_tree(::boost::move(this->icont()));
-
- //Now recreate the source tree reusing nodes stored by other_tree
- this->icont().clone_from
- (x.icont()
- , RecyclingMoveCloner(*this, other_tree)
- , Destroyer(this->node_alloc()));
-
- //If there are remaining nodes, destroy them
- NodePtr p;
- while((p = other_tree.unlink_leftmost_without_rebalance())){
- AllocHolder::destroy_node(p);
- }
+ BOOST_ASSERT(this != &x);
+ NodeAlloc &this_alloc = this->node_alloc();
+ NodeAlloc &x_alloc = x.node_alloc();
+ const bool propagate_alloc = allocator_traits<NodeAlloc>::
+ propagate_on_container_move_assignment::value;
+ const bool allocators_equal = this_alloc == x_alloc; (void)allocators_equal;
+ //Resources can be transferred if both allocators are
+ //going to be equal after this function (either propagated or already equal)
+ if(propagate_alloc || allocators_equal){
+ //Destroy
+ this->clear();
+ //Move allocator if needed
+ this->AllocHolder::move_assign_alloc(x);
+ //Obtain resources
+ this->icont() = boost::move(x.icont());
+ }
+ //Else do a one by one move
+ else{
+ //Transfer all the nodes to a temporary tree
+ //If anything goes wrong, all the nodes will be destroyed
+ //automatically
+ Icont other_tree(::boost::move(this->icont()));
+
+ //Now recreate the source tree reusing nodes stored by other_tree
+ this->icont().clone_from
+ (x.icont()
+ , RecyclingCloner<AllocHolder, true>(*this, other_tree)
+ , Destroyer(this->node_alloc()));
+
+ //If there are remaining nodes, destroy them
+ NodePtr p;
+ while((p = other_tree.unlink_leftmost_without_rebalance())){
+ AllocHolder::destroy_node(p);
}
}
return *this;
}
- public:
+ public:
// accessors:
value_compare value_comp() const
{ return this->icont().value_comp().value_comp(); }
@@ -704,8 +843,10 @@ class rbtree
iterator insert_unique_commit(const value_type& v, insert_commit_data &data)
{
NodePtr tmp = AllocHolder::create_node(v);
- iiterator it(this->icont().insert_unique_commit(*tmp, data));
- return iterator(it);
+ scoped_destroy_deallocator<NodeAlloc> destroy_deallocator(tmp, this->node_alloc());
+ iterator ret(this->icont().insert_unique_commit(*tmp, data));
+ destroy_deallocator.release();
+ return ret;
}
template<class MovableConvertible>
@@ -713,8 +854,10 @@ class rbtree
(BOOST_FWD_REF(MovableConvertible) mv, insert_commit_data &data)
{
NodePtr tmp = AllocHolder::create_node(boost::forward<MovableConvertible>(mv));
- iiterator it(this->icont().insert_unique_commit(*tmp, data));
- return iterator(it);
+ scoped_destroy_deallocator<NodeAlloc> destroy_deallocator(tmp, this->node_alloc());
+ iterator ret(this->icont().insert_unique_commit(*tmp, data));
+ destroy_deallocator.release();
+ return ret;
}
std::pair<iterator,bool> insert_unique(const value_type& v)
@@ -722,10 +865,10 @@ class rbtree
insert_commit_data data;
std::pair<iterator,bool> ret =
this->insert_unique_check(KeyOfValue()(v), data);
- if(!ret.second)
- return ret;
- return std::pair<iterator,bool>
- (this->insert_unique_commit(v, data), true);
+ if(ret.second){
+ ret.first = this->insert_unique_commit(v, data);
+ }
+ return ret;
}
template<class MovableConvertible>
@@ -734,13 +877,22 @@ class rbtree
insert_commit_data data;
std::pair<iterator,bool> ret =
this->insert_unique_check(KeyOfValue()(mv), data);
- if(!ret.second)
- return ret;
- return std::pair<iterator,bool>
- (this->insert_unique_commit(boost::forward<MovableConvertible>(mv), data), true);
+ if(ret.second){
+ ret.first = this->insert_unique_commit(boost::forward<MovableConvertible>(mv), data);
+ }
+ return ret;
}
private:
+
+ template<class MovableConvertible>
+ void push_back_impl(BOOST_FWD_REF(MovableConvertible) mv)
+ {
+ NodePtr tmp(AllocHolder::create_node(boost::forward<MovableConvertible>(mv)));
+ //push_back has no-throw guarantee so avoid any deallocator/destroyer
+ this->icont().push_back(*tmp);
+ }
+
std::pair<iterator, bool> emplace_unique_impl(NodePtr p)
{
value_type &v = p->get_data();
@@ -786,15 +938,21 @@ class rbtree
template <class... Args>
iterator emplace_equal(Args&&... args)
{
- NodePtr p(AllocHolder::create_node(boost::forward<Args>(args)...));
- return iterator(this->icont().insert_equal(this->icont().end(), *p));
+ NodePtr tmp(AllocHolder::create_node(boost::forward<Args>(args)...));
+ scoped_destroy_deallocator<NodeAlloc> destroy_deallocator(tmp, this->node_alloc());
+ iterator ret(this->icont().insert_equal(this->icont().end(), *tmp));
+ destroy_deallocator.release();
+ return ret;
}
template <class... Args>
iterator emplace_hint_equal(const_iterator hint, Args&&... args)
{
- NodePtr p(AllocHolder::create_node(boost::forward<Args>(args)...));
- return iterator(this->icont().insert_equal(hint.get(), *p));
+ NodePtr tmp(AllocHolder::create_node(boost::forward<Args>(args)...));
+ scoped_destroy_deallocator<NodeAlloc> destroy_deallocator(tmp, this->node_alloc());
+ iterator ret(this->icont().insert_equal(hint.get(), *tmp));
+ destroy_deallocator.release();
+ return ret;
}
#else //#ifdef BOOST_CONTAINER_PERFECT_FORWARDING
@@ -818,16 +976,22 @@ class rbtree
BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, >) \
iterator emplace_equal(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \
{ \
- NodePtr p(AllocHolder::create_node(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _))); \
- return iterator(this->icont().insert_equal(this->icont().end(), *p)); \
+ NodePtr tmp(AllocHolder::create_node(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _))); \
+ scoped_destroy_deallocator<NodeAlloc> destroy_deallocator(tmp, this->node_alloc()); \
+ iterator ret(this->icont().insert_equal(this->icont().end(), *tmp)); \
+ destroy_deallocator.release(); \
+ return ret; \
} \
\
BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, >) \
iterator emplace_hint_equal(const_iterator hint \
BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \
{ \
- NodePtr p(AllocHolder::create_node(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _))); \
- return iterator(this->icont().insert_equal(hint.get(), *p)); \
+ NodePtr tmp(AllocHolder::create_node(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _))); \
+ scoped_destroy_deallocator<NodeAlloc> destroy_deallocator(tmp, this->node_alloc()); \
+ iterator ret(this->icont().insert_equal(hint.get(), *tmp)); \
+ destroy_deallocator.release(); \
+ return ret; \
} \
//!
#define BOOST_PP_LOCAL_LIMITS (0, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS)
@@ -859,53 +1023,53 @@ class rbtree
template <class InputIterator>
void insert_unique(InputIterator first, InputIterator last)
{
- if(this->empty()){
- //Insert with end hint, to achieve linear
- //complexity if [first, last) is ordered
- const_iterator hint(this->cend());
- for( ; first != last; ++first)
- hint = this->insert_unique(hint, *first);
- }
- else{
- for( ; first != last; ++first)
- this->insert_unique(*first);
- }
+ for( ; first != last; ++first)
+ this->insert_unique(*first);
}
iterator insert_equal(const value_type& v)
{
- NodePtr p(AllocHolder::create_node(v));
- return iterator(this->icont().insert_equal(this->icont().end(), *p));
+ NodePtr tmp(AllocHolder::create_node(v));
+ scoped_destroy_deallocator<NodeAlloc> destroy_deallocator(tmp, this->node_alloc());
+ iterator ret(this->icont().insert_equal(this->icont().end(), *tmp));
+ destroy_deallocator.release();
+ return ret;
}
template<class MovableConvertible>
iterator insert_equal(BOOST_FWD_REF(MovableConvertible) mv)
{
- NodePtr p(AllocHolder::create_node(boost::forward<MovableConvertible>(mv)));
- return iterator(this->icont().insert_equal(this->icont().end(), *p));
+ NodePtr tmp(AllocHolder::create_node(boost::forward<MovableConvertible>(mv)));
+ scoped_destroy_deallocator<NodeAlloc> destroy_deallocator(tmp, this->node_alloc());
+ iterator ret(this->icont().insert_equal(this->icont().end(), *tmp));
+ destroy_deallocator.release();
+ return ret;
}
iterator insert_equal(const_iterator hint, const value_type& v)
{
- NodePtr p(AllocHolder::create_node(v));
- return iterator(this->icont().insert_equal(hint.get(), *p));
+ NodePtr tmp(AllocHolder::create_node(v));
+ scoped_destroy_deallocator<NodeAlloc> destroy_deallocator(tmp, this->node_alloc());
+ iterator ret(this->icont().insert_equal(hint.get(), *tmp));
+ destroy_deallocator.release();
+ return ret;
}
template<class MovableConvertible>
iterator insert_equal(const_iterator hint, BOOST_FWD_REF(MovableConvertible) mv)
{
- NodePtr p(AllocHolder::create_node(boost::forward<MovableConvertible>(mv)));
- return iterator(this->icont().insert_equal(hint.get(), *p));
+ NodePtr tmp(AllocHolder::create_node(boost::forward<MovableConvertible>(mv)));
+ scoped_destroy_deallocator<NodeAlloc> destroy_deallocator(tmp, this->node_alloc());
+ iterator ret(this->icont().insert_equal(hint.get(), *tmp));
+ destroy_deallocator.release();
+ return ret;
}
template <class InputIterator>
void insert_equal(InputIterator first, InputIterator last)
{
- //Insert with end hint, to achieve linear
- //complexity if [first, last) is ordered
- const_iterator hint(this->cend());
for( ; first != last; ++first)
- hint = this->insert_equal(hint, *first);
+ this->insert_equal(*first);
}
iterator erase(const_iterator position)
@@ -920,7 +1084,8 @@ class rbtree
void clear()
{ AllocHolder::clear(alloc_version()); }
- // set operations:
+ // search operations. Const and non-const overloads even if no iterator is returned
+ // so splay implementations can to their rebalancing when searching in non-const versions
iterator find(const key_type& k)
{ return iterator(this->icont().find(k, KeyNodeCompare(value_comp()))); }
@@ -943,187 +1108,60 @@ class rbtree
{ return const_iterator(this->non_const_icont().upper_bound(k, KeyNodeCompare(value_comp()))); }
std::pair<iterator,iterator> equal_range(const key_type& k)
- {
+ {
std::pair<iiterator, iiterator> ret =
this->icont().equal_range(k, KeyNodeCompare(value_comp()));
return std::pair<iterator,iterator>(iterator(ret.first), iterator(ret.second));
}
std::pair<const_iterator, const_iterator> equal_range(const key_type& k) const
- {
+ {
std::pair<iiterator, iiterator> ret =
this->non_const_icont().equal_range(k, KeyNodeCompare(value_comp()));
return std::pair<const_iterator,const_iterator>
(const_iterator(ret.first), const_iterator(ret.second));
}
- private:
- //Iterator range version
- template<class InpIterator>
- void priv_create_and_insert_nodes
- (InpIterator beg, InpIterator end, bool unique, allocator_v1, std::input_iterator_tag)
+ std::pair<iterator,iterator> lower_bound_range(const key_type& k)
{
- if(unique){
- for (; beg != end; ++beg){
- this->insert_unique(*beg);
- }
- }
- else{
- for (; beg != end; ++beg){
- this->insert_equal(*beg);
- }
- }
- }
-
- template<class InpIterator>
- void priv_create_and_insert_nodes
- (InpIterator beg, InpIterator end, bool unique, allocator_v2, std::input_iterator_tag)
- { //Just forward to the default one
- priv_create_and_insert_nodes(beg, end, unique, allocator_v1(), std::input_iterator_tag());
+ std::pair<iiterator, iiterator> ret =
+ this->icont().lower_bound_range(k, KeyNodeCompare(value_comp()));
+ return std::pair<iterator,iterator>(iterator(ret.first), iterator(ret.second));
}
- class insertion_functor;
- friend class insertion_functor;
-
- class insertion_functor
- {
- Icont &icont_;
-
- public:
- insertion_functor(Icont &icont)
- : icont_(icont)
- {}
-
- void operator()(Node &n)
- { this->icont_.insert_equal(this->icont_.cend(), n); }
- };
-
-
- template<class FwdIterator>
- void priv_create_and_insert_nodes
- (FwdIterator beg, FwdIterator end, bool unique, allocator_v2, std::forward_iterator_tag)
+ std::pair<const_iterator, const_iterator> lower_bound_range(const key_type& k) const
{
- if(beg != end){
- if(unique){
- priv_create_and_insert_nodes(beg, end, unique, allocator_v2(), std::input_iterator_tag());
- }
- else{
- //Optimized allocation and construction
- this->allocate_many_and_construct
- (beg, std::distance(beg, end), insertion_functor(this->icont()));
- }
- }
+ std::pair<iiterator, iiterator> ret =
+ this->non_const_icont().lower_bound_range(k, KeyNodeCompare(value_comp()));
+ return std::pair<const_iterator,const_iterator>
+ (const_iterator(ret.first), const_iterator(ret.second));
}
- //Iterator range version
- template<class InpIterator>
- void priv_create_and_insert_ordered_nodes
- (InpIterator beg, InpIterator end, allocator_v1, std::input_iterator_tag)
- {
- const_iterator cend_n(this->cend());
- for (; beg != end; ++beg){
- this->insert_before(cend_n, *beg);
- }
- }
+ void rebalance()
+ { intrusive_tree_proxy_t::rebalance(this->icont()); }
- template<class InpIterator>
- void priv_create_and_insert_ordered_nodes
- (InpIterator beg, InpIterator end, allocator_v2, std::input_iterator_tag)
- { //Just forward to the default one
- priv_create_and_insert_ordered_nodes(beg, end, allocator_v1(), std::input_iterator_tag());
- }
+ friend bool operator==(const tree& x, const tree& y)
+ { return x.size() == y.size() && std::equal(x.begin(), x.end(), y.begin()); }
- class back_insertion_functor;
- friend class back_insertion_functor;
+ friend bool operator<(const tree& x, const tree& y)
+ { return std::lexicographical_compare(x.begin(), x.end(), y.begin(), y.end()); }
- class back_insertion_functor
- {
- Icont &icont_;
+ friend bool operator!=(const tree& x, const tree& y)
+ { return !(x == y); }
- public:
- back_insertion_functor(Icont &icont)
- : icont_(icont)
- {}
+ friend bool operator>(const tree& x, const tree& y)
+ { return y < x; }
- void operator()(Node &n)
- { this->icont_.push_back(n); }
- };
+ friend bool operator<=(const tree& x, const tree& y)
+ { return !(y < x); }
+ friend bool operator>=(const tree& x, const tree& y)
+ { return !(x < y); }
- template<class FwdIterator>
- void priv_create_and_insert_ordered_nodes
- (FwdIterator beg, FwdIterator end, allocator_v2, std::forward_iterator_tag)
- {
- if(beg != end){
- //Optimized allocation and construction
- this->allocate_many_and_construct
- (beg, std::distance(beg, end), back_insertion_functor(this->icont()));
- }
- }
+ friend void swap(tree& x, tree& y)
+ { x.swap(y); }
};
-template <class Key, class Value, class KeyOfValue,
- class KeyCompare, class A>
-inline bool
-operator==(const rbtree<Key,Value,KeyOfValue,KeyCompare,A>& x,
- const rbtree<Key,Value,KeyOfValue,KeyCompare,A>& y)
-{
- return x.size() == y.size() &&
- std::equal(x.begin(), x.end(), y.begin());
-}
-
-template <class Key, class Value, class KeyOfValue,
- class KeyCompare, class A>
-inline bool
-operator<(const rbtree<Key,Value,KeyOfValue,KeyCompare,A>& x,
- const rbtree<Key,Value,KeyOfValue,KeyCompare,A>& y)
-{
- return std::lexicographical_compare(x.begin(), x.end(),
- y.begin(), y.end());
-}
-
-template <class Key, class Value, class KeyOfValue,
- class KeyCompare, class A>
-inline bool
-operator!=(const rbtree<Key,Value,KeyOfValue,KeyCompare,A>& x,
- const rbtree<Key,Value,KeyOfValue,KeyCompare,A>& y) {
- return !(x == y);
-}
-
-template <class Key, class Value, class KeyOfValue,
- class KeyCompare, class A>
-inline bool
-operator>(const rbtree<Key,Value,KeyOfValue,KeyCompare,A>& x,
- const rbtree<Key,Value,KeyOfValue,KeyCompare,A>& y) {
- return y < x;
-}
-
-template <class Key, class Value, class KeyOfValue,
- class KeyCompare, class A>
-inline bool
-operator<=(const rbtree<Key,Value,KeyOfValue,KeyCompare,A>& x,
- const rbtree<Key,Value,KeyOfValue,KeyCompare,A>& y) {
- return !(y < x);
-}
-
-template <class Key, class Value, class KeyOfValue,
- class KeyCompare, class A>
-inline bool
-operator>=(const rbtree<Key,Value,KeyOfValue,KeyCompare,A>& x,
- const rbtree<Key,Value,KeyOfValue,KeyCompare,A>& y) {
- return !(x < y);
-}
-
-
-template <class Key, class Value, class KeyOfValue,
- class KeyCompare, class A>
-inline void
-swap(rbtree<Key,Value,KeyOfValue,KeyCompare,A>& x,
- rbtree<Key,Value,KeyOfValue,KeyCompare,A>& y)
-{
- x.swap(y);
-}
-
} //namespace container_detail {
} //namespace container {
/*
@@ -1132,9 +1170,9 @@ swap(rbtree<Key,Value,KeyOfValue,KeyCompare,A>& x,
template <class K, class V, class KOV,
class C, class A>
struct has_trivial_destructor_after_move
- <boost::container::container_detail::rbtree<K, V, KOV, C, A> >
+ <boost::container::container_detail::tree<K, V, KOV, C, A> >
{
- static const bool value = has_trivial_destructor<A>::value && has_trivial_destructor<C>::value;
+ static const bool value = has_trivial_destructor_after_move<A>::value && has_trivial_destructor_after_move<C>::value;
};
*/
} //namespace boost {
diff --git a/boost/container/detail/type_traits.hpp b/boost/container/detail/type_traits.hpp
index 0e096e54e3..9ff361454a 100644
--- a/boost/container/detail/type_traits.hpp
+++ b/boost/container/detail/type_traits.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
// (C) Copyright John Maddock 2000.
-// (C) Copyright Ion Gaztanaga 2005-2012.
+// (C) Copyright Ion Gaztanaga 2005-2013.
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
@@ -15,13 +15,12 @@
#ifndef BOOST_CONTAINER_CONTAINER_DETAIL_TYPE_TRAITS_HPP
#define BOOST_CONTAINER_CONTAINER_DETAIL_TYPE_TRAITS_HPP
-#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#if defined(_MSC_VER)
# pragma once
#endif
-#include "config_begin.hpp"
-
-#include <boost/move/move.hpp>
+#include <boost/container/detail/config_begin.hpp>
+#include <boost/container/detail/workaround.hpp>
namespace boost {
namespace container {
@@ -90,7 +89,7 @@ struct remove_reference<T&>
typedef T type;
};
-#ifndef BOOST_NO_RVALUE_REFERENCES
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
template<class T>
struct remove_reference<T&&>
@@ -100,6 +99,15 @@ struct remove_reference<T&&>
#else
+} // namespace container_detail {
+} //namespace container {
+
+template<class T>
+class rv;
+
+namespace container {
+namespace container_detail {
+
template<class T>
struct remove_reference< ::boost::rv<T> >
{
@@ -164,6 +172,10 @@ template <class T>
struct add_const_reference<T&>
{ typedef T& type; };
+template <class T>
+struct add_const
+{ typedef const T type; };
+
template <typename T, typename U>
struct is_same
{
@@ -201,6 +213,21 @@ struct remove_ref_const
typedef typename remove_const< typename remove_reference<T>::type >::type type;
};
+template <class T>
+struct make_unsigned
+{
+ typedef T type;
+};
+
+template <> struct make_unsigned<bool> {};
+template <> struct make_unsigned<signed char> {typedef unsigned char type;};
+template <> struct make_unsigned<signed short> {typedef unsigned short type;};
+template <> struct make_unsigned<signed int> {typedef unsigned int type;};
+template <> struct make_unsigned<signed long> {typedef unsigned long type;};
+#ifdef BOOST_HAS_LONG_LONG
+template <> struct make_unsigned<signed long long> {typedef unsigned long long type;};
+#endif
+
} // namespace container_detail
} //namespace container {
} //namespace boost {
diff --git a/boost/container/detail/utilities.hpp b/boost/container/detail/utilities.hpp
index 152b5e162e..25f035df50 100644
--- a/boost/container/detail/utilities.hpp
+++ b/boost/container/detail/utilities.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
+// (C) Copyright Ion Gaztanaga 2005-2013. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
@@ -11,29 +11,101 @@
#ifndef BOOST_CONTAINER_DETAIL_UTILITIES_HPP
#define BOOST_CONTAINER_DETAIL_UTILITIES_HPP
-#include "config_begin.hpp"
+#if defined(_MSC_VER)
+# pragma once
+#endif
+
+#include <boost/container/detail/config_begin.hpp>
+#include <boost/container/detail/workaround.hpp>
+
#include <cstdio>
-#include <boost/type_traits/is_fundamental.hpp>
+#include <cstring> //for ::memmove / ::memcpy
#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/move/move.hpp>
+#include <boost/type_traits/is_integral.hpp>
+#include <boost/type_traits/is_floating_point.hpp>
+#include <boost/type_traits/is_copy_constructible.hpp>
+#include <boost/type_traits/has_trivial_destructor.hpp>
+#include <boost/type_traits/has_trivial_copy.hpp>
+#include <boost/type_traits/has_trivial_assign.hpp>
+#include <boost/type_traits/is_pod.hpp>
+#include <boost/move/core.hpp>
+#include <boost/move/utility_core.hpp>
+#include <boost/move/iterator.hpp>
+#include <boost/assert.hpp>
+#include <boost/container/throw_exception.hpp>
#include <boost/container/detail/mpl.hpp>
#include <boost/container/detail/type_traits.hpp>
#include <boost/container/allocator_traits.hpp>
-#include <algorithm>
+#include <boost/core/no_exceptions_support.hpp>
+#include <boost/container/detail/memory_util.hpp>
+#include <boost/intrusive/pointer_traits.hpp>
+#include <boost/aligned_storage.hpp>
+#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>
inline T* addressof(T& obj)
{
return static_cast<T*>(
- static_cast<void*>(
- const_cast<char*>(
+ static_cast<void*>(
+ const_cast<char*>(
&reinterpret_cast<const char&>(obj)
)));
}
@@ -46,42 +118,73 @@ template<class T>
const T &min_value(const T &a, const T &b)
{ return a < b ? a : b; }
-template <class SizeType>
-SizeType
- get_next_capacity(const SizeType max_size
- ,const SizeType capacity
- ,const SizeType n)
+enum NextCapacityOption { NextCapacityDouble, NextCapacity60Percent };
+
+template<class SizeType, NextCapacityOption Option>
+struct next_capacity_calculator;
+
+template<class SizeType>
+struct next_capacity_calculator<SizeType, NextCapacityDouble>
{
-// if (n > max_size - capacity)
-// throw std::length_error("get_next_capacity");
+ static SizeType get(const SizeType max_size
+ ,const SizeType capacity
+ ,const SizeType n)
+ {
+ const SizeType remaining = max_size - capacity;
+ if ( remaining < n )
+ boost::container::throw_length_error("get_next_capacity, allocator's max_size reached");
+ const SizeType additional = max_value(n, capacity);
+ return ( remaining < additional ) ? max_size : ( capacity + additional );
+ }
+};
- const SizeType m3 = max_size/3;
- if (capacity < m3)
- return capacity + max_value(3*(capacity+1)/5, n);
+template<class SizeType>
+struct next_capacity_calculator<SizeType, NextCapacity60Percent>
+{
+ static SizeType get(const SizeType max_size
+ ,const SizeType capacity
+ ,const SizeType n)
+ {
+ const SizeType remaining = max_size - capacity;
+ if ( remaining < n )
+ boost::container::throw_length_error("get_next_capacity, allocator's max_size reached");
+ const SizeType m3 = max_size/3;
- if (capacity < m3*2)
- return capacity + max_value((capacity+1)/2, n);
+ if (capacity < m3)
+ return capacity + max_value(3*(capacity+1)/5, n);
- return max_size;
-}
+ if (capacity < m3*2)
+ return capacity + max_value((capacity+1)/2, n);
+ return max_size;
+ }
+};
template <class T>
inline T* to_raw_pointer(T* p)
{ return p; }
template <class Pointer>
-inline typename Pointer::element_type*
+inline typename boost::intrusive::pointer_traits<Pointer>::element_type*
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);
-}
+inline T* iterator_to_pointer(T* i)
+{ return i; }
+
+template <class Iterator>
+inline typename std::iterator_traits<Iterator>::pointer
+ iterator_to_pointer(const Iterator &i)
+{ return i.operator->(); }
+
+template <class Iterator>
+inline
+ typename boost::intrusive::pointer_traits
+ <typename std::iterator_traits<Iterator>::pointer>::element_type*
+ iterator_to_raw_pointer(const Iterator &i)
+{ return (to_raw_pointer)((iterator_to_pointer)(i)); }
+
template<class AllocatorType>
inline void swap_alloc(AllocatorType &, AllocatorType &, container_detail::false_type)
@@ -90,7 +193,7 @@ inline void swap_alloc(AllocatorType &, AllocatorType &, container_detail::false
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)
@@ -122,101 +225,340 @@ struct ct_rounded_size
{
enum { value = ((OrigSize-1)/RoundTo+1)*RoundTo };
};
-/*
-template <class _TypeT>
-struct __rw_is_enum
+
+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> >
{
- struct _C_no { };
- struct _C_yes { int _C_dummy [2]; };
+ static const bool value = true;
+};
- struct _C_indirect {
- // prevent classes with user-defined conversions from matching
+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
- // use double to prevent float->int gcc conversion warnings
- _C_indirect (double);
+/////////////////////////
+// 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;
};
-// nested struct gets rid of bogus gcc errors
-struct _C_nest {
- // supply first argument to prevent HP aCC warnings
- static _C_no _C_is (int, ...);
- static _C_yes _C_is (int, _C_indirect);
+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;
+};
- static _TypeT _C_make_T ();
+template <typename I, typename O>
+struct is_memtransfer_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;
};
-enum {
- _C_val = sizeof (_C_yes) == sizeof (_C_nest::_C_is (0, _C_nest::_C_make_T ()))
- && !::boost::is_fundamental<_TypeT>::value
+template <typename I, typename O>
+struct is_memtransfer_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_memtransfer_copy_constructible
+ : public enable_if_c<container_detail::is_memtransfer_copy_constructible<I, O>::value, R>
+{};
+
+template <typename I, typename O, typename R>
+struct disable_if_memtransfer_copy_constructible
+ : public enable_if_c<!container_detail::is_memtransfer_copy_constructible<I, O>::value, R>
+{};
+
+template <typename I, typename O, typename R>
+struct enable_if_memtransfer_copy_assignable
+ : public enable_if_c<container_detail::is_memtransfer_copy_assignable<I, O>::value, R>
+{};
+
+template <typename I, typename O, typename R>
+struct disable_if_memtransfer_copy_assignable
+ : public enable_if_c<!container_detail::is_memtransfer_copy_assignable<I, O>::value, R>
+{};
+
+template
+ <typename I, // I models InputIterator
+ typename F> // F models ForwardIterator
+inline F memmove(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);
+ ::memmove((iterator_to_raw_pointer)(r), (iterator_to_raw_pointer)(f), sizeof(value_type)*n);
+ std::advance(r, n);
+ return r;
+}
+
+template
+ <typename I, // I models InputIterator
+ typename F> // F models ForwardIterator
+F memmove_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;
+ ::memmove((iterator_to_raw_pointer)(r), (iterator_to_raw_pointer)(f), sizeof(value_type)*n);
+ std::advance(r, n);
+ return r;
+}
+
+template
+ <typename I, // I models InputIterator
+ typename F> // F models ForwardIterator
+I memmove_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;
+ ::memmove((iterator_to_raw_pointer)(r), (iterator_to_raw_pointer)(f), sizeof(value_type)*n);
+ std::advance(f, n);
+ return f;
+}
+
+template
+ <typename I, // I models InputIterator
+ typename F> // F models ForwardIterator
+I memmove_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;
+ ::memmove((iterator_to_raw_pointer)(r), (iterator_to_raw_pointer)(f), sizeof(value_type)*n);
+ std::advance(f, n);
+ std::advance(r, n);
+ return f;
+}
+
+template <typename O>
+struct is_memzero_initializable
+{
+ typedef typename ::std::iterator_traits<O>::value_type value_type;
+ static const bool value = are_elements_contiguous<O>::value &&
+ ( ::boost::is_integral<value_type>::value || ::boost::is_enum<value_type>::value
+ #if defined(BOOST_CONTAINER_MEMZEROED_POINTER_IS_NULL)
+ || ::boost::is_pointer<value_type>::value
+ #endif
+ #if defined(BOOST_CONTAINER_MEMZEROED_FLOATING_POINT_IS_ZERO)
+ || ::boost::is_floating_point<value_type>::value
+ #endif
+ #if defined(BOOST_CONTAINER_MEMZEROED_FLOATING_POINT_IS_ZERO) && defined(BOOST_CONTAINER_MEMZEROED_POINTER_IS_NULL)
+ || ::boost::is_pod<value_type>::value
+ #endif
+ );
};
-*/
-template<class T>
-struct move_const_ref_type
- : if_c
-// < ::boost::is_fundamental<T>::value || ::boost::is_pointer<T>::value || ::boost::is_member_pointer<T>::value || ::boost::is_enum<T>::value
- < !::boost::is_class<T>::value
- ,const T &
- ,BOOST_CATCH_CONST_RLVALUE(T)
- >
+template <typename O, typename R>
+struct enable_if_memzero_initializable
+ : public enable_if_c<container_detail::is_memzero_initializable<O>::value, R>
+{};
+
+template <typename O, typename R>
+struct disable_if_memzero_initializable
+ : public enable_if_c<!container_detail::is_memzero_initializable<O>::value, R>
{};
} //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_memtransfer_copy_constructible<I, F, F>::type
+ uninitialized_move_alloc(A &a, I f, I l, F r)
{
- while (f != l) {
- allocator_traits<A>::construct(a, container_detail::to_raw_pointer(&*r), boost::move(*f));
- ++f; ++r;
+ F back = r;
+ BOOST_TRY{
+ while (f != l) {
+ allocator_traits<A>::construct(a, container_detail::iterator_to_raw_pointer(r), boost::move(*f));
+ ++f; ++r;
+ }
}
+ BOOST_CATCH(...){
+ for (; back != r; ++back){
+ allocator_traits<A>::destroy(a, container_detail::iterator_to_raw_pointer(back));
+ }
+ BOOST_RETHROW;
+ }
+ BOOST_CATCH_END
return r;
}
+template
+ <typename A,
+ typename I, // I models InputIterator
+ typename F> // F models ForwardIterator
+inline typename container_detail::enable_if_memtransfer_copy_constructible<I, F, F>::type
+ uninitialized_move_alloc(A &, I f, I l, F r) BOOST_CONTAINER_NOEXCEPT
+{ return container_detail::memmove(f, l, r); }
+
//////////////////////////////////////////////////////////////////////////////
//
-// uninitialized_copy_alloc
+// uninitialized_move_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, 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_copy_alloc(A &a, I f, I l, F r)
+inline typename container_detail::disable_if_memtransfer_copy_constructible<I, F, F>::type
+ uninitialized_move_alloc_n(A &a, I f, typename std::iterator_traits<I>::difference_type n, F r)
{
- while (f != l) {
- allocator_traits<A>::construct(a, container_detail::to_raw_pointer(&*r), *f);
- ++f; ++r;
+ F back = r;
+ BOOST_TRY{
+ while (n--) {
+ allocator_traits<A>::construct(a, container_detail::iterator_to_raw_pointer(r), boost::move(*f));
+ ++f; ++r;
+ }
}
+ BOOST_CATCH(...){
+ for (; back != r; ++back){
+ allocator_traits<A>::destroy(a, container_detail::iterator_to_raw_pointer(back));
+ }
+ BOOST_RETHROW;
+ }
+ BOOST_CATCH_END
return r;
}
+template
+ <typename A,
+ typename I, // I models InputIterator
+ typename F> // F models ForwardIterator
+inline typename container_detail::enable_if_memtransfer_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::memmove_n(f, n, r); }
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// uninitialized_move_alloc_n_source
+//
+//////////////////////////////////////////////////////////////////////////////
+
+//! <b>Effects</b>:
+//! \code
+//! for (; n--; ++r, ++f)
+//! allocator_traits::construct(a, &*r, boost::move(*f));
+//! \endcode
+//!
+//! <b>Returns</b>: f (after incremented)
+template
+ <typename A,
+ typename I, // I models InputIterator
+ typename F> // F models ForwardIterator
+inline typename container_detail::disable_if_memtransfer_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{
+ while (n--) {
+ allocator_traits<A>::construct(a, container_detail::iterator_to_raw_pointer(r), boost::move(*f));
+ ++f; ++r;
+ }
+ }
+ BOOST_CATCH(...){
+ for (; back != r; ++back){
+ allocator_traits<A>::destroy(a, container_detail::iterator_to_raw_pointer(back));
+ }
+ BOOST_RETHROW;
+ }
+ BOOST_CATCH_END
+ return f;
+}
+
+template
+ <typename A,
+ typename I, // I models InputIterator
+ typename F> // F models ForwardIterator
+inline typename container_detail::enable_if_memtransfer_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::memmove_n_source(f, n, r); }
+
//////////////////////////////////////////////////////////////////////////////
//
// uninitialized_copy_alloc
@@ -225,58 +567,701 @@ F uninitialized_copy_alloc(A &a, I f, I l, F r)
//! <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>: r
+template
+ <typename A,
+ typename I, // I models InputIterator
+ typename F> // F models ForwardIterator
+inline typename container_detail::disable_if_memtransfer_copy_constructible<I, F, F>::type
+ uninitialized_copy_alloc(A &a, I f, I l, F r)
+{
+ F back = r;
+ BOOST_TRY{
+ while (f != l) {
+ allocator_traits<A>::construct(a, container_detail::iterator_to_raw_pointer(r), *f);
+ ++f; ++r;
+ }
+ }
+ BOOST_CATCH(...){
+ for (; back != r; ++back){
+ allocator_traits<A>::destroy(a, container_detail::iterator_to_raw_pointer(back));
+ }
+ BOOST_RETHROW;
+ }
+ BOOST_CATCH_END
+ return r;
+}
+
+template
+ <typename A,
+ typename I, // I models InputIterator
+ typename F> // F models ForwardIterator
+inline typename container_detail::enable_if_memtransfer_copy_constructible<I, F, F>::type
+ uninitialized_copy_alloc(A &, I f, I l, F r) BOOST_CONTAINER_NOEXCEPT
+{ return container_detail::memmove(f, l, r); }
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// uninitialized_copy_alloc_n
+//
+//////////////////////////////////////////////////////////////////////////////
+
+//! <b>Effects</b>:
+//! \code
+//! 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
+inline typename container_detail::disable_if_memtransfer_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{
+ while (n--) {
+ allocator_traits<A>::construct(a, container_detail::iterator_to_raw_pointer(r), *f);
+ ++f; ++r;
+ }
+ }
+ BOOST_CATCH(...){
+ for (; back != r; ++back){
+ allocator_traits<A>::destroy(a, container_detail::iterator_to_raw_pointer(back));
+ }
+ BOOST_RETHROW;
+ }
+ BOOST_CATCH_END
+ return r;
+}
+
+template
+ <typename A,
+ typename I, // I models InputIterator
+ typename F> // F models ForwardIterator
+inline typename container_detail::enable_if_memtransfer_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::memmove_n(f, n, r); }
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// uninitialized_copy_alloc_n_source
+//
+//////////////////////////////////////////////////////////////////////////////
+
+//! <b>Effects</b>:
+//! \code
+//! for (; n--; ++r, ++f)
+//! allocator_traits::construct(a, &*r, *f);
+//! \endcode
+//!
+//! <b>Returns</b>: f (after incremented)
+template
+ <typename A,
+ typename I, // I models InputIterator
+ typename F> // F models ForwardIterator
+inline typename container_detail::disable_if_memtransfer_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{
+ while (n--) {
+ allocator_traits<A>::construct(a, container_detail::iterator_to_raw_pointer(r), *f);
+ ++f; ++r;
+ }
+ }
+ BOOST_CATCH(...){
+ for (; back != r; ++back){
+ allocator_traits<A>::destroy(a, container_detail::iterator_to_raw_pointer(back));
+ }
+ BOOST_RETHROW;
+ }
+ BOOST_CATCH_END
+ return f;
+}
+
+template
+ <typename A,
+ typename I, // I models InputIterator
+ typename F> // F models ForwardIterator
+inline typename container_detail::enable_if_memtransfer_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::memmove_n_source(f, n, r); }
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// uninitialized_value_init_alloc_n
+//
+//////////////////////////////////////////////////////////////////////////////
+
+//! <b>Effects</b>:
+//! \code
+//! for (; n--; ++r, ++f)
+//! allocator_traits::construct(a, &*r);
+//! \endcode
+//!
+//! <b>Returns</b>: r
+template
+ <typename A,
+ typename F> // F models ForwardIterator
+inline typename container_detail::disable_if_memzero_initializable<F, F>::type
+ uninitialized_value_init_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::iterator_to_raw_pointer(r));
+ ++r;
+ }
+ }
+ BOOST_CATCH(...){
+ for (; back != r; ++back){
+ allocator_traits<A>::destroy(a, container_detail::iterator_to_raw_pointer(back));
+ }
+ BOOST_RETHROW;
+ }
+ BOOST_CATCH_END
+ return r;
+}
+
+template
+ <typename A,
+ typename F> // F models ForwardIterator
+inline typename container_detail::enable_if_memzero_initializable<F, F>::type
+ uninitialized_value_init_alloc_n(A &, typename allocator_traits<A>::difference_type n, F r)
+{
+ typedef typename std::iterator_traits<F>::value_type value_type;
+ ::memset((void*)container_detail::iterator_to_raw_pointer(r), 0, sizeof(value_type)*n);
+ std::advance(r, n);
+ return r;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// uninitialized_default_init_alloc_n
+//
+//////////////////////////////////////////////////////////////////////////////
+
+//! <b>Effects</b>:
+//! \code
+//! for (; n--; ++r, ++f)
+//! allocator_traits::construct(a, &*r);
+//! \endcode
+//!
+//! <b>Returns</b>: r
+template
+ <typename A,
+ typename F> // F models ForwardIterator
+inline F uninitialized_default_init_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::iterator_to_raw_pointer(r), default_init);
+ ++r;
+ }
+ }
+ BOOST_CATCH(...){
+ for (; back != r; ++back){
+ allocator_traits<A>::destroy(a, container_detail::iterator_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{
+ while (f != l) {
+ allocator_traits<A>::construct(a, container_detail::iterator_to_raw_pointer(f), t);
+ ++f;
+ }
+ }
+ BOOST_CATCH(...){
+ for (; back != l; ++back){
+ allocator_traits<A>::destroy(a, container_detail::iterator_to_raw_pointer(back));
+ }
+ BOOST_RETHROW;
+ }
+ BOOST_CATCH_END
+}
+
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// 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 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)
+{
+ F back = r;
+ BOOST_TRY{
+ while (n--) {
+ allocator_traits<A>::construct(a, container_detail::iterator_to_raw_pointer(r), v);
+ ++r;
+ }
+ }
+ BOOST_CATCH(...){
+ for (; back != r; ++back){
+ allocator_traits<A>::destroy(a, container_detail::iterator_to_raw_pointer(back));
+ }
+ BOOST_RETHROW;
+ }
+ BOOST_CATCH_END
+ return r;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// copy
+//
+//////////////////////////////////////////////////////////////////////////////
+
+template
+<typename I, // I models InputIterator
+typename F> // F models ForwardIterator
+inline typename container_detail::disable_if_memtransfer_copy_assignable<I, F, F>::type
+ copy(I f, I l, F r)
{
while (f != l) {
- allocator_traits<A>::construct(a, container_detail::to_raw_pointer(&*f), t);
- ++f;
+ *r = *f;
+ ++f; ++r;
}
+ return r;
}
+template
+<typename I, // I models InputIterator
+typename F> // F models ForwardIterator
+inline typename container_detail::enable_if_memtransfer_copy_assignable<I, F, F>::type
+ copy(I f, I l, F r) BOOST_CONTAINER_NOEXCEPT
+{ return container_detail::memmove(f, l, r); }
+
//////////////////////////////////////////////////////////////////////////////
//
-// uninitialized_copy_or_move_alloc
+// copy_n
//
//////////////////////////////////////////////////////////////////////////////
template
-<typename A
-,typename I // I models InputIterator
+<typename I, // I models InputIterator
+typename F> // F models ForwardIterator
+inline typename container_detail::disable_if_memtransfer_copy_assignable<I, F, F>::type
+ copy_n(I f, typename std::iterator_traits<I>::difference_type n, F r)
+{
+ while (n--) {
+ *r = *f;
+ ++f; ++r;
+ }
+ return r;
+}
+
+template
+<typename I, // I models InputIterator
+typename F> // F models ForwardIterator
+inline typename container_detail::enable_if_memtransfer_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::memmove_n(f, n, r); }
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// copy_n_source
+//
+//////////////////////////////////////////////////////////////////////////////
+
+template
+<typename I, // I models InputIterator
+typename F> // F models ForwardIterator
+inline typename container_detail::disable_if_memtransfer_copy_assignable<I, F, I>::type
+ copy_n_source(I f, typename std::iterator_traits<I>::difference_type n, F r)
+{
+ while (n--) {
+ *r = *f;
+ ++f; ++r;
+ }
+ return f;
+}
+
+template
+<typename I, // I models InputIterator
+typename F> // F models ForwardIterator
+inline typename container_detail::enable_if_memtransfer_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::memmove_n_source(f, n, r); }
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// copy_n_source_dest
+//
+//////////////////////////////////////////////////////////////////////////////
+
+template
+<typename I, // I models InputIterator
+typename F> // F models ForwardIterator
+inline typename container_detail::disable_if_memtransfer_copy_assignable<I, F, I>::type
+ copy_n_source_dest(I f, typename std::iterator_traits<I>::difference_type n, F &r)
+{
+ while (n--) {
+ *r = *f;
+ ++f; ++r;
+ }
+ return f;
+}
+
+template
+<typename I, // I models InputIterator
+typename F> // F models ForwardIterator
+inline typename container_detail::enable_if_memtransfer_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::memmove_n_source_dest(f, n, r); }
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// move
+//
+//////////////////////////////////////////////////////////////////////////////
+
+template
+<typename I, // I models InputIterator
+typename F> // F models ForwardIterator
+inline typename container_detail::disable_if_memtransfer_copy_assignable<I, F, F>::type
+ move(I f, I l, F r)
+{
+ while (f != l) {
+ *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_memtransfer_copy_assignable<I, F, F>::type
+ move(I f, I l, F r) BOOST_CONTAINER_NOEXCEPT
+{ return container_detail::memmove(f, l, r); }
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// move_n
+//
+//////////////////////////////////////////////////////////////////////////////
+
+template
+<typename I, // I models InputIterator
+typename F> // F models ForwardIterator
+inline typename container_detail::disable_if_memtransfer_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);
+ ++f; ++r;
+ }
+ return r;
+}
+
+template
+<typename I, // I models InputIterator
+typename F> // F models ForwardIterator
+inline typename container_detail::enable_if_memtransfer_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::memmove_n(f, n, r); }
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// move_n_source
+//
+//////////////////////////////////////////////////////////////////////////////
+
+template
+<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)
+inline typename container_detail::disable_if_memtransfer_copy_assignable<I, F, I>::type
+ move_n_source(I f, typename std::iterator_traits<I>::difference_type n, F r)
{
- return ::boost::container::uninitialized_move_alloc(a, f, l, r);
+ while (n--) {
+ *r = ::boost::move(*f);
+ ++f; ++r;
+ }
+ return f;
}
template
-<typename A
-,typename I // I models InputIterator
+<typename I // I models InputIterator
+,typename F> // F models ForwardIterator
+inline typename container_detail::enable_if_memtransfer_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::memmove_n_source(f, n, r); }
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// move_n_source_dest
+//
+//////////////////////////////////////////////////////////////////////////////
+
+template
+<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)
+inline typename container_detail::disable_if_memtransfer_copy_assignable<I, F, I>::type
+ move_n_source_dest(I f, typename std::iterator_traits<I>::difference_type n, F &r)
{
- return ::boost::container::uninitialized_copy_alloc(a, f, l, r);
+ while (n--) {
+ *r = ::boost::move(*f);
+ ++f; ++r;
+ }
+ return f;
}
+template
+<typename I // I models InputIterator
+,typename F> // F models ForwardIterator
+inline typename container_detail::enable_if_memtransfer_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::memmove_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--){
+ allocator_traits<A>::destroy(a, container_detail::iterator_to_raw_pointer(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_memtransfer_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_memtransfer_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;
+ void *const large_ptr = static_cast<void*>(container_detail::iterator_to_raw_pointer(large_range_f));
+ void *const short_ptr = static_cast<void*>(container_detail::iterator_to_raw_pointer(short_range_f));
+ void *const stora_ptr = static_cast<void*>(container_detail::iterator_to_raw_pointer(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_memtransfer_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::iterator_to_raw_pointer(large_range_f)));
+ char *short_ptr = static_cast<char*>(static_cast<void*>(container_detail::iterator_to_raw_pointer(short_range_f)));
+ char *stora_ptr = static_cast<char*>(static_cast<void*>(&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;
+ BOOST_CONTAINER_FALLTHOUGH
+ 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;
+ BOOST_CONTAINER_FALLTHOUGH
+ 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;
+ BOOST_CONTAINER_FALLTHOUGH
+ 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);
+ }
+}
} //namespace container {
} //namespace boost {
-
#include <boost/container/detail/config_end.hpp>
#endif //#ifndef BOOST_CONTAINER_DETAIL_UTILITIES_HPP
diff --git a/boost/container/detail/value_init.hpp b/boost/container/detail/value_init.hpp
index ec1a99c56d..68f9678358 100644
--- a/boost/container/detail/value_init.hpp
+++ b/boost/container/detail/value_init.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2005-2012.
+// (C) Copyright Ion Gaztanaga 2005-2013.
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
@@ -13,11 +13,11 @@
#ifndef BOOST_CONTAINER_DETAIL_VALUE_INIT_HPP
#define BOOST_CONTAINER_DETAIL_VALUE_INIT_HPP
-#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#if defined(_MSC_VER)
# pragma once
#endif
-#include "config_begin.hpp"
+#include <boost/container/detail/config_begin.hpp>
#include <boost/container/detail/workaround.hpp>
namespace boost {
diff --git a/boost/container/detail/variadic_templates_tools.hpp b/boost/container/detail/variadic_templates_tools.hpp
index d903dfa04c..b07fe3050e 100644
--- a/boost/container/detail/variadic_templates_tools.hpp
+++ b/boost/container/detail/variadic_templates_tools.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2008-2012. Distributed under the Boost
+// (C) Copyright Ion Gaztanaga 2008-2013. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
@@ -11,12 +11,13 @@
#ifndef BOOST_CONTAINER_DETAIL_VARIADIC_TEMPLATES_TOOLS_HPP
#define BOOST_CONTAINER_DETAIL_VARIADIC_TEMPLATES_TOOLS_HPP
-#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#if defined(_MSC_VER)
# pragma once
#endif
-#include "config_begin.hpp"
+#include <boost/container/detail/config_begin.hpp>
#include <boost/container/detail/workaround.hpp>
+
#include <boost/container/detail/type_traits.hpp>
#include <cstddef> //std::size_t
diff --git a/boost/container/detail/version_type.hpp b/boost/container/detail/version_type.hpp
index e47ba26f12..2eabc62483 100644
--- a/boost/container/detail/version_type.hpp
+++ b/boost/container/detail/version_type.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
+// (C) Copyright Ion Gaztanaga 2005-2013. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
@@ -16,7 +16,12 @@
#ifndef BOOST_CONTAINER_DETAIL_VERSION_TYPE_HPP
#define BOOST_CONTAINER_DETAIL_VERSION_TYPE_HPP
-#include "config_begin.hpp"
+#if defined(_MSC_VER)
+# pragma once
+#endif
+
+#include <boost/container/detail/config_begin.hpp>
+#include <boost/container/detail/workaround.hpp>
#include <boost/container/detail/mpl.hpp>
#include <boost/container/detail/type_traits.hpp>
@@ -80,13 +85,19 @@ struct version<T, true>
template <class T>
struct version
: public container_detail::integral_constant<unsigned, impl::version<T>::value>
+{};
+
+template<class T, unsigned N>
+struct is_version
{
+ static const bool value =
+ is_same< typename version<T>::type, integral_constant<unsigned, N> >::value;
};
} //namespace container_detail {
} //namespace container {
} //namespace boost{
-#include "config_end.hpp"
+#include <boost/container/detail/config_end.hpp>
#endif //#define BOOST_CONTAINER_DETAIL_VERSION_TYPE_HPP
diff --git a/boost/container/detail/workaround.hpp b/boost/container/detail/workaround.hpp
index c4440743fc..55ebe339ce 100644
--- a/boost/container/detail/workaround.hpp
+++ b/boost/container/detail/workaround.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
+// (C) Copyright Ion Gaztanaga 2005-2013. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
@@ -11,26 +11,62 @@
#ifndef BOOST_CONTAINER_DETAIL_WORKAROUND_HPP
#define BOOST_CONTAINER_DETAIL_WORKAROUND_HPP
+#if defined(_MSC_VER)
+# pragma once
+#endif
+
#include <boost/container/detail/config_begin.hpp>
-#if !defined(BOOST_NO_RVALUE_REFERENCES) && !defined(BOOST_NO_VARIADIC_TEMPLATES)\
+#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)\
&& !defined(BOOST_INTERPROCESS_DISABLE_VARIADIC_TMPL)
#define BOOST_CONTAINER_PERFECT_FORWARDING
#endif
-#if defined(BOOST_NO_NOEXCEPT)
- #define BOOST_CONTAINER_NOEXCEPT
+#if defined(BOOST_NO_CXX11_NOEXCEPT)
+ #if defined(BOOST_MSVC)
+ #define BOOST_CONTAINER_NOEXCEPT throw()
+ #else
+ #define BOOST_CONTAINER_NOEXCEPT
+ #endif
#define BOOST_CONTAINER_NOEXCEPT_IF(x)
#else
#define BOOST_CONTAINER_NOEXCEPT noexcept
#define BOOST_CONTAINER_NOEXCEPT_IF(x) noexcept(x)
#endif
-#if !defined(BOOST_NO_VARIADIC_TEMPLATES) && defined(__GXX_EXPERIMENTAL_CXX0X__)\
+#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && defined(__GXX_EXPERIMENTAL_CXX0X__)\
&& (__GNUC__*10000 + __GNUC_MINOR__*100 + __GNUC_PATCHLEVEL__ < 40700)
#define BOOST_CONTAINER_UNIMPLEMENTED_PACK_EXPANSION_TO_FIXED_LIST
#endif
+#if !defined(BOOST_FALLTHOUGH)
+ #define BOOST_CONTAINER_FALLTHOUGH
+#else
+ #define BOOST_CONTAINER_FALLTHOUGH BOOST_FALLTHOUGH;
+#endif
+
+//Macros for documentation purposes. For code, expands to the argument
+#define BOOST_CONTAINER_IMPDEF(TYPE) TYPE
+#define BOOST_CONTAINER_SEEDOC(TYPE) TYPE
+
+//Macros for memset optimization. In most platforms
+//memsetting pointers and floatings is safe and faster.
+//
+//If your platform does not offer these guarantees
+//define these to value zero.
+#ifndef BOOST_CONTAINER_MEMZEROED_FLOATING_POINT_IS_NOT_ZERO
+#define BOOST_CONTAINER_MEMZEROED_FLOATING_POINT_IS_ZERO 1
+#endif
+
+#ifndef BOOST_CONTAINER_MEMZEROED_POINTER_IS_NOT_NULL
+#define BOOST_CONTAINER_MEMZEROED_POINTER_IS_NULL
+#endif
+
+#define BOOST_CONTAINER_DOC1ST(TYPE1, TYPE2) TYPE2
+#define BOOST_CONTAINER_I ,
+#define BOOST_CONTAINER_DOCIGN(T) T
+#define BOOST_CONTAINER_DOCONLY(T)
+
#include <boost/container/detail/config_end.hpp>
#endif //#ifndef BOOST_CONTAINER_DETAIL_WORKAROUND_HPP