diff --git a/include/boost/container/allocator_traits.hpp b/include/boost/container/allocator_traits.hpp index c8bf708..828d664 100644 --- a/include/boost/container/allocator_traits.hpp +++ b/include/boost/container/allocator_traits.hpp @@ -28,7 +28,7 @@ #include #include #include -#include +#include #include //numeric_limits<>::max() #include //placement new #include //std::allocator diff --git a/include/boost/container/deque.hpp b/include/boost/container/deque.hpp index b63dab3..32fa480 100644 --- a/include/boost/container/deque.hpp +++ b/include/boost/container/deque.hpp @@ -58,9 +58,11 @@ #include #include #include -#include -#include +#include +#include +#include #include +#include namespace boost { namespace container { @@ -79,8 +81,7 @@ struct deque_value_traits typedef T value_type; typedef Allocator allocator_type; static const bool trivial_dctr = boost::has_trivial_destructor::value; - static const bool trivial_dctr_after_move = false; - //::boost::has_trivial_destructor_after_move::value || trivial_dctr; + static const bool trivial_dctr_after_move = ::boost::has_trivial_destructor_after_move::value; static const bool trivial_copy = has_trivial_copy::value; static const bool nothrow_copy = has_nothrow_copy::value; static const bool trivial_assign = has_trivial_assign::value; @@ -304,7 +305,7 @@ class deque_base { this->m_node = new_node; this->m_first = *new_node; - this->m_last = this->m_first + difference_type(this->s_buffer_size()); + this->m_last = this->m_first + this->s_buffer_size(); } friend const_iterator operator+(difference_type n, const const_iterator& x) @@ -565,9 +566,6 @@ class deque : protected deque_base typedef typename Base::ptr_alloc_ptr index_pointer; static size_type s_buffer_size() { return Base::s_buffer_size(); } - typedef container_detail::advanced_insert_aux_int advanced_insert_aux_int_t; - typedef repeat_iterator r_iterator; - typedef boost::move_iterator move_it; typedef allocator_traits allocator_traits_type; /// @endcond @@ -590,10 +588,10 @@ class deque : protected deque_base //! Effects: Constructs a deque taking the allocator as parameter. //! - //! Throws: If allocator_type's copy constructor throws. + //! Throws: Nothing //! //! Complexity: Constant. - explicit deque(const allocator_type& a) + explicit deque(const allocator_type& a) BOOST_CONTAINER_NOEXCEPT : Base(a) {} @@ -607,8 +605,8 @@ class deque : protected deque_base explicit deque(size_type n) : Base(n, allocator_type()) { - container_detail::default_construct_aux_proxy proxy(this->alloc(), n); - proxy.uninitialized_copy_remaining_to(this->begin()); + container_detail::insert_default_constructed_n_proxy proxy(this->alloc()); + proxy.uninitialized_copy_n_and_update(this->begin(), n); //deque_base will deallocate in case of exception... } @@ -717,7 +715,7 @@ class deque : protected deque_base //! Complexity: Linear to the number of elements. ~deque() BOOST_CONTAINER_NOEXCEPT { - priv_destroy_range(this->members_.m_start, this->members_.m_finish); + this->priv_destroy_range(this->members_.m_start, this->members_.m_finish); } //! Effects: Makes *this contain the same elements as x. @@ -1020,7 +1018,7 @@ class deque : protected deque_base this->priv_erase_last_n(len - new_size); else{ const size_type n = new_size - this->size(); - container_detail::default_construct_aux_proxy proxy(this->alloc(), n); + container_detail::insert_default_constructed_n_proxy proxy(this->alloc()); priv_insert_back_aux_impl(n, proxy); } } @@ -1176,9 +1174,8 @@ class deque : protected deque_base this->priv_push_front_simple_commit(); } else{ - typedef container_detail::advanced_insert_aux_non_movable_emplace type; - type &&proxy = type(this->alloc(), boost::forward(args)...); - this->priv_insert_front_aux_impl(1, proxy); + typedef container_detail::insert_non_movable_emplace_proxy type; + this->priv_insert_front_aux_impl(1, type(this->alloc(), boost::forward(args)...)); } } @@ -1199,9 +1196,8 @@ class deque : protected deque_base this->priv_push_back_simple_commit(); } else{ - typedef container_detail::advanced_insert_aux_non_movable_emplace type; - type &&proxy = type(this->alloc(), boost::forward(args)...); - this->priv_insert_back_aux_impl(1, proxy); + typedef container_detail::insert_non_movable_emplace_proxy type; + this->priv_insert_back_aux_impl(1, type(this->alloc(), boost::forward(args)...)); } } @@ -1226,9 +1222,8 @@ class deque : protected deque_base return (this->end()-1); } else{ - typedef container_detail::advanced_insert_aux_emplace type; - type &&proxy = type(this->alloc(), boost::forward(args)...); - return this->priv_insert_aux_impl(p, 1, proxy); + typedef container_detail::insert_emplace_proxy type; + return this->priv_insert_aux_impl(p, 1, type(this->alloc(), boost::forward(args)...)); } } @@ -1247,9 +1242,8 @@ class deque : protected deque_base priv_push_front_simple_commit(); \ } \ else{ \ - container_detail::BOOST_PP_CAT(BOOST_PP_CAT \ - (advanced_insert_aux_non_movable_emplace, n), arg) \ - proxy \ + container_detail::BOOST_PP_CAT(insert_non_movable_emplace_proxy_arg, n) \ + proxy \ (this->alloc() BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _)); \ priv_insert_front_aux_impl(1, proxy); \ } \ @@ -1266,9 +1260,8 @@ class deque : protected deque_base priv_push_back_simple_commit(); \ } \ else{ \ - container_detail::BOOST_PP_CAT(BOOST_PP_CAT( \ - advanced_insert_aux_non_movable_emplace, n), arg) \ - proxy \ + container_detail::BOOST_PP_CAT(insert_non_movable_emplace_proxy_arg, n) \ + proxy \ (this->alloc() BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _)); \ priv_insert_back_aux_impl(1, proxy); \ } \ @@ -1287,8 +1280,8 @@ class deque : protected deque_base return (this->end()-1); \ } \ else{ \ - container_detail::BOOST_PP_CAT(BOOST_PP_CAT(advanced_insert_aux_emplace, n), arg) \ - proxy \ + container_detail::BOOST_PP_CAT(insert_emplace_proxy_arg, n) \ + proxy \ (this->alloc() BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _)); \ return this->priv_insert_aux_impl(p, 1, proxy); \ } \ @@ -1424,7 +1417,7 @@ class deque : protected deque_base #endif ) { - container_detail::advanced_insert_aux_proxy proxy(this->alloc(), first, last); + container_detail::insert_range_proxy proxy(this->alloc(), first); return priv_insert_aux_impl(p, (size_type)std::distance(first, last), proxy); } #endif @@ -1477,8 +1470,8 @@ class deque : protected deque_base { const_iterator next = pos; ++next; - difference_type index = pos - this->members_.m_start; - if (size_type(index) < (this->size() >> 1)) { + size_type index = pos - this->members_.m_start; + if (index < (this->size()/2)) { boost::move_backward(begin(), iterator(pos), iterator(next)); pop_front(); } @@ -1504,9 +1497,9 @@ class deque : protected deque_base return this->members_.m_finish; } else { - difference_type n = last - first; - difference_type elems_before = first - this->members_.m_start; - if (elems_before < static_cast(this->size() - n) - elems_before) { + const size_type n = static_cast(last - first); + const size_type elems_before = static_cast(first - this->members_.m_start); + if (elems_before < (this->size() - n) - elems_before) { boost::move_backward(begin(), iterator(first), iterator(last)); iterator new_start = this->members_.m_start + n; if(!Base::traits_t::trivial_dctr_after_move) @@ -1584,81 +1577,49 @@ class deque : protected deque_base void priv_range_check(size_type n) const { if (n >= this->size()) BOOST_RETHROW std::out_of_range("deque"); } - iterator priv_insert(const_iterator position, const value_type &x) + template + iterator priv_insert(const_iterator position, BOOST_FWD_REF(U) x) { if (position == cbegin()){ - this->push_front(x); + this->push_front(::boost::forward(x)); return begin(); } else if (position == cend()){ - this->push_back(x); - return (end()-1); + this->push_back(::boost::forward(x)); + return --end(); } else { - return this->insert(position, size_type(1), x); + return priv_insert_aux_impl + (position, (size_type)1, container_detail::get_insert_value_proxy(this->alloc(), ::boost::forward(x))); } } - iterator priv_insert(const_iterator position, BOOST_RV_REF(value_type) mx) - { - if (position == cbegin()) { - this->push_front(boost::move(mx)); - return begin(); - } - else if (position == cend()) { - this->push_back(boost::move(mx)); - return(end()-1); - } - else { - return this->insert(position, move_it(r_iterator(mx, 1)), move_it(r_iterator())); - } - } - - void priv_push_front(const value_type &t) + template + void priv_push_front(BOOST_FWD_REF(U) x) { if(this->priv_push_front_simple_available()){ allocator_traits_type::construct - ( this->alloc(), this->priv_push_front_simple_pos(), t); + ( this->alloc(), this->priv_push_front_simple_pos(), ::boost::forward(x)); this->priv_push_front_simple_commit(); } else{ - this->insert(cbegin(), size_type(1), t); + priv_insert_aux_impl + (this->cbegin(), (size_type)1, container_detail::get_insert_value_proxy(this->alloc(), ::boost::forward(x))); } } - void priv_push_front(BOOST_RV_REF(value_type) t) - { - if(this->priv_push_front_simple_available()){ - allocator_traits_type::construct - ( this->alloc(), this->priv_push_front_simple_pos(), boost::move(t)); - this->priv_push_front_simple_commit(); - } - else{ - this->insert(cbegin(), move_it(r_iterator(t, 1)), move_it(r_iterator())); - } - } - - void priv_push_back(const value_type &t) + template + void priv_push_back(BOOST_FWD_REF(U) x) { if(this->priv_push_back_simple_available()){ allocator_traits_type::construct - ( this->alloc(), this->priv_push_back_simple_pos(), t); + ( this->alloc(), this->priv_push_back_simple_pos(), ::boost::forward(x)); this->priv_push_back_simple_commit(); } else{ - this->insert(cend(), size_type(1), t); - } - } - - void priv_push_back(BOOST_RV_REF(T) t) - { - if(this->priv_push_back_simple_available()){ - allocator_traits_type::construct - ( this->alloc(), this->priv_push_back_simple_pos(), boost::move(t)); - this->priv_push_back_simple_commit(); - } - else{ - this->insert(cend(), move_it(r_iterator(t, 1)), move_it(r_iterator())); + priv_insert_aux_impl + (this->cend(), (size_type)1, container_detail::get_insert_value_proxy(this->alloc(), ::boost::forward(x))); + container_detail::insert_copy_proxy proxy(this->alloc(), x); } } @@ -1710,7 +1671,8 @@ class deque : protected deque_base } } - iterator priv_insert_aux_impl(const_iterator p, size_type n, advanced_insert_aux_int_t &interf) + template + iterator priv_insert_aux_impl(const_iterator p, size_type n, InsertProxy interf) { iterator pos(p); const size_type pos_n = p - this->cbegin(); @@ -1719,58 +1681,85 @@ class deque : protected deque_base pos = this->begin(); } - const difference_type elemsbefore = pos - this->members_.m_start; - size_type length = this->size(); - if (elemsbefore < static_cast(length / 2)) { - iterator new_start = this->priv_reserve_elements_at_front(n); - iterator old_start = this->members_.m_start; - pos = this->members_.m_start + elemsbefore; - if (elemsbefore >= difference_type(n)) { - iterator start_n = this->members_.m_start + difference_type(n); - ::boost::container::uninitialized_move_alloc - (this->alloc(), this->members_.m_start, start_n, new_start); + const size_type elemsbefore = static_cast(pos - this->members_.m_start); + const size_type length = this->size(); + if (elemsbefore < length / 2) { + const iterator new_start = this->priv_reserve_elements_at_front(n); + const iterator old_start = this->members_.m_start; + if(!elemsbefore){ + interf.uninitialized_copy_n_and_update(new_start, n); this->members_.m_start = new_start; - boost::move(start_n, pos, old_start); - interf.copy_remaining_to(pos - difference_type(n)); } - else { - difference_type mid_count = (difference_type(n) - elemsbefore); - iterator mid_start = old_start - mid_count; - interf.uninitialized_copy_some_and_update(mid_start, mid_count, true); - this->members_.m_start = mid_start; - ::boost::container::uninitialized_move_alloc - (this->alloc(), old_start, pos, new_start); - this->members_.m_start = new_start; - interf.copy_remaining_to(old_start); + else{ + pos = this->members_.m_start + elemsbefore; + if (elemsbefore >= n) { + const iterator start_n = this->members_.m_start + n; + ::boost::container::uninitialized_move_alloc + (this->alloc(), this->members_.m_start, start_n, new_start); + this->members_.m_start = new_start; + boost::move(start_n, pos, old_start); + interf.copy_n_and_update(pos - n, n); + } + else { + const size_type mid_count = n - elemsbefore; + const iterator mid_start = old_start - mid_count; + interf.uninitialized_copy_n_and_update(mid_start, mid_count); + this->members_.m_start = mid_start; + ::boost::container::uninitialized_move_alloc + (this->alloc(), old_start, pos, new_start); + this->members_.m_start = new_start; + interf.copy_n_and_update(old_start, elemsbefore); + } } } else { - iterator new_finish = this->priv_reserve_elements_at_back(n); - iterator old_finish = this->members_.m_finish; - const difference_type elemsafter = - difference_type(length) - elemsbefore; - pos = this->members_.m_finish - elemsafter; - if (elemsafter >= difference_type(n)) { - iterator finish_n = this->members_.m_finish - difference_type(n); - ::boost::container::uninitialized_move_alloc - (this->alloc(), finish_n, this->members_.m_finish, this->members_.m_finish); + const iterator new_finish = this->priv_reserve_elements_at_back(n); + const iterator old_finish = this->members_.m_finish; + const size_type elemsafter = length - elemsbefore; + if(!elemsafter){ + interf.uninitialized_copy_n_and_update(old_finish, n); this->members_.m_finish = new_finish; - boost::move_backward(pos, finish_n, old_finish); - interf.copy_remaining_to(pos); } - else { - interf.uninitialized_copy_some_and_update(old_finish, elemsafter, false); - this->members_.m_finish += n-elemsafter; - ::boost::container::uninitialized_move_alloc - (this->alloc(), pos, old_finish, this->members_.m_finish); - this->members_.m_finish = new_finish; - interf.copy_remaining_to(pos); + else{ + pos = this->members_.m_finish - elemsafter; + if (elemsafter >= n) { + iterator finish_n = this->members_.m_finish - difference_type(n); + ::boost::container::uninitialized_move_alloc + (this->alloc(), finish_n, this->members_.m_finish, this->members_.m_finish); + this->members_.m_finish = new_finish; + boost::move_backward(pos, finish_n, old_finish); + interf.copy_n_and_update(pos, n); + } + else { + const size_type raw_gap = n - elemsafter; + ::boost::container::uninitialized_move_alloc + (this->alloc(), pos, old_finish, this->members_.m_finish + raw_gap); + BOOST_TRY{ + interf.uninitialized_copy_n_and_update(old_finish, raw_gap); + } + BOOST_CATCH(...){ + this->priv_destroy_range(this->members_.m_finish, this->members_.m_finish + (old_finish - pos)); + BOOST_RETHROW + } + BOOST_CATCH_END + this->members_.m_finish = new_finish; + interf.copy_n_and_update(pos, elemsafter); + /* + interf.uninitialized_copy_some_and_update(old_finish, elemsafter, false); + this->members_.m_finish += n-elemsafter; + ::boost::container::uninitialized_move_alloc + (this->alloc(), pos, old_finish, this->members_.m_finish); + this->members_.m_finish = new_finish; + interf.copy_remaining_to(pos); + */ + } } } return this->begin() + pos_n; } - iterator priv_insert_back_aux_impl(size_type n, advanced_insert_aux_int_t &interf) + template + iterator priv_insert_back_aux_impl(size_type n, InsertProxy interf) { if(!this->members_.m_map){ this->priv_initialize_map(0); @@ -1778,19 +1767,20 @@ class deque : protected deque_base iterator new_finish = this->priv_reserve_elements_at_back(n); iterator old_finish = this->members_.m_finish; - interf.uninitialized_copy_some_and_update(old_finish, n, true); + interf.uninitialized_copy_n_and_update(old_finish, n); this->members_.m_finish = new_finish; return iterator(this->members_.m_finish - n); } - iterator priv_insert_front_aux_impl(size_type n, advanced_insert_aux_int_t &interf) + template + iterator priv_insert_front_aux_impl(size_type n, InsertProxy interf) { if(!this->members_.m_map){ this->priv_initialize_map(0); } iterator new_start = this->priv_reserve_elements_at_front(n); - interf.uninitialized_copy_some_and_update(new_start, difference_type(n), true); + interf.uninitialized_copy_n_and_update(new_start, n); this->members_.m_start = new_start; return new_start; } @@ -2015,15 +2005,14 @@ inline void swap(deque& x, deque& y) /// @cond namespace boost { -/* + //!has_trivial_destructor_after_move<> == true_type //!specialization for optimizations template struct has_trivial_destructor_after_move > -{ - enum { value = has_trivial_destructor::value }; -}; -*/ + : public ::boost::has_trivial_destructor_after_move +{}; + } /// @endcond diff --git a/include/boost/container/detail/adaptive_node_pool_impl.hpp b/include/boost/container/detail/adaptive_node_pool_impl.hpp index 39b9942..42bdf43 100644 --- a/include/boost/container/detail/adaptive_node_pool_impl.hpp +++ b/include/boost/container/detail/adaptive_node_pool_impl.hpp @@ -21,16 +21,28 @@ #include #include #include +#include #include #include #include #include #include #include +#include #include 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 @@ -42,42 +54,160 @@ struct hdr_offset_holder_t size_type hdr_offset; }; +template +struct less_func; + +template +struct less_func +{ + static bool less(SizeType, SizeType, const void *, const void *) + { return true; } +}; + +template +struct less_func +{ + static bool less(SizeType ls, SizeType rs, const void *, const void *) + { return ls < rs; } +}; + +template +struct less_func +{ + static bool less(SizeType, SizeType, const void *la, const void *ra) + { return &la < &ra; } +}; + +template +struct less_func +{ + static bool less(SizeType ls, SizeType rs, const void *la, const void *ra) + { return (ls < rs) || ((ls == rs) && (la < ra)); } +}; + +template +struct block_container_traits +{ + typedef typename bi::make_set_base_hook + < bi::void_pointer + , bi::optimize_size + , bi::link_mode >::type hook_t; + + template + struct container + { + typedef typename bi::make_multiset + , bi::size_type >::type type; + }; + + template + 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(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 + static void insert_was_empty(Container &container, typename Container::value_type &v, bool) + { + container.insert(v); + } + + template + static void erase_first(Container &container) + { + container.erase(container.cbegin()); + } + + template + static void erase_last(Container &container) + { + container.erase(--container.cend()); + } +}; + template +struct block_container_traits +{ + typedef typename bi::make_list_base_hook + < bi::void_pointer + , bi::link_mode >::type hook_t; + + template + struct container + { + typedef typename bi::make_list + , bi::size_type, bi::constant_time_size >::type type; + }; + + template + 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 + 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 + static void erase_first(Container &container) + { + container.pop_front(); + } + + template + static void erase_last(Container &container) + { + container.pop_back(); + } +}; + +template struct adaptive_pool_types { typedef VoidPointer void_pointer; - typedef typename bi::make_set_base_hook - < bi::void_pointer - , bi::optimize_size - , bi::constant_time_size - , bi::link_mode >::type multiset_hook_t; - + static const bool ordered = (Flags & (adaptive_pool_flag::size_ordered | adaptive_pool_flag::address_ordered)) != 0; + typedef block_container_traits block_container_traits_t; + typedef typename block_container_traits_t::hook_t hook_t; typedef hdr_offset_holder_t 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::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:: + 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 - >::type block_multiset_t; + typedef typename block_container_traits_t:: template container::type block_container_t; }; template @@ -113,9 +243,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 +265,7 @@ inline void calculate_num_subblocks real_num_node = (possible_num_subblock-1)*elements_per_subblock + hdr_subblock_elements; } -template +template class private_adaptive_node_pool_impl { //Non-copyable @@ -147,27 +277,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_ IsAlignOnly; typedef true_ AlignOnlyTrue; typedef false_ AlignOnlyFalse; + //size_ordered + static const bool SizeOrdered = (Flags & adaptive_pool_flag::size_ordered) != 0; + typedef bool_ IsSizeOrdered; + typedef true_ SizeOrderedTrue; + typedef false_ SizeOrderedFalse; + //address_ordered + static const bool AddressOrdered = (Flags & adaptive_pool_flag::address_ordered) != 0; + typedef bool_ IsAddressOrdered; + typedef true_ AddressOrderedTrue; + typedef false_ AddressOrderedFalse; public: - typedef typename node_slist::node_t node_t; - typedef typename node_slist::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::block_info_t block_info_t; - typedef typename adaptive_pool_types::block_multiset_t block_multiset_t; - typedef typename block_multiset_t::iterator block_iterator; - typedef typename adaptive_pool_types::hdr_offset_holder hdr_offset_holder; + typedef adaptive_pool_types + 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::value; + static const size_type MaxAlign = alignment_of::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 +326,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::value))) + , m_real_node_size(lcm(node_size, size_type(alignment_of::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 +340,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 +359,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 +371,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(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(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(free_nodes.empty()){ - m_block_multiset.erase(m_block_multiset.begin()); + 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()); + } + 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(&*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 +536,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,83 +544,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)); + 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(&*it)); + --it; + block_container_traits_t::erase_last(m_block_container); + chain.push_front(void_pointer(addr)); + } + 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); } - void priv_reinsert_nodes_in_block(multiallocation_chain &chain, size_type n) + void priv_reinsert_block(block_info_t &prev_block_info, const bool prev_block_was_empty) { - block_iterator block_it(m_block_multiset.end()); - while(n--){ - void *pElem = container_detail::to_raw_pointer(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(pElem); - block_info->free_nodes.push_front(*to_deallocate); + //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; - 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); - } - 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(); + //Update free block count + m_totally_free_blocks += static_cast(is_full); + if(prev_block_was_empty){ + block_container_traits_t::insert_was_empty(m_block_container, prev_block_info, is_full); } - } - - node_t *priv_take_first_node() - { - 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()); + else{ + block_container_traits_t::reinsert_was_used(m_block_container, prev_block_info, is_full); } - else if(free_nodes_count == m_real_num_node){ - --m_totally_free_blocks; - } - priv_invariants(); - return first_node; } class block_destroyer; @@ -411,33 +600,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. @@ -446,44 +633,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(&*it)); for(size_type i = 0, max = m_num_subblocks; i < max; ++i){ - BOOST_ASSERT(hdr_off_holder->hdr_offset == size_type(reinterpret_cast(&*it)- reinterpret_cast(hdr_off_holder))); + const size_type offset = reinterpret_cast(const_cast(&*it)) - reinterpret_cast(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(reinterpret_cast(hdr_off_holder) + m_real_block_alignment); @@ -499,19 +687,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; } @@ -533,93 +723,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 *const hdr_off_holder = reinterpret_cast (reinterpret_cast(block) - (m_num_subblocks-1)*m_real_block_alignment); BOOST_ASSERT(hdr_off_holder->hdr_offset == size_type(reinterpret_cast(block) - reinterpret_cast(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; } - //!Allocates a several blocks of nodes. Can throw - void priv_alloc_block(size_type n, AlignOnlyTrue) + hdr_offset_holder *priv_first_subblock_from_block(block_info_t *block, AlignOnlyTrue) const { - size_type real_block_size = m_real_block_alignment - PayloadPerAllocation; - 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 - (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); - - 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; + return reinterpret_cast(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(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); } } } - void priv_alloc_block(size_type n, AlignOnlyFalse) + //!Allocates a several blocks of nodes. Can throw + void priv_append_from_new_blocks(size_type min_elements, multiallocation_chain &chain, AlignOnlyTrue) { - 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 - 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 + (mp_segment_mngr_base->allocate_aligned(real_block_size, m_real_block_alignment)); + 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 std::bad_alloc(); + } + block_info_t &c_info = *new(mem_address)block_info_t(); + mem_address += HdrSize; + 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_append_from_new_blocks(size_type min_elements, multiallocation_chain &chain, AlignOnlyFalse) + { + 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 (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 std::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(&static_cast(c_info)->hdr_offset) == - static_cast(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(&static_cast(c_info).hdr_offset) == + static_cast(&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 ::template rebind_pointer::type segment_mngr_base_ptr_t; @@ -633,9 +859,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/include/boost/container/detail/advanced_insert_int.hpp b/include/boost/container/detail/advanced_insert_int.hpp index e7adcd2..4c4fef6 100644 --- a/include/boost/container/detail/advanced_insert_int.hpp +++ b/include/boost/container/detail/advanced_insert_int.hpp @@ -20,160 +20,177 @@ #include #include #include -#include +#include #include //std::iterator_traits #include +#include namespace boost { namespace container { namespace container_detail { -//This class will be interface for operations dependent on FwdIt types used advanced_insert_aux_impl -template -struct advanced_insert_aux_int -{ - typedef typename std::iterator_traits::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() {} -}; - -//This class template will adapt each FwIt types to advanced_insert_aux_int template -struct advanced_insert_aux_proxy - : public advanced_insert_aux_int +struct insert_range_proxy { typedef typename allocator_traits::size_type size_type; typedef typename allocator_traits::value_type value_type; - typedef typename advanced_insert_aux_int::difference_type difference_type; - advanced_insert_aux_proxy(A& a, FwdIt first, FwdIt last) - : a_(a), first_(first), last_(last) + insert_range_proxy(A& a, FwdIt first) + : a_(a), first_(first) {} - virtual ~advanced_insert_aux_proxy() - {} - - 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); } - - virtual void uninitialized_copy_some_and_update(Iterator pos, difference_type division_count, bool first_n) + void uninitialized_copy_n_and_update(Iterator pos, 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::uninitialized_copy_or_move_alloc_n_source + (this->a_, this->first_, n, pos); } - virtual void copy_some_and_update(Iterator pos, difference_type division_count, bool first_n) + void copy_n_and_update(Iterator pos, size_type n) { - 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; - } + this->first_ = ::boost::container::copy_or_move_n_source(this->first_, n, pos); } + A &a_; - FwdIt first_, last_; + FwdIt first_; }; -//This class template will adapt default construction insertions to advanced_insert_aux_int + template -struct default_construct_aux_proxy - : public advanced_insert_aux_int +struct insert_n_copies_proxy +{ + typedef typename allocator_traits::size_type size_type; + typedef typename allocator_traits::value_type value_type; + + insert_n_copies_proxy(A& a, const value_type &v) + : a_(a), v_(v) + {} + + void uninitialized_copy_n_and_update(Iterator p, size_type n) + { std::uninitialized_fill_n(p, n, v_); } + + void copy_n_and_update(Iterator p, size_type n) + { std::fill_n(p, n, v_); } + + A &a_; + const value_type &v_; +}; + +template +struct insert_default_constructed_n_proxy { typedef ::boost::container::allocator_traits alloc_traits; typedef typename allocator_traits::size_type size_type; typedef typename allocator_traits::value_type value_type; - typedef typename advanced_insert_aux_int::difference_type difference_type; - default_construct_aux_proxy(A &a, size_type count) - : a_(a), count_(count) + + explicit insert_default_constructed_n_proxy(A &a) + : a_(a) {} - virtual ~default_construct_aux_proxy() - {} - - virtual void copy_remaining_to(Iterator) - { //This should never be called with any count - BOOST_ASSERT(this->count_ == 0); - } - - 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 uninitialized_copy_n_and_update(Iterator p, size_type n) { - 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); - } - - virtual void copy_some_and_update(Iterator , difference_type division_count, bool first_n) - { - 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; - } - - private: - void priv_uninitialized_copy(Iterator p, const size_type n) - { - BOOST_ASSERT(n <= this->count_); Iterator orig_p = p; - size_type i = 0; - try{ - for(; i < n; ++i, ++p){ + size_type n_left = n; + BOOST_TRY{ + for(; n_left--; ++p){ alloc_traits::construct(this->a_, container_detail::to_raw_pointer(&*p)); } } - catch(...){ - while(i--){ + BOOST_CATCH(...){ + for(; orig_p != p; ++orig_p){ alloc_traits::destroy(this->a_, container_detail::to_raw_pointer(&*orig_p++)); } - throw; + BOOST_RETHROW } - this->count_ -= n; + BOOST_CATCH_END } + + void copy_n_and_update(Iterator, size_type) + { + BOOST_ASSERT(false); + } + + private: A &a_; - size_type count_; }; +template +struct insert_copy_proxy +{ + typedef boost::container::allocator_traits alloc_traits; + typedef typename alloc_traits::size_type size_type; + typedef typename alloc_traits::value_type value_type; + + insert_copy_proxy(A& a, const value_type &v) + : a_(a), v_(v) + {} + + void uninitialized_copy_n_and_update(Iterator p, size_type n) + { + BOOST_ASSERT(n == 1); (void)n; + alloc_traits::construct( this->a_ + , container_detail::to_raw_pointer(&*p) + , v_ + ); + } + + void copy_n_and_update(Iterator p, size_type n) + { + BOOST_ASSERT(n == 1); (void)n; + *p =v_; + } + + A &a_; + const value_type &v_; +}; + + +template +struct insert_move_proxy +{ + typedef boost::container::allocator_traits alloc_traits; + typedef typename alloc_traits::size_type size_type; + typedef typename alloc_traits::value_type value_type; + + insert_move_proxy(A& a, value_type &v) + : a_(a), v_(v) + {} + + void uninitialized_copy_n_and_update(Iterator p, size_type n) + { + BOOST_ASSERT(n == 1); (void)n; + alloc_traits::construct( this->a_ + , container_detail::to_raw_pointer(&*p) + , ::boost::move(v_) + ); + } + + void copy_n_and_update(Iterator p, size_type n) + { + BOOST_ASSERT(n == 1); (void)n; + *p = ::boost::move(v_); + } + + A &a_; + value_type &v_; +}; + +template +insert_move_proxy get_insert_value_proxy(A& a, BOOST_RV_REF(typename std::iterator_traits::value_type) v) +{ + return insert_move_proxy(a, v); +} + +template +insert_copy_proxy get_insert_value_proxy(A& a, const typename std::iterator_traits::value_type &v) +{ + return insert_copy_proxy(a, v); +} + }}} //namespace boost { namespace container { namespace container_detail { #ifdef BOOST_CONTAINER_PERFECT_FORWARDING #include -#include +#include #include //#include //For debugging purposes @@ -181,138 +198,74 @@ namespace boost { namespace container { namespace container_detail { - -//This class template will adapt emplace construction insertions of movable types -//to advanced_insert_aux_int template -struct advanced_insert_aux_non_movable_emplace - : public advanced_insert_aux_int +struct insert_non_movable_emplace_proxy { - typedef boost::container::allocator_traits alloc_traits; - typedef typename allocator_traits::size_type size_type; - typedef typename allocator_traits::value_type value_type; - typedef typename advanced_insert_aux_int::difference_type difference_type; - typedef typename build_number_seq::type index_tuple_t; + typedef boost::container::allocator_traits 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::type index_tuple_t; + + explicit insert_non_movable_emplace_proxy(A &a, Args&&... args) + : a_(a), args_(args...) {} - ~advanced_insert_aux_non_movable_emplace() - {} - - 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(Iterator p, size_type n) + { this->priv_uninitialized_copy_some_and_update(index_tuple_t(), p, n); } private: template - void priv_uninitialized_copy_some_and_update(const index_tuple&, Iterator p, difference_type division_count, bool first_n) + void priv_uninitialized_copy_some_and_update(const index_tuple&, 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::forward(get(this->args_))... - ); - this->used_ = true; - } - } - } - - template - void priv_uninitialized_copy_remaining_to(const index_tuple&, Iterator p) - { - if(!this->used_){ - alloc_traits::construct( this->a_ - , container_detail::to_raw_pointer(&*p) - , ::boost::forward(get(this->args_))... - ); - this->used_ = true; - } + BOOST_ASSERT(n == 1); (void)n; + alloc_traits::construct( this->a_ + , container_detail::to_raw_pointer(&*p) + , ::boost::forward(get(this->args_))... + ); } protected: A &a_; tuple args_; - bool used_; }; -//This class template will adapt emplace construction insertions of movable types -//to advanced_insert_aux_int template -struct advanced_insert_aux_emplace - : public advanced_insert_aux_non_movable_emplace +struct insert_emplace_proxy + : public insert_non_movable_emplace_proxy { - typedef advanced_insert_aux_non_movable_emplace base_t; - typedef boost::container::allocator_traits 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; + typedef insert_non_movable_emplace_proxy base_t; + typedef boost::container::allocator_traits 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 advanced_insert_aux_emplace(A &a, Args&&... args) + explicit insert_emplace_proxy(A &a, Args&&... args) : base_t(a, ::boost::forward(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(Iterator p, size_type n) + { this->priv_copy_some_and_update(index_tuple_t(), p, n); } private: - template - void priv_copy_remaining_to(const index_tuple&, Iterator p) - { - if(!this->used_){ - aligned_storage::value> v; - value_type *vp = static_cast(static_cast(&v)); - alloc_traits::construct(this->a_, vp, - ::boost::forward(get(this->args_))...); - scoped_destructor d(this->a_, vp); - *p = ::boost::move(*vp); - d.release(); - this->used_ = true; - } - } template - void priv_copy_some_and_update(const index_tuple&, Iterator p, difference_type division_count, bool first_n) + void priv_copy_some_and_update(const index_tuple&, Iterator p, size_type n) { - BOOST_ASSERT(division_count <=1); - if((first_n && division_count == 1) || (!first_n && division_count == 0)){ - if(!this->used_){ - aligned_storage::value> v; - value_type *vp = static_cast(static_cast(&v)); - alloc_traits::construct(this->a_, vp, - ::boost::forward(get(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_ASSERT(n ==1); (void)n; + aligned_storage::value> v; + value_type *vp = static_cast(static_cast(&v)); + alloc_traits::construct(this->a_, vp, + ::boost::forward(get(this->args_))...); + BOOST_TRY{ + *p = ::boost::move(*vp); } + BOOST_CATCH(...){ + alloc_traits::destroy(this->a_, vp); + BOOST_RETHROW + } + BOOST_CATCH_END + alloc_traits::destroy(this->a_, vp); } }; @@ -327,115 +280,73 @@ namespace boost { namespace container { namespace container_detail { -#define BOOST_PP_LOCAL_MACRO(n) \ -template \ -struct BOOST_PP_CAT(BOOST_PP_CAT(advanced_insert_aux_non_movable_emplace, n), arg) \ - : public advanced_insert_aux_int \ +#define BOOST_PP_LOCAL_MACRO(N) \ +template \ +struct BOOST_PP_CAT(insert_non_movable_emplace_proxy_arg, N) \ { \ typedef boost::container::allocator_traits alloc_traits; \ - typedef typename allocator_traits::size_type size_type; \ - typedef typename allocator_traits::value_type value_type; \ - typedef typename advanced_insert_aux_int::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, _) ) \ + BOOST_PP_CAT(insert_non_movable_emplace_proxy_arg, N) \ + ( 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, _) \ - {} \ + BOOST_PP_ENUM_TRAILING(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(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 \ + ( this->a_ \ + , container_detail::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(Iterator, size_type) \ { BOOST_ASSERT(false); } \ \ + protected: \ A &a_; \ - bool used_; \ - BOOST_PP_REPEAT(n, BOOST_CONTAINER_PP_PARAM_DEFINE, _) \ + BOOST_PP_REPEAT(N, BOOST_CONTAINER_PP_PARAM_DEFINE, _) \ }; \ \ -template \ -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 \ +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) \ - base_t; \ + typedef BOOST_PP_CAT(insert_non_movable_emplace_proxy_arg, N) \ + 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 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, _) ) \ - {} \ + BOOST_PP_CAT(insert_emplace_proxy_arg, N) \ + ( 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, _) ) \ + {} \ \ - virtual void copy_remaining_to(Iterator p) \ + void copy_n_and_update(Iterator p, size_type n) \ { \ - if(!this->used_){ \ - aligned_storage::value> v; \ - value_type *vp = static_cast(static_cast(&v)); \ - alloc_traits::construct(this->a_, vp \ - BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_MEMBER_FORWARD, _)); \ - scoped_destructor d(this->a_, vp); \ + BOOST_ASSERT(n == 1); (void)n; \ + aligned_storage::value> v; \ + value_type *vp = static_cast(static_cast(&v)); \ + alloc_traits::construct(this->a_, vp \ + BOOST_PP_ENUM_TRAILING(N, BOOST_CONTAINER_PP_MEMBER_FORWARD, _)); \ + BOOST_TRY{ \ *p = ::boost::move(*vp); \ - d.release(); \ - this->used_ = true; \ } \ - } \ - \ - 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::value> v; \ - value_type *vp = static_cast(static_cast(&v)); \ - alloc_traits::construct(this->a_, vp \ - BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_MEMBER_FORWARD, _)); \ - scoped_destructor d(this->a_, vp); \ - *p = ::boost::move(*vp); \ - d.release(); \ - this->used_ = true; \ - } \ + BOOST_CATCH(...){ \ + alloc_traits::destroy(this->a_, vp); \ + BOOST_RETHROW \ } \ + BOOST_CATCH_END \ + alloc_traits::destroy(this->a_, vp); \ } \ }; \ //! - #define BOOST_PP_LOCAL_LIMITS (0, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS) #include BOOST_PP_LOCAL_ITERATE() diff --git a/include/boost/container/detail/allocator_version_traits.hpp b/include/boost/container/detail/allocator_version_traits.hpp new file mode 100644 index 0000000..d69e61b --- /dev/null +++ b/include/boost/container/detail/allocator_version_traits.hpp @@ -0,0 +1,163 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2012-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_ALLOCATOR_VERSION_TRAITS_HPP +#define BOOST_CONTAINER_DETAIL_ALLOCATOR_VERSION_TRAITS_HPP + +#if (defined _MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif + +#include +#include +#include //allocator_traits +#include //multiallocation_chain +#include //version_type +#include //allocation_type +#include //integral_constant +#include //pointer_traits +#include //pair +#include //runtime_error +#include //BOOST_TRY + +namespace boost { +namespace container { +namespace container_detail { + +template::value> +struct allocator_version_traits +{ + typedef ::boost::container::container_detail::integral_constant + alloc_version; + + typedef typename Allocator::multiallocation_chain multiallocation_chain; + + typedef typename boost::container::allocator_traits::pointer pointer; + typedef typename boost::container::allocator_traits::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 + 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 +struct allocator_version_traits +{ + typedef ::boost::container::container_detail::integral_constant + alloc_version; + + typedef typename boost::container::allocator_traits::pointer pointer; + typedef typename boost::container::allocator_traits::size_type size_type; + typedef typename boost::container::allocator_traits::value_type value_type; + + typedef typename boost::intrusive::pointer_traits:: + template rebind_pointer::type void_ptr; + typedef container_detail::basic_multiallocation_chain + 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) + { + while(!holder.empty()){ + a.deallocate(holder.pop_front(), 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 + allocation_command(Allocator &a, allocation_type command, + size_type, size_type preferred_size, + size_type &received_size, const pointer &) + { + std::pair ret(pointer(), false); + if(!(command & allocate_new)){ + if(!(command & nothrow_allocation)){ + throw std::runtime_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 + +#endif // ! defined(BOOST_CONTAINER_DETAIL_ALLOCATOR_VERSION_TRAITS_HPP) diff --git a/include/boost/container/detail/destroyers.hpp b/include/boost/container/detail/destroyers.hpp index befae3f..f9bfd86 100644 --- a/include/boost/container/detail/destroyers.hpp +++ b/include/boost/container/detail/destroyers.hpp @@ -188,13 +188,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) + while(m_n--){ AllocTraits::destroy(m_a, raw_ptr); + } } private: @@ -323,7 +327,7 @@ class allocator_destroyer_and_chain_builder void operator()(const typename A::pointer &p) { allocator_traits::destroy(a_, container_detail::to_raw_pointer(p)); - c_.push_front(p); + c_.push_back(p); } }; @@ -348,8 +352,7 @@ class allocator_multialloc_chain_node_deallocator ~allocator_multialloc_chain_node_deallocator() { - if(!c_.empty()) - a_.deallocate_individual(boost::move(c_)); + a_.deallocate_individual(c_); } }; diff --git a/include/boost/container/detail/flat_tree.hpp b/include/boost/container/detail/flat_tree.hpp index 9146fd4..2af12d4 100644 --- a/include/boost/container/detail/flat_tree.hpp +++ b/include/boost/container/detail/flat_tree.hpp @@ -25,7 +25,7 @@ #include #include -#include +#include #include #include @@ -48,7 +48,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 +65,7 @@ class flat_tree_value_compare const Compare &get_comp() const { return *this; } - + Compare &get_comp() { return *this; } }; @@ -238,7 +238,7 @@ 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(); } @@ -441,17 +441,17 @@ class flat_tree //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 const_iterator b(this->cbegin()); + const_iterator pos(b); //Loop in burst sizes while(len){ const size_type burst = len < BurstSize ? len : BurstSize; - const const_iterator cend_(this->cend()); + const const_iterator ce(this->cend()); len -= burst; for(size_type i = 0; i != burst; ++i){ //Get the insertion position for each key - pos = const_cast(*this).priv_upper_bound(pos, cend_, KeyOfValue()(*first)); - positions[i] = static_cast(pos - beg); + pos = const_cast(*this).priv_upper_bound(pos, ce, KeyOfValue()(*first)); + positions[i] = static_cast(pos - b); ++first; } //Insert all in a single step in the precalculated positions @@ -489,22 +489,22 @@ class flat_tree //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 const_iterator b(this->cbegin()); + const_iterator pos(b); const value_compare &value_comp = this->m_data; skips[0u] = 0u; //Loop in burst sizes while(len){ const size_type burst = len < BurstSize ? len : BurstSize; size_type unique_burst = 0u; - const const_iterator cend_(this->cend()); + const const_iterator ce(this->cend()); while(unique_burst < burst && len > 0){ //Get the insertion position for each key const value_type & val = *first++; --len; - pos = const_cast(*this).priv_lower_bound(pos, cend_, KeyOfValue()(val)); + pos = const_cast(*this).priv_lower_bound(pos, ce, KeyOfValue()(val)); //Check if already present - if(pos != cend_ && !value_comp(val, *pos)){ + if(pos != ce && !value_comp(val, *pos)){ if(unique_burst > 0){ ++skips[unique_burst-1]; } @@ -512,7 +512,7 @@ class flat_tree } //If not present, calculate position - positions[unique_burst] = static_cast(pos - beg); + positions[unique_burst] = static_cast(pos - b); skips[unique_burst++] = 0u; } if(unique_burst){ @@ -692,22 +692,22 @@ class flat_tree // set operations: iterator find(const key_type& k) { - const Compare &key_comp_ = this->m_data.get_comp(); + const Compare &key_cmp = this->m_data.get_comp(); iterator i = this->lower_bound(k); - if (i != this->end() && key_comp_(k, KeyOfValue()(*i))){ - i = this->end(); + if (i != this->end() && key_cmp(k, KeyOfValue()(*i))){ + i = this->end(); } return i; } const_iterator find(const key_type& k) const { - const Compare &key_comp_ = this->m_data.get_comp(); + const Compare &key_cmp = this->m_data.get_comp(); const_iterator i = this->lower_bound(k); - if (i != this->end() && key_comp_(k, KeyOfValue()(*i))){ - i = this->end(); + if (i != this->end() && key_cmp(k, KeyOfValue()(*i))){ + i = this->end(); } return i; } @@ -737,11 +737,11 @@ class flat_tree std::pair equal_range(const key_type& k) const { return this->priv_equal_range(this->begin(), this->end(), 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); } private: struct insert_commit_data @@ -780,13 +780,13 @@ class flat_tree } std::pair priv_insert_unique_prepare - (const_iterator beg, const_iterator end_, const value_type& val, insert_commit_data &commit_data) + (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)); + commit_data.position = this->priv_lower_bound(b, e, KeyOfValue()(val)); return std::pair ( *reinterpret_cast(&commit_data.position) - , commit_data.position == end_ || value_comp(val, *commit_data.position)); + , commit_data.position == e || value_comp(val, *commit_data.position)); } std::pair priv_insert_unique_prepare @@ -854,7 +854,7 @@ class flat_tree RanIt priv_lower_bound(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; @@ -864,7 +864,7 @@ class flat_tree middle = first; middle += half; - if (key_comp_(key_extract(*middle), key)) { + if (key_cmp(key_extract(*middle), key)) { ++middle; first = middle; len = len - half - 1; @@ -879,7 +879,7 @@ class flat_tree RanIt priv_upper_bound(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; @@ -889,12 +889,12 @@ class flat_tree middle = first; middle += half; - if (key_comp_(key, key_extract(*middle))) { + if (key_cmp(key, key_extract(*middle))) { len = half; } else{ first = ++middle; - len = len - half - 1; + len = len - half - 1; } } return first; @@ -904,7 +904,7 @@ class flat_tree std::pair 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; @@ -914,12 +914,12 @@ class flat_tree middle = first; middle += half; - if (key_comp_(key_extract(*middle), key)){ + if (key_cmp(key_extract(*middle), key)){ first = middle; ++first; len = len - half - 1; } - else if (key_comp_(key, key_extract(*middle))){ + else if (key_cmp(key, key_extract(*middle))){ len = half; } else { @@ -1033,7 +1033,7 @@ template struct has_trivial_destructor_after_move > { - static const bool value = has_trivial_destructor::value && has_trivial_destructor::value; + static const bool value = has_trivial_destructor_after_move::value && has_trivial_destructor_after_move::value; }; */ } //namespace boost { diff --git a/include/boost/container/detail/iterators.hpp b/include/boost/container/detail/iterators.hpp index 3e77931..f58c4ce 100644 --- a/include/boost/container/detail/iterators.hpp +++ b/include/boost/container/detail/iterators.hpp @@ -20,7 +20,7 @@ #include "config_begin.hpp" #include -#include +#include #include #include diff --git a/include/boost/container/detail/multiallocation_chain.hpp b/include/boost/container/detail/multiallocation_chain.hpp index 5752083..2e29f9c 100644 --- a/include/boost/container/detail/multiallocation_chain.hpp +++ b/include/boost/container/detail/multiallocation_chain.hpp @@ -19,7 +19,7 @@ #include #include #include -#include +#include namespace boost { namespace container { @@ -50,41 +50,38 @@ class basic_multiallocation_chain typedef typename boost::intrusive:: pointer_traits node_ptr_traits; - static node & build_node(const VoidPointer &p) - { - return *::new (static_cast(static_cast(container_detail::to_raw_pointer(p)))) node; - } + static node & to_node(const VoidPointer &p) + { return *static_cast(static_cast(container_detail::to_raw_pointer(p))); } - static VoidPointer destroy_node(node &n) - { - VoidPointer retptr = node_ptr_traits::pointer_to(n); - n.~node(); - return retptr; - } + static VoidPointer from_node(node &n) + { return node_ptr_traits::pointer_to(n); } - static node_ptr to_node_ptr(VoidPointer p) + 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; } @@ -110,43 +107,54 @@ class basic_multiallocation_chain { slist_impl_.clear(); } iterator insert_after(iterator it, void_pointer m) - { return slist_impl_.insert_after(it, build_node(m)); } + { return slist_impl_.insert_after(it, to_node(m)); } - void push_front(void_pointer m) - { return slist_impl_.push_front(build_node(m)); } + void push_front(const void_pointer &m) + { return slist_impl_.push_front(to_node(m)); } - void push_back(void_pointer m) - { return slist_impl_.push_back(build_node(m)); } + void push_back(const void_pointer &m) + { return slist_impl_.push_back(to_node(m)); } void_pointer pop_front() { node & n = slist_impl_.front(); - void_pointer ret = destroy_node(n); + 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) - { slist_impl_.splice_after(after_this, x.slist_impl_, before_begin_, before_end); } - - 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) + void erase_after(iterator before_b, iterator e, size_type n) + { slist_impl_.erase_after(before_b, e, n); } + + void_pointer incorporate_after(iterator after_this, const void_pointer &b, size_type unit_bytes, size_type num_units) { - slist_impl_.incorporate_after(after_this, to_node_ptr(begin_), to_node_ptr(before_end)); + typedef typename boost::intrusive::pointer_traits 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 begin_, void_pointer before_end, size_type n) - { slist_impl_.incorporate_after(after_this, to_node_ptr(begin_), to_node_ptr(before_end), n); } + 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 extract_data() @@ -170,11 +178,13 @@ struct cast_functor template 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_traits; @@ -193,39 +203,41 @@ class transform_multiallocation_chain 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(other))) + {} transform_multiallocation_chain(BOOST_RV_REF(MultiallocationChain) other) - : holder_(boost::move(other)) + : MultiallocationChain(::boost::move(static_cast(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 + (this->MultiallocationChain::operator=(::boost::move(static_cast(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, pointer begin_, pointer before_end, size_type n) - { holder_.incorporate_after(after_this.base(), begin_, before_end, n); } + 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(holder_.pop_front()); } - + { return cast(this->MultiallocationChain::pop_front()); } +/* bool empty() const { return holder_.empty(); } @@ -246,23 +258,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 extract_data() { - std::pair data(holder_.extract_data()); + std::pair data(this->MultiallocationChain::extract_data()); return std::pair(cast(data.first), cast(data.second)); } - - MultiallocationChain extract_multiallocation_chain() - { - return MultiallocationChain(boost::move(holder_)); - } +/* + MultiallocationChain &extract_multiallocation_chain() + { return holder_; }*/ }; }}} diff --git a/include/boost/container/detail/node_alloc_holder.hpp b/include/boost/container/detail/node_alloc_holder.hpp index 68048bc..7d851c0 100644 --- a/include/boost/container/detail/node_alloc_holder.hpp +++ b/include/boost/container/detail/node_alloc_holder.hpp @@ -21,7 +21,7 @@ #include #include -#include +#include #include #include @@ -30,6 +30,8 @@ #include #include #include +#include +#include #ifndef BOOST_CONTAINER_PERFECT_FORWARDING #include @@ -89,6 +91,7 @@ struct node_alloc_holder typedef typename ICont::const_iterator icont_citerator; typedef allocator_destroyer Destroyer; typedef allocator_traits NodeAllocTraits; + typedef allocator_version_traits AllocVersionTraits; private: BOOST_COPYABLE_AND_MOVABLE(node_alloc_holder) @@ -151,22 +154,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 @@ -235,40 +226,51 @@ struct node_alloc_holder } template - 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; + /* + NodePtr p = this->allocate_one(); + Deallocator node_deallocator(p, this->node_alloc()); + ::boost::container::construct_in_place(this->node_alloc(), container_detail::addressof(p->m_data), it); + node_deallocator.release(); + //This does not throw + typedef typename Node::hook_type hook_type; + ::new(static_cast(container_detail::to_raw_pointer(p))) hook_type; + return (p); + */ + typedef typename NodeAlloc::multiallocation_chain multiallocation_chain; - //Try to allocate memory in a single block - multiallocation_chain mem(this->node_alloc().allocate_individual(n)); - int constructed = 0; - Node *p = 0; - BOOST_TRY{ - for(difference_type i = 0; i < n; ++i, ++beg, --constructed){ - p = container_detail::to_raw_pointer(mem.pop_front()); - //This can throw - constructed = 0; - boost::container::construct_in_place(this->node_alloc(), container_detail::addressof(p->m_data), beg); - ++constructed; - //This does not throw - typedef typename Node::hook_type hook_type; - ::new(static_cast(container_detail::to_raw_pointer(p))) hook_type; - //This can throw in some containers (predicate might throw) - inserter(*p); - } + //Try to allocate memory in a single block + typedef typename multiallocation_chain::iterator multialloc_iterator; + multiallocation_chain mem; + this->node_alloc().allocate_individual(n, mem); + multialloc_iterator itbeg(mem.begin()), itlast(mem.last()); + mem.clear(); + Node *p = 0; + NodeAlloc &nalloc = this->node_alloc(); + BOOST_TRY{ + while(n--){ + p = container_detail::to_raw_pointer(&*itbeg); + ++itbeg; + //This can throw + Deallocator node_deallocator(p, nalloc); + boost::container::construct_in_place(nalloc, container_detail::addressof(p->m_data), beg); + ++beg; + node_deallocator.release(); + //This does not throw + typedef typename Node::hook_type hook_type; + ::new(static_cast(p)) hook_type; + //This can throw in some containers (predicate might throw) + inserter(*p); } - BOOST_CATCH(...){ - if(constructed){ - allocator_traits::destroy(this->node_alloc(), container_detail::to_raw_pointer(p)); - } - this->node_alloc().deallocate_individual(boost::move(mem)); - BOOST_RETHROW - } - BOOST_CATCH_END } - return beg; + BOOST_CATCH(...){ + mem.incorporate_after(mem.last(), &*itbeg, &*itlast, n); + this->node_alloc().deallocate_individual(mem); + BOOST_RETHROW + } + BOOST_CATCH_END } void clear(allocator_v1) @@ -281,7 +283,7 @@ struct node_alloc_holder this->icont().clear_and_dispose(builder); //BOOST_STATIC_ASSERT((::boost::has_move_emulation_enabled::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) @@ -289,8 +291,13 @@ struct node_alloc_holder icont_iterator erase_range(const icont_iterator &first, const icont_iterator &last, allocator_v2) { - allocator_multialloc_chain_node_deallocator 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 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 diff --git a/include/boost/container/detail/node_pool_impl.hpp b/include/boost/container/detail/node_pool_impl.hpp index 63c1278..53e35ac 100644 --- a/include/boost/container/detail/node_pool_impl.hpp +++ b/include/boost/container/detail/node_pool_impl.hpp @@ -26,10 +26,12 @@ #include #include #include +#include #include #include #include //std::unary_function + namespace boost { namespace container { namespace container_detail { @@ -85,19 +87,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 +120,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); } } @@ -275,7 +275,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 +295,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::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 +312,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 diff --git a/include/boost/container/detail/pair.hpp b/include/boost/container/detail/pair.hpp index d5cd65a..3fd63d4 100644 --- a/include/boost/container/detail/pair.hpp +++ b/include/boost/container/detail/pair.hpp @@ -27,7 +27,7 @@ #include //std::pair -#include +#include #include #ifndef BOOST_CONTAINER_PERFECT_FORWARDING diff --git a/include/boost/container/detail/pool_common.hpp b/include/boost/container/detail/pool_common.hpp index 500b912..983d141 100644 --- a/include/boost/container/detail/pool_common.hpp +++ b/include/boost/container/detail/pool_common.hpp @@ -34,7 +34,7 @@ struct node_slist typedef slist_hook_t node_t; typedef typename bi::make_slist - , bi::base_hook >::type node_slist_t; + , bi::cache_last, bi::base_hook >::type node_slist_t; }; template diff --git a/include/boost/container/detail/preprocessor.hpp b/include/boost/container/detail/preprocessor.hpp index 599215f..4e175a8 100644 --- a/include/boost/container/detail/preprocessor.hpp +++ b/include/boost/container/detail/preprocessor.hpp @@ -17,6 +17,7 @@ #include #include +#include #ifdef BOOST_CONTAINER_PERFECT_FORWARDING //#error "This file is not needed when perfect forwarding is available" @@ -38,6 +39,7 @@ #include #include #include +#include #define BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS 10 @@ -97,7 +99,7 @@ const BOOST_PP_CAT(Q, n) & BOOST_PP_CAT(q, n) \ template struct ref_holder { - ref_holder(T &t) + explicit ref_holder(T &t) : t_(t) {} T &t_; @@ -107,7 +109,7 @@ const BOOST_PP_CAT(Q, n) & BOOST_PP_CAT(q, n) \ template struct ref_holder { - ref_holder(const T &t) + explicit ref_holder(const T &t) : t_(t) {} const T &t_; @@ -117,7 +119,7 @@ const BOOST_PP_CAT(Q, n) & BOOST_PP_CAT(q, n) \ template struct ref_holder { - ref_holder(const T &t) + explicit ref_holder(const T &t) : t_(t) {} const T &t_; @@ -127,7 +129,7 @@ const BOOST_PP_CAT(Q, n) & BOOST_PP_CAT(q, n) \ template struct ref_holder { - ref_holder(T &&t) + explicit ref_holder(T &&t) : t_(t) {} T &t_; @@ -137,10 +139,10 @@ const BOOST_PP_CAT(Q, n) & BOOST_PP_CAT(q, n) \ template struct ref_holder { - ref_holder(T &&t) - : t(t) + explicit ref_holder(T &&t) + : t_(t) {} - T &t; + T &t_; T && get() { return ::boost::move(t_); } }; diff --git a/include/boost/container/detail/tree.hpp b/include/boost/container/detail/tree.hpp index 12342a8..9cb3c9f 100644 --- a/include/boost/container/detail/tree.hpp +++ b/include/boost/container/detail/tree.hpp @@ -15,7 +15,7 @@ #include #include -#include +#include #include #include #include @@ -28,6 +28,7 @@ #include #include #include +#include #ifndef BOOST_CONTAINER_PERFECT_FORWARDING #include #endif @@ -247,19 +248,20 @@ class rbtree { if(NodePtr p = m_icont.unlink_leftmost_without_rebalance()){ //First recycle a node (this can't throw) - try{ + BOOST_TRY{ //This can throw p->do_assign(other.m_data); return p; } - catch(...){ + 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); } - throw; + BOOST_RETHROW } + BOOST_CATCH_END } else{ return m_holder.create_node(other.m_data); @@ -284,19 +286,20 @@ class rbtree { if(NodePtr p = m_icont.unlink_leftmost_without_rebalance()){ //First recycle a node (this can't throw) - try{ + BOOST_TRY{ //This can throw p->do_move_assign(const_cast(other).m_data); return p; } - catch(...){ + 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); } - throw; + BOOST_RETHROW } + BOOST_CATCH_END } else{ return m_holder.create_node(other.m_data); @@ -1121,7 +1124,7 @@ class C, class A> struct has_trivial_destructor_after_move > { - static const bool value = has_trivial_destructor::value && has_trivial_destructor::value; + static const bool value = has_trivial_destructor_after_move::value && has_trivial_destructor_after_move::value; }; */ } //namespace boost { diff --git a/include/boost/container/detail/type_traits.hpp b/include/boost/container/detail/type_traits.hpp index c1de447..5020ee9 100644 --- a/include/boost/container/detail/type_traits.hpp +++ b/include/boost/container/detail/type_traits.hpp @@ -21,7 +21,7 @@ #include "config_begin.hpp" -#include +#include namespace boost { namespace container { diff --git a/include/boost/container/detail/utilities.hpp b/include/boost/container/detail/utilities.hpp index ece9a2e..5c294e1 100644 --- a/include/boost/container/detail/utilities.hpp +++ b/include/boost/container/detail/utilities.hpp @@ -18,11 +18,14 @@ #include #include #include -#include +#include +#include #include #include #include +#include #include +#include namespace boost { namespace container { @@ -123,16 +126,6 @@ struct ct_rounded_size enum { value = ((OrigSize-1)/RoundTo+1)*RoundTo }; }; -template -struct move_const_ref_type - : if_c -// < ::boost::is_fundamental::value || ::boost::is_pointer::value || ::boost::is_member_pointer::value || ::boost::is_enum::value - < !::boost::is_class::value - ,const T & - ,BOOST_CATCH_CONST_RLVALUE(T) - > -{}; - } //namespace container_detail { ////////////////////////////////////////////////////////////////////////////// @@ -154,13 +147,95 @@ template typename F> // F models ForwardIterator F uninitialized_move_alloc(A &a, I f, I l, F r) { - while (f != l) { - allocator_traits::construct(a, container_detail::to_raw_pointer(&*r), boost::move(*f)); - ++f; ++r; + F back = r; + BOOST_TRY{ + while (f != l) { + allocator_traits::construct(a, container_detail::to_raw_pointer(&*r), boost::move(*f)); + ++f; ++r; + } } + BOOST_CATCH(...){ + for (; back != r; ++back){ + allocator_traits::destroy(a, container_detail::to_raw_pointer(&*back)); + } + BOOST_RETHROW; + } + BOOST_CATCH_END return r; } +////////////////////////////////////////////////////////////////////////////// +// +// uninitialized_move_alloc_n +// +////////////////////////////////////////////////////////////////////////////// + +//! Effects: +//! \code +//! for (; n--; ++result, ++first) +//! allocator_traits::construct(a, &*result, boost::move(*first)); +//! \endcode +//! +//! Returns: result +template + // F models ForwardIterator +F uninitialized_move_alloc_n(A &a, I f, typename std::iterator_traits::difference_type n, F r) +{ + F back = r; + BOOST_TRY{ + while (n--) { + allocator_traits::construct(a, container_detail::to_raw_pointer(&*r), boost::move(*f)); + ++f; ++r; + } + } + BOOST_CATCH(...){ + for (; back != r; ++back){ + allocator_traits::destroy(a, container_detail::to_raw_pointer(&*back)); + } + BOOST_RETHROW; + } + BOOST_CATCH_END + return r; +} + +////////////////////////////////////////////////////////////////////////////// +// +// uninitialized_move_alloc_n_source +// +////////////////////////////////////////////////////////////////////////////// + +//! Effects: +//! \code +//! for (; n--; ++result, ++first) +//! allocator_traits::construct(a, &*result, boost::move(*first)); +//! \endcode +//! +//! Returns: first (after incremented) +template + // F models ForwardIterator +I uninitialized_move_alloc_n_source(A &a, I f, typename std::iterator_traits::difference_type n, F r) +{ + F back = r; + BOOST_TRY{ + while (n--) { + allocator_traits::construct(a, container_detail::to_raw_pointer(&*r), boost::move(*f)); + ++f; ++r; + } + } + BOOST_CATCH(...){ + for (; back != r; ++back){ + allocator_traits::destroy(a, container_detail::to_raw_pointer(&*back)); + } + BOOST_RETHROW; + } + BOOST_CATCH_END + return f; +} + ////////////////////////////////////////////////////////////////////////////// // // uninitialized_copy_alloc @@ -180,13 +255,95 @@ template typename F> // F models ForwardIterator F uninitialized_copy_alloc(A &a, I f, I l, F r) { - while (f != l) { - allocator_traits::construct(a, container_detail::to_raw_pointer(&*r), *f); - ++f; ++r; + F back = r; + BOOST_TRY{ + while (f != l) { + allocator_traits::construct(a, container_detail::to_raw_pointer(&*r), *f); + ++f; ++r; + } } + BOOST_CATCH(...){ + for (; back != r; ++back){ + allocator_traits::destroy(a, container_detail::to_raw_pointer(&*back)); + } + BOOST_RETHROW; + } + BOOST_CATCH_END return r; } +////////////////////////////////////////////////////////////////////////////// +// +// uninitialized_copy_alloc_n +// +////////////////////////////////////////////////////////////////////////////// + +//! Effects: +//! \code +//! for (; n--; ++result, ++first) +//! allocator_traits::construct(a, &*result, *first); +//! \endcode +//! +//! Returns: result +template + // F models ForwardIterator +F uninitialized_copy_alloc_n(A &a, I f, typename std::iterator_traits::difference_type n, F r) +{ + F back = r; + BOOST_TRY{ + while (n--) { + allocator_traits::construct(a, container_detail::to_raw_pointer(&*r), *f); + ++f; ++r; + } + } + BOOST_CATCH(...){ + for (; back != r; ++back){ + allocator_traits::destroy(a, container_detail::to_raw_pointer(&*back)); + } + BOOST_RETHROW; + } + BOOST_CATCH_END + return r; +} + +////////////////////////////////////////////////////////////////////////////// +// +// uninitialized_copy_alloc_n_source +// +////////////////////////////////////////////////////////////////////////////// + +//! Effects: +//! \code +//! for (; n--; ++result, ++first) +//! allocator_traits::construct(a, &*result, *first); +//! \endcode +//! +//! Returns: first (after incremented) +template + // F models ForwardIterator +I uninitialized_copy_alloc_n_source(A &a, I f, typename std::iterator_traits::difference_type n, F r) +{ + F back = r; + BOOST_TRY{ + while (n--) { + allocator_traits::construct(a, container_detail::to_raw_pointer(&*r), *f); + ++f; ++r; + } + } + BOOST_CATCH(...){ + for (; back != r; ++back){ + allocator_traits::destroy(a, container_detail::to_raw_pointer(&*back)); + } + BOOST_RETHROW; + } + BOOST_CATCH_END + return f; +} + ////////////////////////////////////////////////////////////////////////////// // // uninitialized_copy_alloc @@ -206,10 +363,20 @@ template typename T> void uninitialized_fill_alloc(A &a, F f, F l, const T &t) { - while (f != l) { - allocator_traits::construct(a, container_detail::to_raw_pointer(&*f), t); - ++f; + F back = f; + BOOST_TRY{ + while (f != l) { + allocator_traits::construct(a, container_detail::to_raw_pointer(&*f), t); + ++f; + } } + BOOST_CATCH(...){ + for (; back != l; ++back){ + allocator_traits::destroy(a, container_detail::to_raw_pointer(&*back)); + } + BOOST_RETHROW; + } + BOOST_CATCH_END } ////////////////////////////////////////////////////////////////////////////// @@ -242,6 +409,168 @@ F uninitialized_copy_or_move_alloc return ::boost::container::uninitialized_copy_alloc(a, f, l, r); } +////////////////////////////////////////////////////////////////////////////// +// +// uninitialized_copy_or_move_alloc_n +// +////////////////////////////////////////////////////////////////////////////// + +template + // F models ForwardIterator +F uninitialized_copy_or_move_alloc_n + (A &a, I f, typename std::iterator_traits::difference_type n, F r + ,typename boost::container::container_detail::enable_if + < boost::move_detail::is_move_iterator >::type* = 0) +{ + return ::boost::container::uninitialized_move_alloc_n(a, f, n, r); +} + +template + // F models ForwardIterator +F uninitialized_copy_or_move_alloc_n + (A &a, I f, typename std::iterator_traits::difference_type n, F r + ,typename boost::container::container_detail::disable_if + < boost::move_detail::is_move_iterator >::type* = 0) +{ + return ::boost::container::uninitialized_copy_alloc_n(a, f, n, r); +} + + +////////////////////////////////////////////////////////////////////////////// +// +// uninitialized_copy_or_move_alloc_n_source +// +////////////////////////////////////////////////////////////////////////////// + +template + // F models ForwardIterator +I uninitialized_copy_or_move_alloc_n_source + (A &a, I f, typename std::iterator_traits::difference_type n, F r + ,typename boost::container::container_detail::enable_if + < boost::move_detail::is_move_iterator >::type* = 0) +{ + return ::boost::container::uninitialized_move_alloc_n_source(a, f, n, r); +} + +template + // F models ForwardIterator +I uninitialized_copy_or_move_alloc_n_source + (A &a, I f, typename std::iterator_traits::difference_type n, F r + ,typename boost::container::container_detail::disable_if + < boost::move_detail::is_move_iterator >::type* = 0) +{ + return ::boost::container::uninitialized_copy_alloc_n_source(a, f, n, r); +} + +////////////////////////////////////////////////////////////////////////////// +// +// copy_or_move +// +////////////////////////////////////////////////////////////////////////////// + +template + // F models ForwardIterator +inline F copy_or_move(I f, I l, F r + ,typename boost::container::container_detail::enable_if + < boost::move_detail::is_move_iterator >::type* = 0) +{ + while (f != l) { + *r = ::boost::move(*f); + ++f; ++r; + } + return r; +} + +template + // F models ForwardIterator +inline F copy_or_move(I f, I l, F r + ,typename boost::container::container_detail::disable_if + < boost::move_detail::is_move_iterator >::type* = 0) +{ + while (f != l) { + *r = *f; + ++f; ++r; + } + return r; +} + +////////////////////////////////////////////////////////////////////////////// +// +// copy_or_move_n +// +////////////////////////////////////////////////////////////////////////////// + +template + // F models ForwardIterator +inline F copy_or_move_n(I f, typename std::iterator_traits::difference_type n, F r + ,typename boost::container::container_detail::enable_if + < boost::move_detail::is_move_iterator >::type* = 0) +{ + while (n--) { + *r = ::boost::move(*f); + ++f; ++r; + } + return r; +} + +template + // F models ForwardIterator +inline F copy_or_move_n(I f, typename std::iterator_traits::difference_type n, F r + ,typename boost::container::container_detail::disable_if + < boost::move_detail::is_move_iterator >::type* = 0) +{ + while (n--) { + *r = *f; + ++f; ++r; + } + return r; +} + +////////////////////////////////////////////////////////////////////////////// +// +// copy_or_move_n_source +// +////////////////////////////////////////////////////////////////////////////// + +template + // F models ForwardIterator +inline I copy_or_move_n_source(I f, typename std::iterator_traits::difference_type n, F r + ,typename boost::container::container_detail::enable_if + < boost::move_detail::is_move_iterator >::type* = 0) +{ + while (n--) { + *r = ::boost::move(*f); + ++f; ++r; + } + return f; +} + +template + // F models ForwardIterator +inline I copy_or_move_n_source(I f, typename std::iterator_traits::difference_type n, F r + ,typename boost::container::container_detail::disable_if + < boost::move_detail::is_move_iterator >::type* = 0) +{ + while (n--) { + *r = *f; + ++f; ++r; + } + return f; +} } //namespace container { } //namespace boost { diff --git a/include/boost/container/detail/workaround.hpp b/include/boost/container/detail/workaround.hpp index 317bbb2..a0820a1 100644 --- a/include/boost/container/detail/workaround.hpp +++ b/include/boost/container/detail/workaround.hpp @@ -18,8 +18,12 @@ #define BOOST_CONTAINER_PERFECT_FORWARDING #endif -#if defined(BOOST_NO_CXX11_NOEXCEPT) - #define BOOST_CONTAINER_NOEXCEPT +#if defined(BOOST_NO_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 diff --git a/include/boost/container/flat_map.hpp b/include/boost/container/flat_map.hpp index 4fb9e07..2dd2210 100644 --- a/include/boost/container/flat_map.hpp +++ b/include/boost/container/flat_map.hpp @@ -27,8 +27,8 @@ #include #include #include -#include -#include +#include +#include namespace boost { namespace container { @@ -251,7 +251,7 @@ class flat_map //! was passed to the object's constructor. //! //! Complexity: Constant. - allocator_type get_allocator() const + allocator_type get_allocator() const BOOST_CONTAINER_NOEXCEPT { return container_detail::force_copy(m_flat_tree.get_allocator()); } //! Effects: Returns a reference to the internal allocator. @@ -261,7 +261,7 @@ class flat_map //! Complexity: Constant. //! //! Note: Non-standard extension. - stored_allocator_type &get_stored_allocator() + stored_allocator_type &get_stored_allocator() BOOST_CONTAINER_NOEXCEPT { return container_detail::force(m_flat_tree.get_stored_allocator()); } //! Effects: Returns a reference to the internal allocator. @@ -271,7 +271,7 @@ class flat_map //! Complexity: Constant. //! //! Note: Non-standard extension. - const stored_allocator_type &get_stored_allocator() const + const stored_allocator_type &get_stored_allocator() const BOOST_CONTAINER_NOEXCEPT { return container_detail::force(m_flat_tree.get_stored_allocator()); } ////////////////////////////////////////////// @@ -285,7 +285,7 @@ class flat_map //! Throws: Nothing. //! //! Complexity: Constant. - iterator begin() + iterator begin() BOOST_CONTAINER_NOEXCEPT { return container_detail::force_copy(m_flat_tree.begin()); } //! Effects: Returns a const_iterator to the first element contained in the container. @@ -293,7 +293,7 @@ class flat_map //! Throws: Nothing. //! //! Complexity: Constant. - const_iterator begin() const + const_iterator begin() const BOOST_CONTAINER_NOEXCEPT { return container_detail::force_copy(m_flat_tree.begin()); } //! Effects: Returns an iterator to the end of the container. @@ -301,7 +301,7 @@ class flat_map //! Throws: Nothing. //! //! Complexity: Constant. - iterator end() + iterator end() BOOST_CONTAINER_NOEXCEPT { return container_detail::force_copy(m_flat_tree.end()); } //! Effects: Returns a const_iterator to the end of the container. @@ -309,7 +309,7 @@ class flat_map //! Throws: Nothing. //! //! Complexity: Constant. - const_iterator end() const + const_iterator end() const BOOST_CONTAINER_NOEXCEPT { return container_detail::force_copy(m_flat_tree.end()); } //! Effects: Returns a reverse_iterator pointing to the beginning @@ -318,7 +318,7 @@ class flat_map //! Throws: Nothing. //! //! Complexity: Constant. - reverse_iterator rbegin() + reverse_iterator rbegin() BOOST_CONTAINER_NOEXCEPT { return container_detail::force_copy(m_flat_tree.rbegin()); } //! Effects: Returns a const_reverse_iterator pointing to the beginning @@ -327,7 +327,7 @@ class flat_map //! Throws: Nothing. //! //! Complexity: Constant. - const_reverse_iterator rbegin() const + const_reverse_iterator rbegin() const BOOST_CONTAINER_NOEXCEPT { return container_detail::force_copy(m_flat_tree.rbegin()); } //! Effects: Returns a reverse_iterator pointing to the end @@ -336,7 +336,7 @@ class flat_map //! Throws: Nothing. //! //! Complexity: Constant. - reverse_iterator rend() + reverse_iterator rend() BOOST_CONTAINER_NOEXCEPT { return container_detail::force_copy(m_flat_tree.rend()); } //! Effects: Returns a const_reverse_iterator pointing to the end @@ -345,7 +345,7 @@ class flat_map //! Throws: Nothing. //! //! Complexity: Constant. - const_reverse_iterator rend() const + const_reverse_iterator rend() const BOOST_CONTAINER_NOEXCEPT { return container_detail::force_copy(m_flat_tree.rend()); } //! Effects: Returns a const_iterator to the first element contained in the container. @@ -353,7 +353,7 @@ class flat_map //! Throws: Nothing. //! //! Complexity: Constant. - const_iterator cbegin() const + const_iterator cbegin() const BOOST_CONTAINER_NOEXCEPT { return container_detail::force_copy(m_flat_tree.cbegin()); } //! Effects: Returns a const_iterator to the end of the container. @@ -361,7 +361,7 @@ class flat_map //! Throws: Nothing. //! //! Complexity: Constant. - const_iterator cend() const + const_iterator cend() const BOOST_CONTAINER_NOEXCEPT { return container_detail::force_copy(m_flat_tree.cend()); } //! Effects: Returns a const_reverse_iterator pointing to the beginning @@ -370,7 +370,7 @@ class flat_map //! Throws: Nothing. //! //! Complexity: Constant. - const_reverse_iterator crbegin() const + const_reverse_iterator crbegin() const BOOST_CONTAINER_NOEXCEPT { return container_detail::force_copy(m_flat_tree.crbegin()); } //! Effects: Returns a const_reverse_iterator pointing to the end @@ -379,7 +379,7 @@ class flat_map //! Throws: Nothing. //! //! Complexity: Constant. - const_reverse_iterator crend() const + const_reverse_iterator crend() const BOOST_CONTAINER_NOEXCEPT { return container_detail::force_copy(m_flat_tree.crend()); } ////////////////////////////////////////////// @@ -393,7 +393,7 @@ class flat_map //! Throws: Nothing. //! //! Complexity: Constant. - bool empty() const + bool empty() const BOOST_CONTAINER_NOEXCEPT { return m_flat_tree.empty(); } //! Effects: Returns the number of the elements contained in the container. @@ -401,7 +401,7 @@ class flat_map //! Throws: Nothing. //! //! Complexity: Constant. - size_type size() const + size_type size() const BOOST_CONTAINER_NOEXCEPT { return m_flat_tree.size(); } //! Effects: Returns the largest possible size of the container. @@ -409,7 +409,7 @@ class flat_map //! Throws: Nothing. //! //! Complexity: Constant. - size_type max_size() const + size_type max_size() const BOOST_CONTAINER_NOEXCEPT { return m_flat_tree.max_size(); } //! Effects: Number of elements for which memory has been allocated. @@ -418,7 +418,7 @@ class flat_map //! Throws: Nothing. //! //! Complexity: Constant. - size_type capacity() const + size_type capacity() const BOOST_CONTAINER_NOEXCEPT { return m_flat_tree.capacity(); } //! Effects: If n is less than or equal to capacity(), this call has no @@ -428,10 +428,10 @@ class flat_map //! //! Throws: If memory allocation allocation throws or T's copy constructor throws. //! - //! Note: If capacity() is less than "count", iterators and references to + //! Note: If capacity() is less than "cnt", iterators and references to //! to values might be invalidated. - void reserve(size_type count_) - { m_flat_tree.reserve(count_); } + void reserve(size_type cnt) + { m_flat_tree.reserve(cnt); } //! Effects: Tries to deallocate the excess of memory created // with previous allocations. The size of the vector is unchanged @@ -740,7 +740,7 @@ class flat_map //! Postcondition: size() == 0. //! //! Complexity: linear in size(). - void clear() + void clear() BOOST_CONTAINER_NOEXCEPT { m_flat_tree.clear(); } ////////////////////////////////////////////// @@ -900,15 +900,15 @@ inline void swap(flat_map& x, /// @cond } //namespace container { -/* + //!has_trivial_destructor_after_move<> == true_type //!specialization for optimizations template struct has_trivial_destructor_after_move > { - static const bool value = has_trivial_destructor::value && has_trivial_destructor::value; + static const bool value = has_trivial_destructor_after_move::value && has_trivial_destructor_after_move::value; }; -*/ + namespace container { // Forward declaration of operators < and ==, needed for friend declaration. @@ -1099,7 +1099,7 @@ class flat_multimap //! was passed to the object's constructor. //! //! Complexity: Constant. - allocator_type get_allocator() const + allocator_type get_allocator() const BOOST_CONTAINER_NOEXCEPT { return container_detail::force_copy(m_flat_tree.get_allocator()); } //! Effects: Returns a reference to the internal allocator. @@ -1109,7 +1109,7 @@ class flat_multimap //! Complexity: Constant. //! //! Note: Non-standard extension. - stored_allocator_type &get_stored_allocator() + stored_allocator_type &get_stored_allocator() BOOST_CONTAINER_NOEXCEPT { return container_detail::force(m_flat_tree.get_stored_allocator()); } //! Effects: Returns a reference to the internal allocator. @@ -1119,7 +1119,7 @@ class flat_multimap //! Complexity: Constant. //! //! Note: Non-standard extension. - const stored_allocator_type &get_stored_allocator() const + const stored_allocator_type &get_stored_allocator() const BOOST_CONTAINER_NOEXCEPT { return container_detail::force(m_flat_tree.get_stored_allocator()); } ////////////////////////////////////////////// @@ -1133,7 +1133,7 @@ class flat_multimap //! Throws: Nothing. //! //! Complexity: Constant. - iterator begin() + iterator begin() BOOST_CONTAINER_NOEXCEPT { return container_detail::force_copy(m_flat_tree.begin()); } //! Effects: Returns a const_iterator to the first element contained in the container. @@ -1141,7 +1141,7 @@ class flat_multimap //! Throws: Nothing. //! //! Complexity: Constant. - const_iterator begin() const + const_iterator begin() const BOOST_CONTAINER_NOEXCEPT { return container_detail::force_copy(m_flat_tree.begin()); } //! Effects: Returns an iterator to the end of the container. @@ -1149,7 +1149,7 @@ class flat_multimap //! Throws: Nothing. //! //! Complexity: Constant. - iterator end() + iterator end() BOOST_CONTAINER_NOEXCEPT { return container_detail::force_copy(m_flat_tree.end()); } //! Effects: Returns a const_iterator to the end of the container. @@ -1157,7 +1157,7 @@ class flat_multimap //! Throws: Nothing. //! //! Complexity: Constant. - const_iterator end() const + const_iterator end() const BOOST_CONTAINER_NOEXCEPT { return container_detail::force_copy(m_flat_tree.end()); } //! Effects: Returns a reverse_iterator pointing to the beginning @@ -1166,7 +1166,7 @@ class flat_multimap //! Throws: Nothing. //! //! Complexity: Constant. - reverse_iterator rbegin() + reverse_iterator rbegin() BOOST_CONTAINER_NOEXCEPT { return container_detail::force_copy(m_flat_tree.rbegin()); } //! Effects: Returns a const_reverse_iterator pointing to the beginning @@ -1175,7 +1175,7 @@ class flat_multimap //! Throws: Nothing. //! //! Complexity: Constant. - const_reverse_iterator rbegin() const + const_reverse_iterator rbegin() const BOOST_CONTAINER_NOEXCEPT { return container_detail::force_copy(m_flat_tree.rbegin()); } //! Effects: Returns a reverse_iterator pointing to the end @@ -1184,7 +1184,7 @@ class flat_multimap //! Throws: Nothing. //! //! Complexity: Constant. - reverse_iterator rend() + reverse_iterator rend() BOOST_CONTAINER_NOEXCEPT { return container_detail::force_copy(m_flat_tree.rend()); } //! Effects: Returns a const_reverse_iterator pointing to the end @@ -1193,7 +1193,7 @@ class flat_multimap //! Throws: Nothing. //! //! Complexity: Constant. - const_reverse_iterator rend() const + const_reverse_iterator rend() const BOOST_CONTAINER_NOEXCEPT { return container_detail::force_copy(m_flat_tree.rend()); } //! Effects: Returns a const_iterator to the first element contained in the container. @@ -1201,7 +1201,7 @@ class flat_multimap //! Throws: Nothing. //! //! Complexity: Constant. - const_iterator cbegin() const + const_iterator cbegin() const BOOST_CONTAINER_NOEXCEPT { return container_detail::force_copy(m_flat_tree.cbegin()); } //! Effects: Returns a const_iterator to the end of the container. @@ -1209,7 +1209,7 @@ class flat_multimap //! Throws: Nothing. //! //! Complexity: Constant. - const_iterator cend() const + const_iterator cend() const BOOST_CONTAINER_NOEXCEPT { return container_detail::force_copy(m_flat_tree.cend()); } //! Effects: Returns a const_reverse_iterator pointing to the beginning @@ -1218,7 +1218,7 @@ class flat_multimap //! Throws: Nothing. //! //! Complexity: Constant. - const_reverse_iterator crbegin() const + const_reverse_iterator crbegin() const BOOST_CONTAINER_NOEXCEPT { return container_detail::force_copy(m_flat_tree.crbegin()); } //! Effects: Returns a const_reverse_iterator pointing to the end @@ -1227,7 +1227,7 @@ class flat_multimap //! Throws: Nothing. //! //! Complexity: Constant. - const_reverse_iterator crend() const + const_reverse_iterator crend() const BOOST_CONTAINER_NOEXCEPT { return container_detail::force_copy(m_flat_tree.crend()); } ////////////////////////////////////////////// @@ -1241,7 +1241,7 @@ class flat_multimap //! Throws: Nothing. //! //! Complexity: Constant. - bool empty() const + bool empty() const BOOST_CONTAINER_NOEXCEPT { return m_flat_tree.empty(); } //! Effects: Returns the number of the elements contained in the container. @@ -1249,7 +1249,7 @@ class flat_multimap //! Throws: Nothing. //! //! Complexity: Constant. - size_type size() const + size_type size() const BOOST_CONTAINER_NOEXCEPT { return m_flat_tree.size(); } //! Effects: Returns the largest possible size of the container. @@ -1257,7 +1257,7 @@ class flat_multimap //! Throws: Nothing. //! //! Complexity: Constant. - size_type max_size() const + size_type max_size() const BOOST_CONTAINER_NOEXCEPT { return m_flat_tree.max_size(); } //! Effects: Number of elements for which memory has been allocated. @@ -1266,7 +1266,7 @@ class flat_multimap //! Throws: Nothing. //! //! Complexity: Constant. - size_type capacity() const + size_type capacity() const BOOST_CONTAINER_NOEXCEPT { return m_flat_tree.capacity(); } //! Effects: If n is less than or equal to capacity(), this call has no @@ -1276,10 +1276,10 @@ class flat_multimap //! //! Throws: If memory allocation allocation throws or T's copy constructor throws. //! - //! Note: If capacity() is less than "count", iterators and references to + //! Note: If capacity() is less than "cnt", iterators and references to //! to values might be invalidated. - void reserve(size_type count_) - { m_flat_tree.reserve(count_); } + void reserve(size_type cnt) + { m_flat_tree.reserve(cnt); } //! Effects: Tries to deallocate the excess of memory created // with previous allocations. The size of the vector is unchanged @@ -1516,7 +1516,7 @@ class flat_multimap //! Postcondition: size() == 0. //! //! Complexity: linear in size(). - void clear() + void clear() BOOST_CONTAINER_NOEXCEPT { m_flat_tree.clear(); } ////////////////////////////////////////////// @@ -1655,15 +1655,15 @@ inline void swap(flat_multimap& x, flat_multimap == true_type //!specialization for optimizations template struct has_trivial_destructor_after_move< boost::container::flat_multimap > { - static const bool value = has_trivial_destructor::value && has_trivial_destructor::value; + static const bool value = has_trivial_destructor_after_move::value && has_trivial_destructor_after_move::value; }; -*/ + } //namespace boost { /// @endcond diff --git a/include/boost/container/flat_set.hpp b/include/boost/container/flat_set.hpp index b6266e6..82bdea8 100644 --- a/include/boost/container/flat_set.hpp +++ b/include/boost/container/flat_set.hpp @@ -25,8 +25,8 @@ #include #include #include -#include -#include +#include +#include namespace boost { namespace container { @@ -197,7 +197,7 @@ class flat_set //! was passed to the object's constructor. //! //! Complexity: Constant. - allocator_type get_allocator() const + allocator_type get_allocator() const BOOST_CONTAINER_NOEXCEPT { return m_flat_tree.get_allocator(); } //! Effects: Returns a reference to the internal allocator. @@ -207,7 +207,7 @@ class flat_set //! Complexity: Constant. //! //! Note: Non-standard extension. - stored_allocator_type &get_stored_allocator() + stored_allocator_type &get_stored_allocator() BOOST_CONTAINER_NOEXCEPT { return m_flat_tree.get_stored_allocator(); } //! Effects: Returns a reference to the internal allocator. @@ -217,7 +217,7 @@ class flat_set //! Complexity: Constant. //! //! Note: Non-standard extension. - const stored_allocator_type &get_stored_allocator() const + const stored_allocator_type &get_stored_allocator() const BOOST_CONTAINER_NOEXCEPT { return m_flat_tree.get_stored_allocator(); } ////////////////////////////////////////////// @@ -231,7 +231,7 @@ class flat_set //! Throws: Nothing. //! //! Complexity: Constant. - iterator begin() + iterator begin() BOOST_CONTAINER_NOEXCEPT { return m_flat_tree.begin(); } //! Effects: Returns a const_iterator to the first element contained in the container. @@ -239,7 +239,7 @@ class flat_set //! Throws: Nothing. //! //! Complexity: Constant. - const_iterator begin() const + const_iterator begin() const BOOST_CONTAINER_NOEXCEPT { return m_flat_tree.begin(); } //! Effects: Returns an iterator to the end of the container. @@ -247,7 +247,7 @@ class flat_set //! Throws: Nothing. //! //! Complexity: Constant. - iterator end() + iterator end() BOOST_CONTAINER_NOEXCEPT { return m_flat_tree.end(); } //! Effects: Returns a const_iterator to the end of the container. @@ -255,7 +255,7 @@ class flat_set //! Throws: Nothing. //! //! Complexity: Constant. - const_iterator end() const + const_iterator end() const BOOST_CONTAINER_NOEXCEPT { return m_flat_tree.end(); } //! Effects: Returns a reverse_iterator pointing to the beginning @@ -264,7 +264,7 @@ class flat_set //! Throws: Nothing. //! //! Complexity: Constant. - reverse_iterator rbegin() + reverse_iterator rbegin() BOOST_CONTAINER_NOEXCEPT { return m_flat_tree.rbegin(); } //! Effects: Returns a const_reverse_iterator pointing to the beginning @@ -273,7 +273,7 @@ class flat_set //! Throws: Nothing. //! //! Complexity: Constant. - const_reverse_iterator rbegin() const + const_reverse_iterator rbegin() const BOOST_CONTAINER_NOEXCEPT { return m_flat_tree.rbegin(); } //! Effects: Returns a reverse_iterator pointing to the end @@ -282,7 +282,7 @@ class flat_set //! Throws: Nothing. //! //! Complexity: Constant. - reverse_iterator rend() + reverse_iterator rend() BOOST_CONTAINER_NOEXCEPT { return m_flat_tree.rend(); } //! Effects: Returns a const_reverse_iterator pointing to the end @@ -291,7 +291,7 @@ class flat_set //! Throws: Nothing. //! //! Complexity: Constant. - const_reverse_iterator rend() const + const_reverse_iterator rend() const BOOST_CONTAINER_NOEXCEPT { return m_flat_tree.rend(); } //! Effects: Returns a const_iterator to the first element contained in the container. @@ -299,7 +299,7 @@ class flat_set //! Throws: Nothing. //! //! Complexity: Constant. - const_iterator cbegin() const + const_iterator cbegin() const BOOST_CONTAINER_NOEXCEPT { return m_flat_tree.cbegin(); } //! Effects: Returns a const_iterator to the end of the container. @@ -307,7 +307,7 @@ class flat_set //! Throws: Nothing. //! //! Complexity: Constant. - const_iterator cend() const + const_iterator cend() const BOOST_CONTAINER_NOEXCEPT { return m_flat_tree.cend(); } //! Effects: Returns a const_reverse_iterator pointing to the beginning @@ -316,7 +316,7 @@ class flat_set //! Throws: Nothing. //! //! Complexity: Constant. - const_reverse_iterator crbegin() const + const_reverse_iterator crbegin() const BOOST_CONTAINER_NOEXCEPT { return m_flat_tree.crbegin(); } //! Effects: Returns a const_reverse_iterator pointing to the end @@ -325,7 +325,7 @@ class flat_set //! Throws: Nothing. //! //! Complexity: Constant. - const_reverse_iterator crend() const + const_reverse_iterator crend() const BOOST_CONTAINER_NOEXCEPT { return m_flat_tree.crend(); } @@ -340,7 +340,7 @@ class flat_set //! Throws: Nothing. //! //! Complexity: Constant. - bool empty() const + bool empty() const BOOST_CONTAINER_NOEXCEPT { return m_flat_tree.empty(); } //! Effects: Returns the number of the elements contained in the container. @@ -348,7 +348,7 @@ class flat_set //! Throws: Nothing. //! //! Complexity: Constant. - size_type size() const + size_type size() const BOOST_CONTAINER_NOEXCEPT { return m_flat_tree.size(); } //! Effects: Returns the largest possible size of the container. @@ -356,7 +356,7 @@ class flat_set //! Throws: Nothing. //! //! Complexity: Constant. - size_type max_size() const + size_type max_size() const BOOST_CONTAINER_NOEXCEPT { return m_flat_tree.max_size(); } //! Effects: Number of elements for which memory has been allocated. @@ -365,7 +365,7 @@ class flat_set //! Throws: Nothing. //! //! Complexity: Constant. - size_type capacity() const + size_type capacity() const BOOST_CONTAINER_NOEXCEPT { return m_flat_tree.capacity(); } //! Effects: If n is less than or equal to capacity(), this call has no @@ -375,10 +375,10 @@ class flat_set //! //! Throws: If memory allocation allocation throws or Key's copy constructor throws. //! - //! Note: If capacity() is less than "count", iterators and references to + //! Note: If capacity() is less than "cnt", iterators and references to //! to values might be invalidated. - void reserve(size_type count_) - { m_flat_tree.reserve(count_); } + void reserve(size_type cnt) + { m_flat_tree.reserve(cnt); } //! Effects: Tries to deallocate the excess of memory created // with previous allocations. The size of the vector is unchanged @@ -582,7 +582,7 @@ class flat_set //! Postcondition: size() == 0. //! //! Complexity: linear in size(). - void clear() + void clear() BOOST_CONTAINER_NOEXCEPT { m_flat_tree.clear(); } ////////////////////////////////////////////// @@ -726,15 +726,15 @@ inline void swap(flat_set& x, flat_set == true_type //!specialization for optimizations template struct has_trivial_destructor_after_move > { - static const bool value = has_trivial_destructor::value &&has_trivial_destructor::value; + static const bool value = has_trivial_destructor_after_move::value &&has_trivial_destructor_after_move::value; }; -*/ + namespace container { // Forward declaration of operators < and ==, needed for friend declaration. @@ -884,7 +884,7 @@ class flat_multiset //! was passed to the object's constructor. //! //! Complexity: Constant. - allocator_type get_allocator() const + allocator_type get_allocator() const BOOST_CONTAINER_NOEXCEPT { return m_flat_tree.get_allocator(); } //! Effects: Returns a reference to the internal allocator. @@ -894,7 +894,7 @@ class flat_multiset //! Complexity: Constant. //! //! Note: Non-standard extension. - stored_allocator_type &get_stored_allocator() + stored_allocator_type &get_stored_allocator() BOOST_CONTAINER_NOEXCEPT { return m_flat_tree.get_stored_allocator(); } //! Effects: Returns a reference to the internal allocator. @@ -904,7 +904,7 @@ class flat_multiset //! Complexity: Constant. //! //! Note: Non-standard extension. - const stored_allocator_type &get_stored_allocator() const + const stored_allocator_type &get_stored_allocator() const BOOST_CONTAINER_NOEXCEPT { return m_flat_tree.get_stored_allocator(); } //! Effects: Returns an iterator to the first element contained in the container. @@ -912,7 +912,7 @@ class flat_multiset //! Throws: Nothing. //! //! Complexity: Constant. - iterator begin() + iterator begin() BOOST_CONTAINER_NOEXCEPT { return m_flat_tree.begin(); } //! Effects: Returns a const_iterator to the first element contained in the container. @@ -928,7 +928,7 @@ class flat_multiset //! Throws: Nothing. //! //! Complexity: Constant. - const_iterator cbegin() const + const_iterator cbegin() const BOOST_CONTAINER_NOEXCEPT { return m_flat_tree.cbegin(); } //! Effects: Returns an iterator to the end of the container. @@ -936,7 +936,7 @@ class flat_multiset //! Throws: Nothing. //! //! Complexity: Constant. - iterator end() + iterator end() BOOST_CONTAINER_NOEXCEPT { return m_flat_tree.end(); } //! Effects: Returns a const_iterator to the end of the container. @@ -944,7 +944,7 @@ class flat_multiset //! Throws: Nothing. //! //! Complexity: Constant. - const_iterator end() const + const_iterator end() const BOOST_CONTAINER_NOEXCEPT { return m_flat_tree.end(); } //! Effects: Returns a const_iterator to the end of the container. @@ -952,7 +952,7 @@ class flat_multiset //! Throws: Nothing. //! //! Complexity: Constant. - const_iterator cend() const + const_iterator cend() const BOOST_CONTAINER_NOEXCEPT { return m_flat_tree.cend(); } //! Effects: Returns a reverse_iterator pointing to the beginning @@ -961,7 +961,7 @@ class flat_multiset //! Throws: Nothing. //! //! Complexity: Constant. - reverse_iterator rbegin() + reverse_iterator rbegin() BOOST_CONTAINER_NOEXCEPT { return m_flat_tree.rbegin(); } //! Effects: Returns a const_reverse_iterator pointing to the beginning @@ -970,7 +970,7 @@ class flat_multiset //! Throws: Nothing. //! //! Complexity: Constant. - const_reverse_iterator rbegin() const + const_reverse_iterator rbegin() const BOOST_CONTAINER_NOEXCEPT { return m_flat_tree.rbegin(); } //! Effects: Returns a const_reverse_iterator pointing to the beginning @@ -979,7 +979,7 @@ class flat_multiset //! Throws: Nothing. //! //! Complexity: Constant. - const_reverse_iterator crbegin() const + const_reverse_iterator crbegin() const BOOST_CONTAINER_NOEXCEPT { return m_flat_tree.crbegin(); } //! Effects: Returns a reverse_iterator pointing to the end @@ -988,7 +988,7 @@ class flat_multiset //! Throws: Nothing. //! //! Complexity: Constant. - reverse_iterator rend() + reverse_iterator rend() BOOST_CONTAINER_NOEXCEPT { return m_flat_tree.rend(); } //! Effects: Returns a const_reverse_iterator pointing to the end @@ -997,7 +997,7 @@ class flat_multiset //! Throws: Nothing. //! //! Complexity: Constant. - const_reverse_iterator rend() const + const_reverse_iterator rend() const BOOST_CONTAINER_NOEXCEPT { return m_flat_tree.rend(); } //! Effects: Returns a const_reverse_iterator pointing to the end @@ -1006,7 +1006,7 @@ class flat_multiset //! Throws: Nothing. //! //! Complexity: Constant. - const_reverse_iterator crend() const + const_reverse_iterator crend() const BOOST_CONTAINER_NOEXCEPT { return m_flat_tree.crend(); } ////////////////////////////////////////////// @@ -1020,7 +1020,7 @@ class flat_multiset //! Throws: Nothing. //! //! Complexity: Constant. - bool empty() const + bool empty() const BOOST_CONTAINER_NOEXCEPT { return m_flat_tree.empty(); } //! Effects: Returns the number of the elements contained in the container. @@ -1028,7 +1028,7 @@ class flat_multiset //! Throws: Nothing. //! //! Complexity: Constant. - size_type size() const + size_type size() const BOOST_CONTAINER_NOEXCEPT { return m_flat_tree.size(); } //! Effects: Returns the largest possible size of the container. @@ -1036,7 +1036,7 @@ class flat_multiset //! Throws: Nothing. //! //! Complexity: Constant. - size_type max_size() const + size_type max_size() const BOOST_CONTAINER_NOEXCEPT { return m_flat_tree.max_size(); } //! Effects: Number of elements for which memory has been allocated. @@ -1045,7 +1045,7 @@ class flat_multiset //! Throws: Nothing. //! //! Complexity: Constant. - size_type capacity() const + size_type capacity() const BOOST_CONTAINER_NOEXCEPT { return m_flat_tree.capacity(); } //! Effects: If n is less than or equal to capacity(), this call has no @@ -1055,10 +1055,10 @@ class flat_multiset //! //! Throws: If memory allocation allocation throws or Key's copy constructor throws. //! - //! Note: If capacity() is less than "count", iterators and references to + //! Note: If capacity() is less than "cnt", iterators and references to //! to values might be invalidated. - void reserve(size_type count_) - { m_flat_tree.reserve(count_); } + void reserve(size_type cnt) + { m_flat_tree.reserve(cnt); } //! Effects: Tries to deallocate the excess of memory created // with previous allocations. The size of the vector is unchanged @@ -1244,7 +1244,7 @@ class flat_multiset //! Postcondition: size() == 0. //! //! Complexity: linear in size(). - void clear() + void clear() BOOST_CONTAINER_NOEXCEPT { m_flat_tree.clear(); } ////////////////////////////////////////////// @@ -1388,15 +1388,15 @@ inline void swap(flat_multiset& x, flat_multiset == true_type //!specialization for optimizations template struct has_trivial_destructor_after_move > { - static const bool value = has_trivial_destructor::value && has_trivial_destructor::value; + static const bool value = has_trivial_destructor_after_move::value && has_trivial_destructor_after_move::value; }; -*/ + namespace container { /// @endcond diff --git a/include/boost/container/list.hpp b/include/boost/container/list.hpp index 38f7c54..b4a3cf3 100644 --- a/include/boost/container/list.hpp +++ b/include/boost/container/list.hpp @@ -18,8 +18,9 @@ #include #include #include -#include -#include +#include +#include +#include #include #include #include @@ -140,9 +141,6 @@ class list_const_iterator friend bool operator!= (const list_const_iterator& l, const list_const_iterator& r) { return l.m_it != r.m_it; } - IIterator &get() - { return this->m_it; } - const IIterator &get() const { return this->m_it; } }; @@ -187,9 +185,6 @@ class list_iterator list_iterator operator--(int) { IIterator tmp = this->m_it; --*this; return list_iterator(tmp); } - IIterator &get() - { return this->m_it; } - const IIterator &get() const { return this->m_it; } }; @@ -303,10 +298,10 @@ class list //! Effects: Constructs a list taking the allocator as parameter. //! - //! Throws: If allocator_type's copy constructor throws. + //! Throws: Nothing //! //! Complexity: Constant. - explicit list(const allocator_type &a) + explicit list(const allocator_type &a) BOOST_CONTAINER_NOEXCEPT : AllocHolder(a) {} @@ -398,7 +393,7 @@ class list //! Throws: Nothing. //! //! Complexity: Linear to the number of elements. - ~list() + ~list() BOOST_CONTAINER_NOEXCEPT {} //AllocHolder clears the list //! Effects: Makes *this contain the same elements as x. @@ -498,7 +493,7 @@ class list //! Throws: If allocator's copy constructor throws. //! //! Complexity: Constant. - allocator_type get_allocator() const + allocator_type get_allocator() const BOOST_CONTAINER_NOEXCEPT { return allocator_type(this->node_alloc()); } //! Effects: Returns a reference to the internal allocator. @@ -508,7 +503,7 @@ class list //! Complexity: Constant. //! //! Note: Non-standard extension. - stored_allocator_type &get_stored_allocator() + stored_allocator_type &get_stored_allocator() BOOST_CONTAINER_NOEXCEPT { return this->node_alloc(); } //! Effects: Returns a reference to the internal allocator. @@ -518,7 +513,7 @@ class list //! Complexity: Constant. //! //! Note: Non-standard extension. - const stored_allocator_type &get_stored_allocator() const + const stored_allocator_type &get_stored_allocator() const BOOST_CONTAINER_NOEXCEPT { return this->node_alloc(); } ////////////////////////////////////////////// @@ -532,7 +527,7 @@ class list //! Throws: Nothing. //! //! Complexity: Constant. - iterator begin() + iterator begin() BOOST_CONTAINER_NOEXCEPT { return iterator(this->icont().begin()); } //! Effects: Returns a const_iterator to the first element contained in the list. @@ -540,7 +535,7 @@ class list //! Throws: Nothing. //! //! Complexity: Constant. - const_iterator begin() const + const_iterator begin() const BOOST_CONTAINER_NOEXCEPT { return this->cbegin(); } //! Effects: Returns an iterator to the end of the list. @@ -548,7 +543,7 @@ class list //! Throws: Nothing. //! //! Complexity: Constant. - iterator end() + iterator end() BOOST_CONTAINER_NOEXCEPT { return iterator(this->icont().end()); } //! Effects: Returns a const_iterator to the end of the list. @@ -556,7 +551,7 @@ class list //! Throws: Nothing. //! //! Complexity: Constant. - const_iterator end() const + const_iterator end() const BOOST_CONTAINER_NOEXCEPT { return this->cend(); } //! Effects: Returns a reverse_iterator pointing to the beginning @@ -565,7 +560,7 @@ class list //! Throws: Nothing. //! //! Complexity: Constant. - reverse_iterator rbegin() + reverse_iterator rbegin() BOOST_CONTAINER_NOEXCEPT { return reverse_iterator(end()); } //! Effects: Returns a const_reverse_iterator pointing to the beginning @@ -574,7 +569,7 @@ class list //! Throws: Nothing. //! //! Complexity: Constant. - const_reverse_iterator rbegin() const + const_reverse_iterator rbegin() const BOOST_CONTAINER_NOEXCEPT { return this->crbegin(); } //! Effects: Returns a reverse_iterator pointing to the end @@ -583,7 +578,7 @@ class list //! Throws: Nothing. //! //! Complexity: Constant. - reverse_iterator rend() + reverse_iterator rend() BOOST_CONTAINER_NOEXCEPT { return reverse_iterator(begin()); } //! Effects: Returns a const_reverse_iterator pointing to the end @@ -592,7 +587,7 @@ class list //! Throws: Nothing. //! //! Complexity: Constant. - const_reverse_iterator rend() const + const_reverse_iterator rend() const BOOST_CONTAINER_NOEXCEPT { return this->crend(); } //! Effects: Returns a const_iterator to the first element contained in the list. @@ -600,7 +595,7 @@ class list //! Throws: Nothing. //! //! Complexity: Constant. - const_iterator cbegin() const + const_iterator cbegin() const BOOST_CONTAINER_NOEXCEPT { return const_iterator(this->non_const_icont().begin()); } //! Effects: Returns a const_iterator to the end of the list. @@ -608,7 +603,7 @@ class list //! Throws: Nothing. //! //! Complexity: Constant. - const_iterator cend() const + const_iterator cend() const BOOST_CONTAINER_NOEXCEPT { return const_iterator(this->non_const_icont().end()); } //! Effects: Returns a const_reverse_iterator pointing to the beginning @@ -617,7 +612,7 @@ class list //! Throws: Nothing. //! //! Complexity: Constant. - const_reverse_iterator crbegin() const + const_reverse_iterator crbegin() const BOOST_CONTAINER_NOEXCEPT { return const_reverse_iterator(this->cend()); } //! Effects: Returns a const_reverse_iterator pointing to the end @@ -626,7 +621,7 @@ class list //! Throws: Nothing. //! //! Complexity: Constant. - const_reverse_iterator crend() const + const_reverse_iterator crend() const BOOST_CONTAINER_NOEXCEPT { return const_reverse_iterator(this->cbegin()); } ////////////////////////////////////////////// @@ -640,7 +635,7 @@ class list //! Throws: Nothing. //! //! Complexity: Constant. - bool empty() const + bool empty() const BOOST_CONTAINER_NOEXCEPT { return !this->size(); } //! Effects: Returns the number of the elements contained in the list. @@ -648,7 +643,7 @@ class list //! Throws: Nothing. //! //! Complexity: Constant. - size_type size() const + size_type size() const BOOST_CONTAINER_NOEXCEPT { return this->icont().size(); } //! Effects: Returns the largest possible size of the list. @@ -656,7 +651,7 @@ class list //! Throws: Nothing. //! //! Complexity: Constant. - size_type max_size() const + size_type max_size() const BOOST_CONTAINER_NOEXCEPT { return AllocHolder::max_size(); } //! Effects: Inserts or erases elements at the end such that @@ -700,7 +695,7 @@ class list //! Throws: Nothing. //! //! Complexity: Constant. - reference front() + reference front() BOOST_CONTAINER_NOEXCEPT { return *this->begin(); } //! Requires: !empty() @@ -711,7 +706,7 @@ class list //! Throws: Nothing. //! //! Complexity: Constant. - const_reference front() const + const_reference front() const BOOST_CONTAINER_NOEXCEPT { return *this->begin(); } //! Requires: !empty() @@ -722,7 +717,7 @@ class list //! Throws: Nothing. //! //! Complexity: Constant. - reference back() + reference back() BOOST_CONTAINER_NOEXCEPT { return *(--this->end()); } //! Requires: !empty() @@ -733,7 +728,7 @@ class list //! Throws: Nothing. //! //! Complexity: Constant. - const_reference back() const + const_reference back() const BOOST_CONTAINER_NOEXCEPT { return *(--this->end()); } ////////////////////////////////////////////// @@ -939,8 +934,10 @@ class list { //Optimized allocation and construction insertion_functor func(this->icont(), p.get()); + iterator before_p(p.get()); + --before_p; this->allocate_many_and_construct(first, std::distance(first, last), func); - return iterator(func.inserted_first()); + return ++before_p; } #endif @@ -949,7 +946,7 @@ class list //! Throws: Nothing. //! //! Complexity: Amortized constant time. - void pop_front() + void pop_front() BOOST_CONTAINER_NOEXCEPT { this->erase(this->cbegin()); } //! Effects: Removes the last element from the list. @@ -957,7 +954,7 @@ class list //! Throws: Nothing. //! //! Complexity: Amortized constant time. - void pop_back() + void pop_back() BOOST_CONTAINER_NOEXCEPT { const_iterator tmp = this->cend(); this->erase(--tmp); } //! Requires: p must be a valid iterator of *this. @@ -967,7 +964,7 @@ class list //! Throws: Nothing. //! //! Complexity: Amortized constant time. - iterator erase(const_iterator p) + iterator erase(const_iterator p) BOOST_CONTAINER_NOEXCEPT { return iterator(this->icont().erase_and_dispose(p.get(), Destroyer(this->node_alloc()))); } //! Requires: first and last must be valid iterator to elements in *this. @@ -977,7 +974,7 @@ class list //! Throws: Nothing. //! //! Complexity: Linear to the distance between first and last. - iterator erase(const_iterator first, const_iterator last) + iterator erase(const_iterator first, const_iterator last) BOOST_CONTAINER_NOEXCEPT { return iterator(AllocHolder::erase_range(first.get(), last.get(), alloc_version())); } //! Effects: Swaps the contents of *this and x. @@ -993,7 +990,7 @@ class list //! Throws: Nothing. //! //! Complexity: Linear to the number of elements in the list. - void clear() + void clear() BOOST_CONTAINER_NOEXCEPT { AllocHolder::clear(alloc_version()); } ////////////////////////////////////////////// @@ -1003,13 +1000,12 @@ class list ////////////////////////////////////////////// //! Requires: p must point to an element contained - //! by the list. x != *this + //! by the list. x != *this. this' allocator and x's allocator shall compare equal //! //! Effects: Transfers all the elements of list x to this list, before the //! the element pointed by p. No destructors or copy constructors are called. //! - //! Throws: std::runtime_error if this' allocator and x's allocator - //! are not equal. + //! Throws: Nothing //! //! Complexity: Constant. //! @@ -1017,19 +1013,18 @@ class list //! this list. Iterators of this list and all the references are not invalidated. void splice(const_iterator p, list& x) BOOST_CONTAINER_NOEXCEPT { - BOOST_ASSERT(*this != x); + BOOST_ASSERT(this != &x); BOOST_ASSERT(this->node_alloc() == x.node_alloc()); this->icont().splice(p.get(), x.icont()); } //! Requires: p must point to an element contained - //! by the list. x != *this + //! by the list. x != *this. this' allocator and x's allocator shall compare equal //! //! Effects: Transfers all the elements of list x to this list, before the //! the element pointed by p. No destructors or copy constructors are called. //! - //! Throws: std::runtime_error if this' allocator and x's allocator - //! are not equal. + //! Throws: Nothing //! //! Complexity: Constant. //! @@ -1040,13 +1035,13 @@ class list //! Requires: p must point to an element contained //! by this list. i must point to an element contained in list x. + //! this' allocator and x's allocator shall compare equal //! //! Effects: Transfers the value pointed by i, from list x to this list, //! before the the element pointed by p. No destructors or copy constructors are called. //! If p == i or p == ++i, this function is a null operation. //! - //! Throws: std::runtime_error if this' allocator and x's allocator - //! are not equal. + //! Throws: Nothing //! //! Complexity: Constant. //! @@ -1054,20 +1049,20 @@ class list //! list. Iterators of this list and all the references are not invalidated. void splice(const_iterator p, list &x, const_iterator i) BOOST_CONTAINER_NOEXCEPT { - BOOST_ASSERT(*this != x); + //BOOST_ASSERT(this != &x); BOOST_ASSERT(this->node_alloc() == x.node_alloc()); this->icont().splice(p.get(), x.icont(), i.get()); } //! Requires: p must point to an element contained //! by this list. i must point to an element contained in list x. + //! this' allocator and x's allocator shall compare equal. //! //! Effects: Transfers the value pointed by i, from list x to this list, //! before the the element pointed by p. No destructors or copy constructors are called. //! If p == i or p == ++i, this function is a null operation. //! - //! Throws: std::runtime_error if this' allocator and x's allocator - //! are not equal. + //! Throws: Nothing //! //! Complexity: Constant. //! @@ -1078,12 +1073,12 @@ class list //! Requires: p must point to an element contained //! by this list. first and last must point to elements contained in list x. + //! this' allocator and x's allocator shall compare equal //! //! Effects: Transfers the range pointed by first and last from list x to this list, //! before the the element pointed by p. No destructors or copy constructors are called. //! - //! Throws: std::runtime_error if this' allocator and x's allocator - //! are not equal. + //! Throws: Nothing //! //! Complexity: Linear to the number of elements transferred. //! @@ -1091,19 +1086,18 @@ class list //! list. Iterators of this list and all the references are not invalidated. void splice(const_iterator p, list &x, const_iterator first, const_iterator last) BOOST_CONTAINER_NOEXCEPT { - BOOST_ASSERT(*this != x); BOOST_ASSERT(this->node_alloc() == x.node_alloc()); this->icont().splice(p.get(), x.icont(), first.get(), last.get()); } //! Requires: p must point to an element contained //! by this list. first and last must point to elements contained in list x. + //! this' allocator and x's allocator shall compare equal. //! //! Effects: Transfers the range pointed by first and last from list x to this list, //! before the the element pointed by p. No destructors or copy constructors are called. //! - //! Throws: std::runtime_error if this' allocator and x's allocator - //! are not equal. + //! Throws: Nothing //! //! Complexity: Linear to the number of elements transferred. //! @@ -1114,13 +1108,12 @@ class list //! Requires: p must point to an element contained //! by this list. first and last must point to elements contained in list x. - //! n == std::distance(first, last) + //! n == std::distance(first, last). this' allocator and x's allocator shall compare equal //! //! Effects: Transfers the range pointed by first and last from list x to this list, //! before the the element pointed by p. No destructors or copy constructors are called. //! - //! Throws: std::runtime_error if this' allocator and x's allocator - //! are not equal. + //! Throws: Nothing //! //! Complexity: Constant. //! @@ -1130,20 +1123,18 @@ class list //! Note: Non-standard extension void splice(const_iterator p, list &x, const_iterator first, const_iterator last, size_type n) BOOST_CONTAINER_NOEXCEPT { - BOOST_ASSERT(*this != x); BOOST_ASSERT(this->node_alloc() == x.node_alloc()); this->icont().splice(p.get(), x.icont(), first.get(), last.get(), n); } //! Requires: p must point to an element contained //! by this list. first and last must point to elements contained in list x. - //! n == std::distance(first, last) + //! n == std::distance(first, last). this' allocator and x's allocator shall compare equal //! //! Effects: Transfers the range pointed by first and last from list x to this list, //! before the the element pointed by p. No destructors or copy constructors are called. //! - //! Throws: std::runtime_error if this' allocator and x's allocator - //! are not equal. + //! Throws: Nothing //! //! Complexity: Constant. //! @@ -1156,7 +1147,7 @@ class list //! Effects: Removes all the elements that compare equal to value. //! - //! Throws: Nothing. + //! Throws: If comparison throws. //! //! Complexity: Linear time. It performs exactly size() comparisons for equality. //! @@ -1184,9 +1175,9 @@ class list //! Effects: Removes adjacent duplicate elements or adjacent //! elements that are equal from the list. //! - //! Throws: Nothing. + //! Throws: If comparison throws. //! - //! Complexity: Linear time (size()-1 comparisons calls to pred()). + //! Complexity: Linear time (size()-1 comparisons equality comparisons). //! //! Note: The relative order of elements that are not removed is unchanged, //! and iterators to elements that are not removed remain valid. @@ -1198,7 +1189,7 @@ class list //! //! Throws: If pred throws. //! - //! Complexity: Linear time (size()-1 comparisons equality comparisons). + //! Complexity: Linear time (size()-1 comparisons calls to pred()). //! //! Note: The relative order of elements that are not removed is unchanged, //! and iterators to elements that are not removed remain valid. @@ -1216,7 +1207,7 @@ class list //! that is, if an element from *this is equivalent to one from x, then the element //! from *this will precede the one from x. //! - //! Throws: Nothing. + //! Throws: If comparison throws. //! //! Complexity: This function is linear time: it performs at most //! size() + x.size() - 1 comparisons. @@ -1230,7 +1221,7 @@ class list //! that is, if an element from *this is equivalent to one from x, then the element //! from *this will precede the one from x. //! - //! Throws: Nothing. + //! Throws: If comparison throws. //! //! Complexity: This function is linear time: it performs at most //! size() + x.size() - 1 comparisons. @@ -1245,22 +1236,18 @@ class list //! in order into *this. The merge is stable; that is, if an element from *this is //! equivalent to one from x, then the element from *this will precede the one from x. //! - //! Throws: Nothing. + //! Throws: If comp throws. //! //! Complexity: This function is linear time: it performs at most //! size() + x.size() - 1 comparisons. //! //! Note: Iterators and references to *this are not invalidated. template - void merge(list &x, StrictWeakOrdering comp) + void merge(list &x, const StrictWeakOrdering &comp) { - if((NodeAlloc&)*this == (NodeAlloc&)x){ - this->icont().merge(x.icont(), - ValueCompareToNodeCompare(comp)); - } - else{ - throw std::runtime_error("list::merge called with unequal allocators"); - } + BOOST_ASSERT(this->node_alloc() == x.node_alloc()); + this->icont().merge(x.icont(), + ValueCompareToNodeCompare(comp)); } //! Requires: p must be a comparison function that induces a strict weak @@ -1271,7 +1258,7 @@ class list //! in order into *this. The merge is stable; that is, if an element from *this is //! equivalent to one from x, then the element from *this will precede the one from x. //! - //! Throws: Nothing. + //! Throws: If comp throws. //! //! Complexity: This function is linear time: it performs at most //! size() + x.size() - 1 comparisons. @@ -1284,7 +1271,7 @@ class list //! Effects: This function sorts the list *this according to std::less. //! The sort is stable, that is, the relative order of equivalent elements is preserved. //! - //! Throws: Nothing. + //! Throws: If comparison throws. //! //! Notes: Iterators and references are not invalidated. //! @@ -1296,7 +1283,7 @@ class list //! Effects: This function sorts the list *this according to std::less. //! The sort is stable, that is, the relative order of equivalent elements is preserved. //! - //! Throws: Nothing. + //! Throws: If comp throws. //! //! Notes: Iterators and references are not invalidated. //! @@ -1318,7 +1305,7 @@ class list //! Complexity: This function is linear time. //! //! Note: Iterators and references are not invalidated - void reverse() + void reverse() BOOST_CONTAINER_NOEXCEPT { this->icont().reverse(); } /// @cond @@ -1382,31 +1369,18 @@ class list class insertion_functor { Icont &icont_; - typedef typename Icont::iterator iiterator; typedef typename Icont::const_iterator iconst_iterator; - const iconst_iterator pos_; - iiterator ret_; - bool first_; public: insertion_functor(Icont &icont, typename Icont::const_iterator pos) - : icont_(icont), pos_(pos), ret_(pos.unconst()), first_(true) + : icont_(icont), pos_(pos) {} void operator()(Node &n) { - if(first_){ - ret_ = this->icont_.insert(pos_, n); - first_ = false; - } - else{ - this->icont_.insert(pos_, n); - } + this->icont_.insert(pos_, n); } - - iiterator inserted_first() const - { return ret_; } }; //Functors for member algorithm defaults @@ -1483,15 +1457,14 @@ inline void swap(list& x, list& y) /// @cond } //namespace container { -/* + //!has_trivial_destructor_after_move<> == true_type //!specialization for optimizations template struct has_trivial_destructor_after_move > -{ - static const bool value = has_trivial_destructor::value; -}; -*/ + : public ::boost::has_trivial_destructor_after_move +{}; + namespace container { /// @endcond diff --git a/include/boost/container/map.hpp b/include/boost/container/map.hpp index 92d499a..d4ab423 100644 --- a/include/boost/container/map.hpp +++ b/include/boost/container/map.hpp @@ -30,8 +30,8 @@ #include #include #include -#include -#include +#include +#include #include #include @@ -229,7 +229,7 @@ class map //! was passed to the object's constructor. //! //! Complexity: Constant. - allocator_type get_allocator() const + allocator_type get_allocator() const BOOST_CONTAINER_NOEXCEPT { return m_tree.get_allocator(); } //! Effects: Returns a reference to the internal allocator. @@ -239,7 +239,7 @@ class map //! Complexity: Constant. //! //! Note: Non-standard extension. - stored_allocator_type &get_stored_allocator() + stored_allocator_type &get_stored_allocator() BOOST_CONTAINER_NOEXCEPT { return m_tree.get_stored_allocator(); } //! Effects: Returns a reference to the internal allocator. @@ -249,7 +249,7 @@ class map //! Complexity: Constant. //! //! Note: Non-standard extension. - const stored_allocator_type &get_stored_allocator() const + const stored_allocator_type &get_stored_allocator() const BOOST_CONTAINER_NOEXCEPT { return m_tree.get_stored_allocator(); } ////////////////////////////////////////////// @@ -263,7 +263,7 @@ class map //! Throws: Nothing. //! //! Complexity: Constant. - iterator begin() + iterator begin() BOOST_CONTAINER_NOEXCEPT { return m_tree.begin(); } //! Effects: Returns a const_iterator to the first element contained in the container. @@ -271,7 +271,7 @@ class map //! Throws: Nothing. //! //! Complexity: Constant. - const_iterator begin() const + const_iterator begin() const BOOST_CONTAINER_NOEXCEPT { return this->cbegin(); } //! Effects: Returns an iterator to the end of the container. @@ -279,7 +279,7 @@ class map //! Throws: Nothing. //! //! Complexity: Constant. - iterator end() + iterator end() BOOST_CONTAINER_NOEXCEPT { return m_tree.end(); } //! Effects: Returns a const_iterator to the end of the container. @@ -287,7 +287,7 @@ class map //! Throws: Nothing. //! //! Complexity: Constant. - const_iterator end() const + const_iterator end() const BOOST_CONTAINER_NOEXCEPT { return this->cend(); } //! Effects: Returns a reverse_iterator pointing to the beginning @@ -296,7 +296,7 @@ class map //! Throws: Nothing. //! //! Complexity: Constant. - reverse_iterator rbegin() + reverse_iterator rbegin() BOOST_CONTAINER_NOEXCEPT { return m_tree.rbegin(); } //! Effects: Returns a const_reverse_iterator pointing to the beginning @@ -305,7 +305,7 @@ class map //! Throws: Nothing. //! //! Complexity: Constant. - const_reverse_iterator rbegin() const + const_reverse_iterator rbegin() const BOOST_CONTAINER_NOEXCEPT { return this->crbegin(); } //! Effects: Returns a reverse_iterator pointing to the end @@ -314,7 +314,7 @@ class map //! Throws: Nothing. //! //! Complexity: Constant. - reverse_iterator rend() + reverse_iterator rend() BOOST_CONTAINER_NOEXCEPT { return m_tree.rend(); } //! Effects: Returns a const_reverse_iterator pointing to the end @@ -323,7 +323,7 @@ class map //! Throws: Nothing. //! //! Complexity: Constant. - const_reverse_iterator rend() const + const_reverse_iterator rend() const BOOST_CONTAINER_NOEXCEPT { return this->crend(); } //! Effects: Returns a const_iterator to the first element contained in the container. @@ -331,7 +331,7 @@ class map //! Throws: Nothing. //! //! Complexity: Constant. - const_iterator cbegin() const + const_iterator cbegin() const BOOST_CONTAINER_NOEXCEPT { return m_tree.begin(); } //! Effects: Returns a const_iterator to the end of the container. @@ -339,7 +339,7 @@ class map //! Throws: Nothing. //! //! Complexity: Constant. - const_iterator cend() const + const_iterator cend() const BOOST_CONTAINER_NOEXCEPT { return m_tree.end(); } //! Effects: Returns a const_reverse_iterator pointing to the beginning @@ -348,7 +348,7 @@ class map //! Throws: Nothing. //! //! Complexity: Constant. - const_reverse_iterator crbegin() const + const_reverse_iterator crbegin() const BOOST_CONTAINER_NOEXCEPT { return m_tree.rbegin(); } //! Effects: Returns a const_reverse_iterator pointing to the end @@ -357,7 +357,7 @@ class map //! Throws: Nothing. //! //! Complexity: Constant. - const_reverse_iterator crend() const + const_reverse_iterator crend() const BOOST_CONTAINER_NOEXCEPT { return m_tree.rend(); } ////////////////////////////////////////////// @@ -371,7 +371,7 @@ class map //! Throws: Nothing. //! //! Complexity: Constant. - bool empty() const + bool empty() const BOOST_CONTAINER_NOEXCEPT { return m_tree.empty(); } //! Effects: Returns the number of the elements contained in the container. @@ -379,7 +379,7 @@ class map //! Throws: Nothing. //! //! Complexity: Constant. - size_type size() const + size_type size() const BOOST_CONTAINER_NOEXCEPT { return m_tree.size(); } //! Effects: Returns the largest possible size of the container. @@ -387,7 +387,7 @@ class map //! Throws: Nothing. //! //! Complexity: Constant. - size_type max_size() const + size_type max_size() const BOOST_CONTAINER_NOEXCEPT { return m_tree.max_size(); } ////////////////////////////////////////////// @@ -621,7 +621,7 @@ class map //! returns end(). //! //! Complexity: Amortized constant time - iterator erase(const_iterator position) + iterator erase(const_iterator position) BOOST_CONTAINER_NOEXCEPT { return m_tree.erase(position); } //! Effects: Erases all elements in the container with key equivalent to x. @@ -629,7 +629,7 @@ class map //! Returns: Returns the number of erased elements. //! //! Complexity: log(size()) + count(k) - size_type erase(const key_type& x) + size_type erase(const key_type& x) BOOST_CONTAINER_NOEXCEPT { return m_tree.erase(x); } //! Effects: Erases all the elements in the range [first, last). @@ -637,7 +637,7 @@ class map //! Returns: Returns last. //! //! Complexity: log(size())+N where N is the distance from first to last. - iterator erase(const_iterator first, const_iterator last) + iterator erase(const_iterator first, const_iterator last) BOOST_CONTAINER_NOEXCEPT { return m_tree.erase(first, last); } //! Effects: Swaps the contents of *this and x. @@ -653,7 +653,7 @@ class map //! Postcondition: size() == 0. //! //! Complexity: linear in size(). - void clear() + void clear() BOOST_CONTAINER_NOEXCEPT { m_tree.clear(); } ////////////////////////////////////////////// @@ -827,15 +827,15 @@ inline bool operator<(const multimap& x, const multimap& y); } //namespace container { -/* + //!has_trivial_destructor_after_move<> == true_type //!specialization for optimizations template struct has_trivial_destructor_after_move > { - static const bool value = has_trivial_destructor::value && has_trivial_destructor::value; + static const bool value = has_trivial_destructor_after_move::value && has_trivial_destructor_after_move::value; }; -*/ + namespace container { /// @endcond @@ -951,9 +951,9 @@ class multimap //! //! Complexity: Linear in N. template - multimap(ordered_range_t ordered_range_, InputIterator first, InputIterator last, const Compare& comp = Compare(), + multimap(ordered_range_t, InputIterator first, InputIterator last, const Compare& comp = Compare(), const allocator_type& a = allocator_type()) - : m_tree(ordered_range_, first, last, comp, a) + : m_tree(ordered_range, first, last, comp, a) {} //! Effects: Copy constructs a multimap. @@ -1016,7 +1016,7 @@ class multimap //! was passed to the object's constructor. //! //! Complexity: Constant. - allocator_type get_allocator() const + allocator_type get_allocator() const BOOST_CONTAINER_NOEXCEPT { return m_tree.get_allocator(); } //! Effects: Returns a reference to the internal allocator. @@ -1026,7 +1026,7 @@ class multimap //! Complexity: Constant. //! //! Note: Non-standard extension. - stored_allocator_type &get_stored_allocator() + stored_allocator_type &get_stored_allocator() BOOST_CONTAINER_NOEXCEPT { return m_tree.get_stored_allocator(); } //! Effects: Returns a reference to the internal allocator. @@ -1036,7 +1036,7 @@ class multimap //! Complexity: Constant. //! //! Note: Non-standard extension. - const stored_allocator_type &get_stored_allocator() const + const stored_allocator_type &get_stored_allocator() const BOOST_CONTAINER_NOEXCEPT { return m_tree.get_stored_allocator(); } ////////////////////////////////////////////// @@ -1050,7 +1050,7 @@ class multimap //! Throws: Nothing. //! //! Complexity: Constant. - iterator begin() + iterator begin() BOOST_CONTAINER_NOEXCEPT { return m_tree.begin(); } //! Effects: Returns a const_iterator to the first element contained in the container. @@ -1058,7 +1058,7 @@ class multimap //! Throws: Nothing. //! //! Complexity: Constant. - const_iterator begin() const + const_iterator begin() const BOOST_CONTAINER_NOEXCEPT { return this->cbegin(); } //! Effects: Returns an iterator to the end of the container. @@ -1066,7 +1066,7 @@ class multimap //! Throws: Nothing. //! //! Complexity: Constant. - iterator end() + iterator end() BOOST_CONTAINER_NOEXCEPT { return m_tree.end(); } //! Effects: Returns a const_iterator to the end of the container. @@ -1074,7 +1074,7 @@ class multimap //! Throws: Nothing. //! //! Complexity: Constant. - const_iterator end() const + const_iterator end() const BOOST_CONTAINER_NOEXCEPT { return this->cend(); } //! Effects: Returns a reverse_iterator pointing to the beginning @@ -1083,7 +1083,7 @@ class multimap //! Throws: Nothing. //! //! Complexity: Constant. - reverse_iterator rbegin() + reverse_iterator rbegin() BOOST_CONTAINER_NOEXCEPT { return m_tree.rbegin(); } //! Effects: Returns a const_reverse_iterator pointing to the beginning @@ -1092,7 +1092,7 @@ class multimap //! Throws: Nothing. //! //! Complexity: Constant. - const_reverse_iterator rbegin() const + const_reverse_iterator rbegin() const BOOST_CONTAINER_NOEXCEPT { return this->crbegin(); } //! Effects: Returns a reverse_iterator pointing to the end @@ -1101,7 +1101,7 @@ class multimap //! Throws: Nothing. //! //! Complexity: Constant. - reverse_iterator rend() + reverse_iterator rend() BOOST_CONTAINER_NOEXCEPT { return m_tree.rend(); } //! Effects: Returns a const_reverse_iterator pointing to the end @@ -1110,7 +1110,7 @@ class multimap //! Throws: Nothing. //! //! Complexity: Constant. - const_reverse_iterator rend() const + const_reverse_iterator rend() const BOOST_CONTAINER_NOEXCEPT { return this->crend(); } //! Effects: Returns a const_iterator to the first element contained in the container. @@ -1118,7 +1118,7 @@ class multimap //! Throws: Nothing. //! //! Complexity: Constant. - const_iterator cbegin() const + const_iterator cbegin() const BOOST_CONTAINER_NOEXCEPT { return m_tree.begin(); } //! Effects: Returns a const_iterator to the end of the container. @@ -1126,7 +1126,7 @@ class multimap //! Throws: Nothing. //! //! Complexity: Constant. - const_iterator cend() const + const_iterator cend() const BOOST_CONTAINER_NOEXCEPT { return m_tree.end(); } //! Effects: Returns a const_reverse_iterator pointing to the beginning @@ -1135,7 +1135,7 @@ class multimap //! Throws: Nothing. //! //! Complexity: Constant. - const_reverse_iterator crbegin() const + const_reverse_iterator crbegin() const BOOST_CONTAINER_NOEXCEPT { return m_tree.rbegin(); } //! Effects: Returns a const_reverse_iterator pointing to the end @@ -1144,7 +1144,7 @@ class multimap //! Throws: Nothing. //! //! Complexity: Constant. - const_reverse_iterator crend() const + const_reverse_iterator crend() const BOOST_CONTAINER_NOEXCEPT { return m_tree.rend(); } ////////////////////////////////////////////// @@ -1158,7 +1158,7 @@ class multimap //! Throws: Nothing. //! //! Complexity: Constant. - bool empty() const + bool empty() const BOOST_CONTAINER_NOEXCEPT { return m_tree.empty(); } //! Effects: Returns the number of the elements contained in the container. @@ -1166,7 +1166,7 @@ class multimap //! Throws: Nothing. //! //! Complexity: Constant. - size_type size() const + size_type size() const BOOST_CONTAINER_NOEXCEPT { return m_tree.size(); } //! Effects: Returns the largest possible size of the container. @@ -1174,7 +1174,7 @@ class multimap //! Throws: Nothing. //! //! Complexity: Constant. - size_type max_size() const + size_type max_size() const BOOST_CONTAINER_NOEXCEPT { return m_tree.max_size(); } ////////////////////////////////////////////// @@ -1317,7 +1317,7 @@ class multimap //! returns end(). //! //! Complexity: Amortized constant time - iterator erase(const_iterator position) + iterator erase(const_iterator position) BOOST_CONTAINER_NOEXCEPT { return m_tree.erase(position); } //! Effects: Erases all elements in the container with key equivalent to x. @@ -1325,7 +1325,7 @@ class multimap //! Returns: Returns the number of erased elements. //! //! Complexity: log(size()) + count(k) - size_type erase(const key_type& x) + size_type erase(const key_type& x) BOOST_CONTAINER_NOEXCEPT { return m_tree.erase(x); } //! Effects: Erases all the elements in the range [first, last). @@ -1333,7 +1333,7 @@ class multimap //! Returns: Returns last. //! //! Complexity: log(size())+N where N is the distance from first to last. - iterator erase(const_iterator first, const_iterator last) + iterator erase(const_iterator first, const_iterator last) BOOST_CONTAINER_NOEXCEPT { return m_tree.erase(first, last); } //! Effects: Swaps the contents of *this and x. @@ -1349,7 +1349,7 @@ class multimap //! Postcondition: size() == 0. //! //! Complexity: linear in size(). - void clear() + void clear() BOOST_CONTAINER_NOEXCEPT { m_tree.clear(); } ////////////////////////////////////////////// @@ -1486,15 +1486,15 @@ inline void swap(multimap& x, multimap == true_type //!specialization for optimizations template struct has_trivial_destructor_after_move > { - static const bool value = has_trivial_destructor::value && has_trivial_destructor::value; + static const bool value = has_trivial_destructor_after_move::value && has_trivial_destructor_after_move::value; }; -*/ + namespace container { /// @endcond diff --git a/include/boost/container/scoped_allocator.hpp b/include/boost/container/scoped_allocator.hpp index c49c3cf..39fd4da 100644 --- a/include/boost/container/scoped_allocator.hpp +++ b/include/boost/container/scoped_allocator.hpp @@ -30,8 +30,8 @@ #include #include #include -#include - +#include +#include namespace boost { namespace container { @@ -1338,52 +1338,56 @@ class scoped_allocator_adaptor void construct_pair(Pair* p) { this->construct(container_detail::addressof(p->first)); - try { + BOOST_TRY{ this->construct(container_detail::addressof(p->second)); } - catch (...) { + BOOST_CATCH(...){ this->destroy(container_detail::addressof(p->first)); - throw; + BOOST_RETHROW } + BOOST_CATCH_END } template void construct_pair(Pair* p, BOOST_FWD_REF(U) x, BOOST_FWD_REF(V) y) { this->construct(container_detail::addressof(p->first), ::boost::forward(x)); - try { + BOOST_TRY{ this->construct(container_detail::addressof(p->second), ::boost::forward(y)); } - catch (...) { + BOOST_CATCH(...){ this->destroy(container_detail::addressof(p->first)); - throw; + BOOST_RETHROW } + BOOST_CATCH_END } template void construct_pair(Pair* p, const Pair2& pr) { this->construct(container_detail::addressof(p->first), pr.first); - try { + BOOST_TRY{ this->construct(container_detail::addressof(p->second), pr.second); } - catch (...) { + BOOST_CATCH(...){ this->destroy(container_detail::addressof(p->first)); - throw; + BOOST_RETHROW } + BOOST_CATCH_END } template void construct_pair(Pair* p, BOOST_RV_REF(Pair2) pr) { this->construct(container_detail::addressof(p->first), ::boost::move(pr.first)); - try { + BOOST_TRY{ this->construct(container_detail::addressof(p->second), ::boost::move(pr.second)); } - catch (...) { + BOOST_CATCH(...){ this->destroy(container_detail::addressof(p->first)); - throw; + BOOST_RETHROW } + BOOST_CATCH_END } //template diff --git a/include/boost/container/set.hpp b/include/boost/container/set.hpp index 3c6fcd5..0b49376 100644 --- a/include/boost/container/set.hpp +++ b/include/boost/container/set.hpp @@ -23,11 +23,11 @@ #include #include -#include -#include +#include +#include #include #include -#include +#include #ifndef BOOST_CONTAINER_PERFECT_FORWARDING #include #endif @@ -646,15 +646,15 @@ inline void swap(set& x, set& y) /// @cond } //namespace container { -/* + //!has_trivial_destructor_after_move<> == true_type //!specialization for optimizations template struct has_trivial_destructor_after_move > { - static const bool value = has_trivial_destructor::value && has_trivial_destructor::value; + static const bool value = has_trivial_destructor_after_move::value && has_trivial_destructor_after_move::value; }; -*/ + namespace container { // Forward declaration of operators < and ==, needed for friend declaration. @@ -757,10 +757,10 @@ class multiset //! //! Complexity: Linear in N. template - multiset( ordered_range_t ordered_range_, InputIterator first, InputIterator last + multiset( ordered_range_t, InputIterator first, InputIterator last , const Compare& comp = Compare() , const allocator_type& a = allocator_type()) - : m_tree(ordered_range_, first, last, comp, a) + : m_tree(ordered_range, first, last, comp, a) {} //! Effects: Copy constructs a multiset. @@ -1259,15 +1259,15 @@ inline void swap(multiset& x, multiset == true_type //!specialization for optimizations template struct has_trivial_destructor_after_move > { - static const bool value = has_trivial_destructor::value && has_trivial_destructor::value; + static const bool value = has_trivial_destructor_after_move::value && has_trivial_destructor_after_move::value; }; -*/ + namespace container { /// @endcond diff --git a/include/boost/container/slist.hpp b/include/boost/container/slist.hpp index c65a9a2..84cccda 100644 --- a/include/boost/container/slist.hpp +++ b/include/boost/container/slist.hpp @@ -19,8 +19,8 @@ #include #include -#include -#include +#include +#include #include #include #include @@ -140,9 +140,6 @@ class slist_const_iterator friend bool operator!= (const slist_const_iterator& l, const slist_const_iterator& r) { return l.m_it != r.m_it; } - IIterator &get() - { return this->m_it; } - const IIterator &get() const { return this->m_it; } }; @@ -181,9 +178,6 @@ class slist_iterator slist_iterator operator++(int) { IIterator tmp = this->m_it; ++*this; return slist_iterator(tmp); } - IIterator &get() - { return this->m_it; } - const IIterator &get() const { return this->m_it; } }; @@ -319,10 +313,10 @@ class slist //! Effects: Constructs a list taking the allocator as parameter. //! - //! Throws: If allocator_type's copy constructor throws. + //! Throws: Nothing //! //! Complexity: Constant. - explicit slist(const allocator_type& a) + explicit slist(const allocator_type& a) BOOST_CONTAINER_NOEXCEPT : AllocHolder(a) {} @@ -407,7 +401,7 @@ class slist //! Throws: Nothing. //! //! Complexity: Linear to the number of elements. - ~slist() + ~slist() BOOST_CONTAINER_NOEXCEPT {} //AllocHolder clears the slist //! Effects: Makes *this contain the same elements as x. @@ -511,7 +505,7 @@ class slist //! Throws: If allocator's copy constructor throws. //! //! Complexity: Constant. - allocator_type get_allocator() const + allocator_type get_allocator() const BOOST_CONTAINER_NOEXCEPT { return allocator_type(this->node_alloc()); } //! Effects: Returns a reference to the internal allocator. @@ -521,7 +515,7 @@ class slist //! Complexity: Constant. //! //! Note: Non-standard extension. - stored_allocator_type &get_stored_allocator() + stored_allocator_type &get_stored_allocator() BOOST_CONTAINER_NOEXCEPT { return this->node_alloc(); } //! Effects: Returns a reference to the internal allocator. @@ -531,7 +525,7 @@ class slist //! Complexity: Constant. //! //! Note: Non-standard extension. - const stored_allocator_type &get_stored_allocator() const + const stored_allocator_type &get_stored_allocator() const BOOST_CONTAINER_NOEXCEPT { return this->node_alloc(); } ////////////////////////////////////////////// @@ -547,7 +541,7 @@ class slist //! Throws: Nothing. //! //! Complexity: Constant. - iterator before_begin() + iterator before_begin() BOOST_CONTAINER_NOEXCEPT { return iterator(end()); } //! Effects: Returns a non-dereferenceable const_iterator @@ -557,7 +551,7 @@ class slist //! Throws: Nothing. //! //! Complexity: Constant. - const_iterator before_begin() const + const_iterator before_begin() const BOOST_CONTAINER_NOEXCEPT { return this->cbefore_begin(); } //! Effects: Returns an iterator to the first element contained in the list. @@ -565,7 +559,7 @@ class slist //! Throws: Nothing. //! //! Complexity: Constant. - iterator begin() + iterator begin() BOOST_CONTAINER_NOEXCEPT { return iterator(this->icont().begin()); } //! Effects: Returns a const_iterator to the first element contained in the list. @@ -573,7 +567,7 @@ class slist //! Throws: Nothing. //! //! Complexity: Constant. - const_iterator begin() const + const_iterator begin() const BOOST_CONTAINER_NOEXCEPT { return this->cbegin(); } //! Effects: Returns an iterator to the end of the list. @@ -581,7 +575,7 @@ class slist //! Throws: Nothing. //! //! Complexity: Constant. - iterator end() + iterator end() BOOST_CONTAINER_NOEXCEPT { return iterator(this->icont().end()); } //! Effects: Returns a const_iterator to the end of the list. @@ -589,7 +583,7 @@ class slist //! Throws: Nothing. //! //! Complexity: Constant. - const_iterator end() const + const_iterator end() const BOOST_CONTAINER_NOEXCEPT { return this->cend(); } //! Effects: Returns a non-dereferenceable const_iterator @@ -599,7 +593,7 @@ class slist //! Throws: Nothing. //! //! Complexity: Constant. - const_iterator cbefore_begin() const + const_iterator cbefore_begin() const BOOST_CONTAINER_NOEXCEPT { return const_iterator(end()); } //! Effects: Returns a const_iterator to the first element contained in the list. @@ -607,7 +601,7 @@ class slist //! Throws: Nothing. //! //! Complexity: Constant. - const_iterator cbegin() const + const_iterator cbegin() const BOOST_CONTAINER_NOEXCEPT { return const_iterator(this->non_const_icont().begin()); } //! Effects: Returns a const_iterator to the end of the list. @@ -615,7 +609,7 @@ class slist //! Throws: Nothing. //! //! Complexity: Constant. - const_iterator cend() const + const_iterator cend() const BOOST_CONTAINER_NOEXCEPT { return const_iterator(this->non_const_icont().end()); } //! Returns: The iterator to the element before i in the sequence. @@ -627,7 +621,7 @@ class slist //! Complexity: Linear to the number of elements before i. //! //! Note: Non-standard extension. - iterator previous(iterator p) + iterator previous(iterator p) BOOST_CONTAINER_NOEXCEPT { return iterator(this->icont().previous(p.get())); } //! Returns: The const_iterator to the element before i in the sequence. @@ -986,9 +980,9 @@ class slist //! //! Note: Iterators of values obtained from list x now point to elements of //! this list. Iterators of this list and all the references are not invalidated. - void splice_after(const_iterator prev_pos, slist& x) + void splice_after(const_iterator prev_pos, slist& x) BOOST_CONTAINER_NOEXCEPT { - BOOST_ASSERT(*this != x); + BOOST_ASSERT(this != &x); BOOST_ASSERT(this->node_alloc() == x.node_alloc()); this->icont().splice_after(prev_pos.get(), x.icont()); } @@ -1006,65 +1000,63 @@ class slist //! //! Note: Iterators of values obtained from list x now point to elements of //! this list. Iterators of this list and all the references are not invalidated. - void splice_after(const_iterator prev_pos, BOOST_RV_REF(slist) x) + void splice_after(const_iterator prev_pos, BOOST_RV_REF(slist) x) BOOST_CONTAINER_NOEXCEPT { this->splice_after(prev_pos, static_cast(x)); } //! Requires: prev_pos must be a valid iterator of this. //! i must point to an element contained in list x. + //! this' allocator and x's allocator shall compare equal. //! //! Effects: Transfers the value pointed by i, from list x to this list, //! after the element pointed by prev_pos. //! If prev_pos == prev or prev_pos == ++prev, this function is a null operation. //! - //! Throws: std::runtime_error if this' allocator and x's allocator - //! are not equal. + //! Throws: Nothing //! //! Complexity: Constant. //! //! Note: Iterators of values obtained from list x now point to elements of this //! list. Iterators of this list and all the references are not invalidated. - void splice_after(const_iterator prev_pos, slist& x, const_iterator prev) + void splice_after(const_iterator prev_pos, slist& x, const_iterator prev) BOOST_CONTAINER_NOEXCEPT { - BOOST_ASSERT(*this != x); BOOST_ASSERT(this->node_alloc() == x.node_alloc()); this->icont().splice_after(prev_pos.get(), x.icont(), prev.get()); } //! Requires: prev_pos must be a valid iterator of this. //! i must point to an element contained in list x. + //! this' allocator and x's allocator shall compare equal. //! //! Effects: Transfers the value pointed by i, from list x to this list, //! after the element pointed by prev_pos. //! If prev_pos == prev or prev_pos == ++prev, this function is a null operation. //! - //! Throws: std::runtime_error if this' allocator and x's allocator - //! are not equal. + //! Throws: Nothing //! //! Complexity: Constant. //! //! Note: Iterators of values obtained from list x now point to elements of this //! list. Iterators of this list and all the references are not invalidated. - void splice_after(const_iterator prev_pos, BOOST_RV_REF(slist) x, const_iterator prev) + void splice_after(const_iterator prev_pos, BOOST_RV_REF(slist) x, const_iterator prev) BOOST_CONTAINER_NOEXCEPT { this->splice_after(prev_pos, static_cast(x), prev); } //! Requires: prev_pos must be a valid iterator of this. //! before_first and before_last must be valid iterators of x. //! prev_pos must not be contained in [before_first, before_last) range. + //! this' allocator and x's allocator shall compare equal. //! //! Effects: Transfers the range [before_first + 1, before_last + 1) //! from list x to this list, after the element pointed by prev_pos. //! - //! Throws: std::runtime_error if this' allocator and x's allocator - //! are not equal. + //! Throws: Nothing //! //! Complexity: Linear to the number of transferred elements. //! //! Note: Iterators of values obtained from list x now point to elements of this //! list. Iterators of this list and all the references are not invalidated. void splice_after(const_iterator prev_pos, slist& x, - const_iterator before_first, const_iterator before_last) + const_iterator before_first, const_iterator before_last) BOOST_CONTAINER_NOEXCEPT { - BOOST_ASSERT(*this != x); BOOST_ASSERT(this->node_alloc() == x.node_alloc()); this->icont().splice_after (prev_pos.get(), x.icont(), before_first.get(), before_last.get()); @@ -1073,31 +1065,31 @@ class slist //! Requires: prev_pos must be a valid iterator of this. //! before_first and before_last must be valid iterators of x. //! prev_pos must not be contained in [before_first, before_last) range. + //! this' allocator and x's allocator shall compare equal. //! //! Effects: Transfers the range [before_first + 1, before_last + 1) //! from list x to this list, after the element pointed by prev_pos. //! - //! Throws: std::runtime_error if this' allocator and x's allocator - //! are not equal. + //! Throws: Nothing //! //! Complexity: Linear to the number of transferred elements. //! //! Note: Iterators of values obtained from list x now point to elements of this //! list. Iterators of this list and all the references are not invalidated. void splice_after(const_iterator prev_pos, BOOST_RV_REF(slist) x, - const_iterator before_first, const_iterator before_last) + const_iterator before_first, const_iterator before_last) BOOST_CONTAINER_NOEXCEPT { this->splice_after(prev_pos, static_cast(x), before_first, before_last); } //! Requires: prev_pos must be a valid iterator of this. //! before_first and before_last must be valid iterators of x. //! prev_pos must not be contained in [before_first, before_last) range. - //! n == std::distance(before_first, before_last) + //! n == std::distance(before_first, before_last). + //! this' allocator and x's allocator shall compare equal. //! //! Effects: Transfers the range [before_first + 1, before_last + 1) //! from list x to this list, after the element pointed by prev_pos. //! - //! Throws: std::runtime_error if this' allocator and x's allocator - //! are not equal. + //! Throws: Nothing //! //! Complexity: Constant. //! @@ -1105,9 +1097,8 @@ class slist //! list. Iterators of this list and all the references are not invalidated. void splice_after(const_iterator prev_pos, slist& x, const_iterator before_first, const_iterator before_last, - size_type n) + size_type n) BOOST_CONTAINER_NOEXCEPT { - BOOST_ASSERT(*this != x); BOOST_ASSERT(this->node_alloc() == x.node_alloc()); this->icont().splice_after (prev_pos.get(), x.icont(), before_first.get(), before_last.get(), n); @@ -1116,13 +1107,13 @@ class slist //! Requires: prev_pos must be a valid iterator of this. //! before_first and before_last must be valid iterators of x. //! prev_pos must not be contained in [before_first, before_last) range. - //! n == std::distance(before_first, before_last) + //! n == std::distance(before_first, before_last). + //! this' allocator and x's allocator shall compare equal. //! //! Effects: Transfers the range [before_first + 1, before_last + 1) //! from list x to this list, after the element pointed by prev_pos. //! - //! Throws: std::runtime_error if this' allocator and x's allocator - //! are not equal. + //! Throws: Nothing //! //! Complexity: Constant. //! @@ -1130,7 +1121,7 @@ class slist //! list. Iterators of this list and all the references are not invalidated. void splice_after(const_iterator prev_pos, BOOST_RV_REF(slist) x, const_iterator before_first, const_iterator before_last, - size_type n) + size_type n) BOOST_CONTAINER_NOEXCEPT { this->splice_after(prev_pos, static_cast(x), before_first, before_last, n); } //! Effects: Removes all the elements that compare equal to value. @@ -1163,9 +1154,9 @@ class slist //! Effects: Removes adjacent duplicate elements or adjacent //! elements that are equal from the list. //! - //! Throws: Nothing. + //! Throws: If comparison throws. //! - //! Complexity: Linear time (size()-1 comparisons calls to pred()). + //! Complexity: Linear time (size()-1 comparisons equality comparisons). //! //! Note: The relative order of elements that are not removed is unchanged, //! and iterators to elements that are not removed remain valid. @@ -1177,7 +1168,7 @@ class slist //! //! Throws: If pred throws. //! - //! Complexity: Linear time (size()-1 comparisons equality comparisons). + //! Complexity: Linear time (size()-1 comparisons calls to pred()). //! //! Note: The relative order of elements that are not removed is unchanged, //! and iterators to elements that are not removed remain valid. @@ -1195,7 +1186,7 @@ class slist //! that is, if an element from *this is equivalent to one from x, then the element //! from *this will precede the one from x. //! - //! Throws: Nothing. + //! Throws: If comparison throws. //! //! Complexity: This function is linear time: it performs at most //! size() + x.size() - 1 comparisons. @@ -1209,7 +1200,7 @@ class slist //! that is, if an element from *this is equivalent to one from x, then the element //! from *this will precede the one from x. //! - //! Throws: Nothing. + //! Throws: If comparison throws. //! //! Complexity: This function is linear time: it performs at most //! size() + x.size() - 1 comparisons. @@ -1224,7 +1215,7 @@ class slist //! in order into *this. The merge is stable; that is, if an element from *this is //! equivalent to one from x, then the element from *this will precede the one from x. //! - //! Throws: Nothing. + //! Throws: If comp throws. //! //! Complexity: This function is linear time: it performs at most //! size() + x.size() - 1 comparisons. @@ -1233,13 +1224,9 @@ class slist template void merge(slist& x, StrictWeakOrdering comp) { - if((NodeAlloc&)*this == (NodeAlloc&)x){ - this->icont().merge(x.icont(), - ValueCompareToNodeCompare(comp)); - } - else{ - throw std::runtime_error("list::merge called with unequal allocators"); - } + BOOST_ASSERT(this->node_alloc() == x.node_alloc()); + this->icont().merge(x.icont(), + ValueCompareToNodeCompare(comp)); } //! Requires: p must be a comparison function that induces a strict weak @@ -1250,7 +1237,7 @@ class slist //! in order into *this. The merge is stable; that is, if an element from *this is //! equivalent to one from x, then the element from *this will precede the one from x. //! - //! Throws: Nothing. + //! Throws: If comp throws. //! //! Complexity: This function is linear time: it performs at most //! size() + x.size() - 1 comparisons. @@ -1263,7 +1250,7 @@ class slist //! Effects: This function sorts the list *this according to std::less. //! The sort is stable, that is, the relative order of equivalent elements is preserved. //! - //! Throws: Nothing. + //! Throws: If comparison throws. //! //! Notes: Iterators and references are not invalidated. //! @@ -1275,7 +1262,7 @@ class slist //! Effects: This function sorts the list *this according to std::less. //! The sort is stable, that is, the relative order of equivalent elements is preserved. //! - //! Throws: Nothing. + //! Throws: If comp throws. //! //! Notes: Iterators and references are not invalidated. //! @@ -1297,7 +1284,7 @@ class slist //! Complexity: This function is linear time. //! //! Note: Iterators and references are not invalidated - void reverse() + void reverse() BOOST_CONTAINER_NOEXCEPT { this->icont().reverse(); } ////////////////////////////////////////////// @@ -1403,7 +1390,7 @@ class slist //! Throws: Nothing. //! //! Complexity: Linear to the number of elements before p. - iterator erase(const_iterator p) + iterator erase(const_iterator p) BOOST_CONTAINER_NOEXCEPT { return iterator(this->erase_after(previous(p))); } //! Requires: first and last must be valid iterator to elements in *this. @@ -1414,73 +1401,71 @@ class slist //! //! Complexity: Linear to the distance between first and last plus //! linear to the elements before first. - iterator erase(const_iterator first, const_iterator last) + iterator erase(const_iterator first, const_iterator last) BOOST_CONTAINER_NOEXCEPT { return iterator(this->erase_after(previous(first), last)); } //! Requires: p must point to an element contained - //! by the list. x != *this + //! by the list. x != *this. this' allocator and x's allocator shall compare equal //! //! Effects: Transfers all the elements of list x to this list, before the //! the element pointed by p. No destructors or copy constructors are called. //! - //! Throws: std::runtime_error if this' allocator and x's allocator - //! are not equal. + //! Throws: Nothing //! //! Complexity: Linear in distance(begin(), p), and linear in x.size(). //! //! Note: Iterators of values obtained from list x now point to elements of //! this list. Iterators of this list and all the references are not invalidated. - void splice(const_iterator p, slist& x) + void splice(const_iterator p, slist& x) BOOST_CONTAINER_NOEXCEPT { this->splice_after(this->previous(p), x); } //! Requires: p must point to an element contained - //! by the list. x != *this + //! by the list. x != *this. this' allocator and x's allocator shall compare equal //! //! Effects: Transfers all the elements of list x to this list, before the //! the element pointed by p. No destructors or copy constructors are called. //! - //! Throws: std::runtime_error if this' allocator and x's allocator - //! are not equal. + //! Throws: Nothing //! //! Complexity: Linear in distance(begin(), p), and linear in x.size(). //! //! Note: Iterators of values obtained from list x now point to elements of //! this list. Iterators of this list and all the references are not invalidated. - void splice(const_iterator p, BOOST_RV_REF(slist) x) + void splice(const_iterator p, BOOST_RV_REF(slist) x) BOOST_CONTAINER_NOEXCEPT { this->splice(p, static_cast(x)); } //! Requires: p must point to an element contained //! by this list. i must point to an element contained in list x. + //! this' allocator and x's allocator shall compare equal //! //! Effects: Transfers the value pointed by i, from list x to this list, //! before the the element pointed by p. No destructors or copy constructors are called. //! If p == i or p == ++i, this function is a null operation. //! - //! Throws: std::runtime_error if this' allocator and x's allocator - //! are not equal. + //! Throws: Nothing //! //! Complexity: Linear in distance(begin(), p), and in distance(x.begin(), i). //! //! Note: Iterators of values obtained from list x now point to elements of this //! list. Iterators of this list and all the references are not invalidated. - void splice(const_iterator p, slist& x, const_iterator i) + void splice(const_iterator p, slist& x, const_iterator i) BOOST_CONTAINER_NOEXCEPT { this->splice_after(this->previous(p), x, this->previous(i)); } //! Requires: p must point to an element contained //! by this list. i must point to an element contained in list x. + //! this' allocator and x's allocator shall compare equal. //! //! Effects: Transfers the value pointed by i, from list x to this list, //! before the the element pointed by p. No destructors or copy constructors are called. //! If p == i or p == ++i, this function is a null operation. //! - //! Throws: std::runtime_error if this' allocator and x's allocator - //! are not equal. + //! Throws: Nothing //! //! Complexity: Linear in distance(begin(), p), and in distance(x.begin(), i). //! //! Note: Iterators of values obtained from list x now point to elements of this //! list. Iterators of this list and all the references are not invalidated. - void splice(const_iterator p, BOOST_RV_REF(slist) x, const_iterator i) + void splice(const_iterator p, BOOST_RV_REF(slist) x, const_iterator i) BOOST_CONTAINER_NOEXCEPT { this->splice(p, static_cast(x), i); } //! Requires: p must point to an element contained @@ -1488,33 +1473,33 @@ class slist //! //! Effects: Transfers the range pointed by first and last from list x to this list, //! before the the element pointed by p. No destructors or copy constructors are called. + //! this' allocator and x's allocator shall compare equal. //! - //! Throws: std::runtime_error if this' allocator and x's allocator - //! are not equal. + //! Throws: Nothing //! //! Complexity: Linear in distance(begin(), p), in distance(x.begin(), first), //! and in distance(first, last). //! //! Note: Iterators of values obtained from list x now point to elements of this //! list. Iterators of this list and all the references are not invalidated. - void splice(const_iterator p, slist& x, const_iterator first, const_iterator last) + void splice(const_iterator p, slist& x, const_iterator first, const_iterator last) BOOST_CONTAINER_NOEXCEPT { this->splice_after(this->previous(p), x, this->previous(first), this->previous(last)); } //! Requires: p must point to an element contained //! by this list. first and last must point to elements contained in list x. + //! this' allocator and x's allocator shall compare equal //! //! Effects: Transfers the range pointed by first and last from list x to this list, //! before the the element pointed by p. No destructors or copy constructors are called. //! - //! Throws: std::runtime_error if this' allocator and x's allocator - //! are not equal. + //! Throws: Nothing //! //! Complexity: Linear in distance(begin(), p), in distance(x.begin(), first), //! and in distance(first, last). //! //! Note: Iterators of values obtained from list x now point to elements of this //! list. Iterators of this list and all the references are not invalidated. - void splice(const_iterator p, BOOST_RV_REF(slist) x, const_iterator first, const_iterator last) + void splice(const_iterator p, BOOST_RV_REF(slist) x, const_iterator first, const_iterator last) BOOST_CONTAINER_NOEXCEPT { this->splice(p, static_cast(x), first, last); } /// @cond @@ -1658,15 +1643,14 @@ inline void swap(slist& x, slist& y) /// @cond namespace boost { -/* + //!has_trivial_destructor_after_move<> == true_type //!specialization for optimizations template struct has_trivial_destructor_after_move > -{ - static const bool value = has_trivial_destructor::value; -}; -*/ + : public ::boost::has_trivial_destructor_after_move +{}; + namespace container { /// @endcond diff --git a/include/boost/container/stable_vector.hpp b/include/boost/container/stable_vector.hpp index 8d23672..539b2da 100644 --- a/include/boost/container/stable_vector.hpp +++ b/include/boost/container/stable_vector.hpp @@ -1,4 +1,4 @@ -////////////////////////////////////////////////////////////////////////////// + // // (C) Copyright Ion Gaztanaga 2008-2012. Distributed under the Boost // Software License, Version 1.0. (See accompanying file @@ -29,15 +29,16 @@ #include #include #include -#include -#include -#include +#include #include #include #include #include #include #include +#include +#include +#include #include //max #include #include @@ -303,7 +304,7 @@ struct index_traits static const size_type ExtraPointers = 3; //Stable vector stores metadata at the end of the index (node_base_ptr vector) with additional 3 pointers: // back() is this->index.back() - ExtraPointers; - // end node index is *(this->index.end() -3) + // end node index is *(this->index.end() - 3) // Node cache first is *(this->index.end() - 2); // Node cache last is this->index.back(); @@ -366,89 +367,6 @@ struct index_traits #endif //STABLE_VECTOR_ENABLE_INVARIANT_CHECKING }; -template::value> -struct allocator_version_wrapper -{ - typedef ::boost::container::container_detail::integral_constant - alloc_version; - - typedef typename Allocator::multiallocation_chain multiallocation_chain; - - typedef typename boost::container::allocator_traits::pointer pointer; - typedef typename boost::container::allocator_traits::size_type size_type; - - static pointer allocate_one(Allocator &a) - { return a.allocate_one(); } - - static void deallocate_one(Allocator &a, const pointer &p) - { a.deallocate_one(p); } - - static multiallocation_chain allocate_individual(Allocator &a, size_type n) - { return a.allocate_individual(n); } - - static void deallocate_individual(Allocator &a, multiallocation_chain &holder) - { a.deallocate_individual(::boost::move(holder)); } -}; - -template -struct allocator_version_wrapper -{ - typedef ::boost::container::container_detail::integral_constant - alloc_version; - - typedef typename boost::container::allocator_traits::pointer pointer; - typedef typename boost::container::allocator_traits::size_type size_type; - typedef typename boost::container::allocator_traits::value_type value_type; - - typedef typename boost::intrusive::pointer_traits:: - template rebind_pointer::type void_ptr; - typedef container_detail::basic_multiallocation_chain - multialloc_cached_counted; - typedef boost::container::container_detail:: - transform_multiallocation_chain - < multialloc_cached_counted, value_type> multiallocation_chain; - - static pointer allocate_one(Allocator &a) - { return a.allocate(1); } - - static void deallocate_one(Allocator &a, const pointer &p) - { a.deallocate(p, 1); } - - static void deallocate_individual(Allocator &a, multiallocation_chain &holder) - { - while(!holder.empty()){ - a.deallocate(holder.pop_front(), 1); - } - } - - struct allocate_individual_rollback - { - allocate_individual_rollback(Allocator &a, multiallocation_chain &chain) - : mr_a(a), mr_chain(chain) - {} - - ~allocate_individual_rollback() - { - allocator_version_wrapper::deallocate_individual(mr_a, mr_chain); - } - - Allocator &mr_a; - multiallocation_chain &mr_chain; - }; - - static multiallocation_chain allocate_individual(Allocator &a, size_type n) - { - multiallocation_chain m; - multiallocation_chain m_ret; - allocate_individual_rollback rollback(a, m); - while(n--){ - m.push_front(a.allocate(1)); - } - m.swap(m_ret); - return ::boost::move(m_ret); - } -}; - } //namespace stable_vector_detail #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED) @@ -555,20 +473,21 @@ class stable_vector template portable_rebind_alloc ::type node_allocator_type; - typedef stable_vector_detail::allocator_version_wrapper allocator_version_wrapper_t; - typedef typename allocator_version_wrapper_t::multiallocation_chain multiallocation_chain; + typedef ::boost::container::container_detail:: + allocator_version_traits allocator_version_traits_t; + typedef typename allocator_version_traits_t::multiallocation_chain multiallocation_chain; node_ptr allocate_one() - { return allocator_version_wrapper_t::allocate_one(this->priv_node_alloc()); } + { return allocator_version_traits_t::allocate_one(this->priv_node_alloc()); } void deallocate_one(const node_ptr &p) - { allocator_version_wrapper_t::deallocate_one(this->priv_node_alloc(), p); } + { allocator_version_traits_t::deallocate_one(this->priv_node_alloc(), p); } - multiallocation_chain allocate_individual(typename allocator_traits_type::size_type n) - { return allocator_version_wrapper_t::allocate_individual(this->priv_node_alloc(), n); } + void allocate_individual(typename allocator_traits_type::size_type n, multiallocation_chain &m) + { allocator_version_traits_t::allocate_individual(this->priv_node_alloc(), n, m); } void deallocate_individual(multiallocation_chain &holder) - { allocator_version_wrapper_t::deallocate_individual(this->priv_node_alloc(), holder); } + { allocator_version_traits_t::deallocate_individual(this->priv_node_alloc(), holder); } friend class stable_vector_detail::clear_on_destroy; typedef stable_vector_detail::iterator @@ -633,10 +552,10 @@ class stable_vector //! Effects: Constructs a stable_vector taking the allocator as parameter. //! - //! Throws: If allocator_type's copy constructor throws. + //! Throws: Nothing //! //! Complexity: Constant. - explicit stable_vector(const allocator_type& al) + explicit stable_vector(const allocator_type& al) BOOST_CONTAINER_NOEXCEPT : internal_data(al), index(al) { STABLE_VECTOR_CHECK_INVARIANT; @@ -904,7 +823,7 @@ class stable_vector //! Throws: Nothing. //! //! Complexity: Constant. - iterator begin() + iterator begin() BOOST_CONTAINER_NOEXCEPT { return (this->index.empty()) ? this->end(): iterator(node_ptr_traits::static_cast_from(this->index.front())); } //! Effects: Returns a const_iterator to the first element contained in the stable_vector. @@ -912,7 +831,7 @@ class stable_vector //! Throws: Nothing. //! //! Complexity: Constant. - const_iterator begin()const + const_iterator begin() const BOOST_CONTAINER_NOEXCEPT { return (this->index.empty()) ? this->cend() : const_iterator(node_ptr_traits::static_cast_from(this->index.front())) ; } //! Effects: Returns an iterator to the end of the stable_vector. @@ -920,7 +839,7 @@ class stable_vector //! Throws: Nothing. //! //! Complexity: Constant. - iterator end() + iterator end() BOOST_CONTAINER_NOEXCEPT { return iterator(this->priv_get_end_node()); } //! Effects: Returns a const_iterator to the end of the stable_vector. @@ -928,7 +847,7 @@ class stable_vector //! Throws: Nothing. //! //! Complexity: Constant. - const_iterator end() const + const_iterator end() const BOOST_CONTAINER_NOEXCEPT { return const_iterator(this->priv_get_end_node()); } //! Effects: Returns a reverse_iterator pointing to the beginning @@ -937,7 +856,7 @@ class stable_vector //! Throws: Nothing. //! //! Complexity: Constant. - reverse_iterator rbegin() + reverse_iterator rbegin() BOOST_CONTAINER_NOEXCEPT { return reverse_iterator(this->end()); } //! Effects: Returns a const_reverse_iterator pointing to the beginning @@ -946,7 +865,7 @@ class stable_vector //! Throws: Nothing. //! //! Complexity: Constant. - const_reverse_iterator rbegin() const + const_reverse_iterator rbegin() const BOOST_CONTAINER_NOEXCEPT { return const_reverse_iterator(this->end()); } //! Effects: Returns a reverse_iterator pointing to the end @@ -955,7 +874,7 @@ class stable_vector //! Throws: Nothing. //! //! Complexity: Constant. - reverse_iterator rend() + reverse_iterator rend() BOOST_CONTAINER_NOEXCEPT { return reverse_iterator(this->begin()); } //! Effects: Returns a const_reverse_iterator pointing to the end @@ -964,7 +883,7 @@ class stable_vector //! Throws: Nothing. //! //! Complexity: Constant. - const_reverse_iterator rend()const + const_reverse_iterator rend() const BOOST_CONTAINER_NOEXCEPT { return const_reverse_iterator(this->begin()); } //! Effects: Returns a const_iterator to the first element contained in the stable_vector. @@ -972,7 +891,7 @@ class stable_vector //! Throws: Nothing. //! //! Complexity: Constant. - const_iterator cbegin() const + const_iterator cbegin() const BOOST_CONTAINER_NOEXCEPT { return this->begin(); } //! Effects: Returns a const_iterator to the end of the stable_vector. @@ -980,7 +899,7 @@ class stable_vector //! Throws: Nothing. //! //! Complexity: Constant. - const_iterator cend()const + const_iterator cend() const BOOST_CONTAINER_NOEXCEPT { return this->end(); } //! Effects: Returns a const_reverse_iterator pointing to the beginning @@ -989,7 +908,7 @@ class stable_vector //! Throws: Nothing. //! //! Complexity: Constant. - const_reverse_iterator crbegin() const + const_reverse_iterator crbegin() const BOOST_CONTAINER_NOEXCEPT { return this->rbegin(); } //! Effects: Returns a const_reverse_iterator pointing to the end @@ -998,7 +917,7 @@ class stable_vector //! Throws: Nothing. //! //! Complexity: Constant. - const_reverse_iterator crend()const + const_reverse_iterator crend()const BOOST_CONTAINER_NOEXCEPT { return this->rend(); } ////////////////////////////////////////////// @@ -1012,7 +931,7 @@ class stable_vector //! Throws: Nothing. //! //! Complexity: Constant. - bool empty() const + bool empty() const BOOST_CONTAINER_NOEXCEPT { return this->index.size() <= ExtraPointers; } //! Effects: Returns the number of the elements contained in the stable_vector. @@ -1020,7 +939,7 @@ class stable_vector //! Throws: Nothing. //! //! Complexity: Constant. - size_type size() const + size_type size() const BOOST_CONTAINER_NOEXCEPT { const size_type index_size = this->index.size(); return index_size ? (index_size - ExtraPointers) : 0; @@ -1031,7 +950,7 @@ class stable_vector //! Throws: Nothing. //! //! Complexity: Constant. - size_type max_size() const + size_type max_size() const BOOST_CONTAINER_NOEXCEPT { return this->index.max_size() - ExtraPointers; } //! Effects: Inserts or erases elements at the end such that @@ -1071,7 +990,7 @@ class stable_vector //! Throws: Nothing. //! //! Complexity: Constant. - size_type capacity() const + size_type capacity() const BOOST_CONTAINER_NOEXCEPT { const size_type index_size = this->index.size(); BOOST_ASSERT(!index_size || index_size >= ExtraPointers); @@ -1094,7 +1013,7 @@ class stable_vector if(n > this->max_size()) throw std::bad_alloc(); - size_type size_ = this->size(); + size_type sz = this->size(); size_type old_capacity = this->capacity(); if(n > old_capacity){ index_traits_type::initialize_end_node(this->index, this->internal_data.end_node, n); @@ -1106,8 +1025,8 @@ class stable_vector index_traits_type::fix_up_pointers_from(this->index, this->index.begin()); } //Now fill pool if data is not enough - if((n - size_) > this->internal_data.pool_size){ - this->priv_increase_pool((n - size_) - this->internal_data.pool_size); + if((n - sz) > this->internal_data.pool_size){ + this->priv_increase_pool((n - sz) - this->internal_data.pool_size); } } } @@ -1156,7 +1075,7 @@ class stable_vector //! Throws: Nothing. //! //! Complexity: Constant. - reference front() + reference front() BOOST_CONTAINER_NOEXCEPT { return static_cast(*this->index.front()).value; } //! Requires: !empty() @@ -1167,7 +1086,7 @@ class stable_vector //! Throws: Nothing. //! //! Complexity: Constant. - const_reference front() const + const_reference front() const BOOST_CONTAINER_NOEXCEPT { return static_cast(*this->index.front()).value; } //! Requires: !empty() @@ -1178,7 +1097,7 @@ class stable_vector //! Throws: Nothing. //! //! Complexity: Constant. - reference back() + reference back() BOOST_CONTAINER_NOEXCEPT { return static_cast(*this->index[this->size() - ExtraPointers]).value; } //! Requires: !empty() @@ -1189,7 +1108,7 @@ class stable_vector //! Throws: Nothing. //! //! Complexity: Constant. - const_reference back()const + const_reference back() const BOOST_CONTAINER_NOEXCEPT { return static_cast(*this->index[this->size() - ExtraPointers]).value; } //! Requires: size() > n. @@ -1200,7 +1119,7 @@ class stable_vector //! Throws: Nothing. //! //! Complexity: Constant. - reference operator[](size_type n) + reference operator[](size_type n) BOOST_CONTAINER_NOEXCEPT { return static_cast(*this->index[n]).value; } //! Requires: size() > n. @@ -1211,7 +1130,7 @@ class stable_vector //! Throws: Nothing. //! //! Complexity: Constant. - const_reference operator[](size_type n)const + const_reference operator[](size_type n) const BOOST_CONTAINER_NOEXCEPT { return static_cast(*this->index[n]).value; } //! Requires: size() > n. @@ -1400,7 +1319,7 @@ class stable_vector //! //! Complexity: Linear to std::distance [first, last). template - iterator insert(const_iterator position,InputIterator first, InputIterator last + iterator insert(const_iterator position, InputIterator first, InputIterator last #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED) , typename container_detail::enable_if_c < !container_detail::is_convertible::value @@ -1426,8 +1345,8 @@ class stable_vector >::type * = 0 ) { - const size_type num_new = (size_type)std::distance(first,last); - const size_type pos = static_cast(position - this->cbegin()); + const size_type num_new = static_cast(std::distance(first, last)); + const size_type pos = static_cast(position - this->cbegin()); if(num_new){ //Fills the node pool and inserts num_new null pointers in pos. //If a new buffer was needed fixes up pointers up to pos so @@ -1463,7 +1382,7 @@ class stable_vector //! Throws: Nothing. //! //! Complexity: Constant time. - void pop_back() + void pop_back() BOOST_CONTAINER_NOEXCEPT { this->erase(--this->cend()); } //! Effects: Erases the element at position pos. @@ -1472,15 +1391,15 @@ class stable_vector //! //! Complexity: Linear to the elements between pos and the //! last element. Constant if pos is the last element. - iterator erase(const_iterator position) + iterator erase(const_iterator position) BOOST_CONTAINER_NOEXCEPT { STABLE_VECTOR_CHECK_INVARIANT; - difference_type d = position - this->cbegin(); - index_iterator it = this->index.begin() + d; + const size_type d = position - this->cbegin(); + index_iterator it = this->index.begin() + d; this->priv_delete_node(position.node_pointer()); it = this->index.erase(it); index_traits_type::fix_up_pointers_from(this->index, it); - return this->begin()+d; + return iterator(node_ptr_traits::static_cast_from(*it)); } //! Effects: Erases the elements pointed by [first, last). @@ -1489,19 +1408,30 @@ class stable_vector //! //! Complexity: Linear to the distance between first and last //! plus linear to the elements between pos and the last element. - iterator erase(const_iterator first, const_iterator last) + iterator erase(const_iterator first, const_iterator last) BOOST_CONTAINER_NOEXCEPT { STABLE_VECTOR_CHECK_INVARIANT; - difference_type d1 = first - this->cbegin(), d2 = last - this->cbegin(); - if(d1 != d2){ - index_iterator it1(this->index.begin() + d1), it2(it1 + (d2 - d1)); - for(index_iterator it = it1; it != it2; ++it){ - this->priv_delete_node(node_ptr_traits::static_cast_from(*it)); + const const_iterator cbeg(this->cbegin()); + const size_type d1 = static_cast(first - cbeg), + d2 = static_cast(last - cbeg); + size_type d_dif = d2 - d1; + if(d_dif){ + multiallocation_chain holder; + const index_iterator it1(this->index.begin() + d1); + const index_iterator it2(it1 + d_dif); + index_iterator it(it1); + while(d_dif--){ + node_base_ptr &nb = *it; + ++it; + node_type &n = *node_ptr_traits::static_cast_from(nb); + this->priv_destroy_node(n); + holder.push_back(node_ptr_traits::pointer_to(n)); } + this->priv_put_in_pool(holder); const index_iterator e = this->index.erase(it1, it2); index_traits_type::fix_up_pointers_from(this->index, e); } - return iterator(this->begin() + d1); + return iterator(last.node_pointer()); } //! Effects: Swaps the contents of *this and x. @@ -1524,7 +1454,7 @@ class stable_vector //! Throws: Nothing. //! //! Complexity: Linear to the number of elements in the stable_vector. - void clear() + void clear() BOOST_CONTAINER_NOEXCEPT { this->erase(this->cbegin(),this->cend()); } /// @cond @@ -1666,7 +1596,8 @@ class stable_vector , node_ptr_traits::static_cast_from(pool_first_ref) , node_ptr_traits::static_cast_from(pool_last_ref) , internal_data.pool_size); - multiallocation_chain m (this->allocate_individual(n)); + multiallocation_chain m; + this->allocate_individual(n, m); holder.splice_after(holder.before_begin(), m, m.before_begin(), m.last(), n); this->internal_data.pool_size += n; std::pair data(holder.extract_data()); @@ -1690,11 +1621,25 @@ class stable_vector pool_last_ref = ret.second; } + void priv_put_in_pool(multiallocation_chain &ch) + { + node_base_ptr &pool_first_ref = *(this->index.end()-(ExtraPointers-1)); + node_base_ptr &pool_last_ref = this->index.back(); + ch.incorporate_after( ch.before_begin() + , node_ptr_traits::static_cast_from(pool_first_ref) + , node_ptr_traits::static_cast_from(pool_last_ref) + , internal_data.pool_size); + this->internal_data.pool_size = ch.size(); + const std::pair ret(ch.extract_data()); + pool_first_ref = ret.first; + pool_last_ref = ret.second; + } + node_ptr priv_get_from_pool() { //Precondition: index is not empty BOOST_ASSERT(!this->index.empty()); - node_base_ptr &pool_first_ref = *(this->index.end() - 2); + node_base_ptr &pool_first_ref = *(this->index.end() - (ExtraPointers-1)); node_base_ptr &pool_last_ref = this->index.back(); multiallocation_chain holder; holder.incorporate_after( holder.before_begin() @@ -1707,9 +1652,9 @@ class stable_vector pool_first_ref = pool_last_ref = node_ptr(); } else{ - std::pair data(holder.extract_data()); + const std::pair data(holder.extract_data()); pool_first_ref = data.first; - pool_last_ref = data.second; + pool_last_ref = data.second; } return ret; } @@ -1720,11 +1665,16 @@ class stable_vector (static_cast(const_cast(this->internal_data.end_node))); } - void priv_delete_node(const node_ptr &n) + void priv_destroy_node(const node_type &n) { allocator_traits:: - destroy(this->priv_node_alloc(), container_detail::addressof(n->value)); - static_cast(container_detail::to_raw_pointer(n))->~node_base_type(); + destroy(this->priv_node_alloc(), container_detail::addressof(n.value)); + static_cast(&n)->~node_base_type(); + } + + void priv_delete_node(const node_ptr &n) + { + this->priv_destroy_node(*n); this->priv_put_in_pool(n); } @@ -1776,7 +1726,7 @@ class stable_vector } size_type n = this->capacity() - this->size(); - node_base_ptr &pool_first_ref = *(index_ref.end() - 2); + node_base_ptr &pool_first_ref = *(index_ref.end() - (ExtraPointers-1)); node_base_ptr &pool_last_ref = index_ref.back(); multiallocation_chain holder; holder.incorporate_after( holder.before_begin() @@ -1886,6 +1836,17 @@ void swap(stable_vector& x,stable_vector& y) /// @endcond +/* + +//!has_trivial_destructor_after_move<> == true_type +//!specialization for optimizations +template +struct has_trivial_destructor_after_move > + : public has_trivial_destructor_after_move::value +{}; + +*/ + }} #include diff --git a/include/boost/container/string.hpp b/include/boost/container/string.hpp index 7cbd447..40b2397 100644 --- a/include/boost/container/string.hpp +++ b/include/boost/container/string.hpp @@ -44,11 +44,13 @@ #include #include #include +#include #include -#include +#include #include #include #include +#include #include #include @@ -81,8 +83,8 @@ namespace container_detail { // an exception-safe version of basic_string. The constructor allocates, // but does not initialize, a block of memory. The destructor // deallocates, but does not destroy elements within, a block of -// memory. The destructor assumes that the memory either is the internal buffer, -// or else points to a block of memory that was allocated using _String_base's +// memory. The destructor assumes that the memory either is the internal buffer, +// or else points to a block of memory that was allocated using string_base's // allocator and whose size is this->m_storage. template class basic_string_base @@ -92,7 +94,6 @@ class basic_string_base typedef allocator_traits allocator_traits_type; public: typedef Allocator allocator_type; - //! The stored allocator type typedef allocator_type stored_allocator_type; typedef typename allocator_traits_type::pointer pointer; typedef typename allocator_traits_type::value_type value_type; @@ -284,36 +285,8 @@ class basic_string_base reuse = pointer(); command &= ~(expand_fwd | expand_bwd); } - return this->allocation_command - (command, limit_size, preferred_size, received_size, reuse, alloc_version()); - } - - std::pair - allocation_command(allocation_type command, - size_type limit_size, - size_type preferred_size, - size_type &received_size, - const pointer &reuse, - allocator_v1) - { - (void)limit_size; - (void)reuse; - if(!(command & allocate_new)) - return std::pair(pointer(), false); - received_size = preferred_size; - return std::make_pair(this->alloc().allocate(received_size), false); - } - - std::pair - allocation_command(allocation_type command, - size_type limit_size, - size_type preferred_size, - size_type &received_size, - pointer reuse, - allocator_v2) - { - return this->alloc().allocation_command(command, limit_size, preferred_size, - received_size, reuse); + return container_detail::allocator_version_traits::allocation_command + (this->alloc(), command, limit_size, preferred_size, received_size, reuse); } size_type next_capacity(size_type additional_objects) const @@ -336,11 +309,9 @@ class basic_string_base void destroy(pointer p, size_type n) { - for(; n--; ++p){ - allocator_traits_type::destroy - ( this->alloc() - , container_detail::to_raw_pointer(p) - ); + value_type *raw_p = container_detail::to_raw_pointer(p); + for(; n--; ++raw_p){ + allocator_traits_type::destroy( this->alloc(), raw_p); } } @@ -569,37 +540,26 @@ class basic_string /// @endcond public: - - //! The allocator type - typedef Allocator allocator_type; - //! The stored allocator type - typedef allocator_type stored_allocator_type; - //! The type of object, CharT, stored in the string - typedef CharT value_type; - //! The second template parameter Traits - typedef Traits traits_type; - //! Pointer to CharT - typedef typename allocator_traits_type::pointer pointer; - //! Const pointer to CharT - typedef typename allocator_traits_type::const_pointer const_pointer; - //! Reference to CharT - typedef typename allocator_traits_type::reference reference; - //! Const reference to CharT - typedef typename allocator_traits_type::const_reference const_reference; - //! An unsigned integral type - typedef typename allocator_traits_type::size_type size_type; - //! A signed integral type - typedef typename allocator_traits_type::difference_type difference_type; - //! Iterator used to iterate through a string. It's a Random Access Iterator - typedef pointer iterator; - //! Const iterator used to iterate through a string. It's a Random Access Iterator - typedef const_pointer const_iterator; - //! Iterator used to iterate backwards through a string - typedef std::reverse_iterator reverse_iterator; - //! Const iterator used to iterate backwards through a string - typedef std::reverse_iterator const_reverse_iterator; - //! The largest possible value of type size_type. That is, size_type(-1). - static const size_type npos; + ////////////////////////////////////////////// + // + // types + // + ////////////////////////////////////////////// + typedef Traits traits_type; + typedef CharT value_type; + typedef typename ::boost::container::allocator_traits::pointer pointer; + typedef typename ::boost::container::allocator_traits::const_pointer const_pointer; + typedef typename ::boost::container::allocator_traits::reference reference; + typedef typename ::boost::container::allocator_traits::const_reference const_reference; + typedef typename ::boost::container::allocator_traits::size_type size_type; + typedef typename ::boost::container::allocator_traits::difference_type difference_type; + typedef Allocator allocator_type; + typedef BOOST_CONTAINER_IMPDEF(allocator_type) stored_allocator_type; + typedef BOOST_CONTAINER_IMPDEF(pointer) iterator; + typedef BOOST_CONTAINER_IMPDEF(const_pointer) const_iterator; + typedef BOOST_CONTAINER_IMPDEF(std::reverse_iterator) reverse_iterator; + typedef BOOST_CONTAINER_IMPDEF(std::reverse_iterator) const_reverse_iterator; + static const size_type npos = size_type(-1); /// @cond private: @@ -611,6 +571,11 @@ class basic_string /// @endcond public: // Constructor, destructor, assignment. + ////////////////////////////////////////////// + // + // construct/copy/destroy + // + ////////////////////////////////////////////// /// @cond struct reserve_t {}; @@ -634,8 +599,8 @@ class basic_string //! Effects: Constructs a basic_string taking the allocator as parameter. //! - //! Throws: If allocator_type's copy constructor throws. - explicit basic_string(const allocator_type& a) + //! Throws: Nothing + explicit basic_string(const allocator_type& a) BOOST_CONTAINER_NOEXCEPT : base_t(a) { this->priv_terminate_string(); } @@ -653,10 +618,10 @@ class basic_string //! Effects: Move constructor. Moves s's resources to *this. //! - //! Throws: If allocator_type's copy constructor throws. + //! Throws: Nothing. //! //! Complexity: Constant. - basic_string(BOOST_RV_REF(basic_string) s) + basic_string(BOOST_RV_REF(basic_string) s) BOOST_CONTAINER_NOEXCEPT : base_t(boost::move((base_t&)s)) {} @@ -693,7 +658,7 @@ class basic_string //! Effects: Constructs a basic_string taking the allocator as parameter, //! and is initialized by a specific number of characters of the s string. basic_string(const basic_string& s, size_type pos, size_type n = npos, - const allocator_type& a = allocator_type()) + const allocator_type& a = allocator_type()) : base_t(a) { this->priv_terminate_string(); @@ -706,8 +671,7 @@ class basic_string //! Effects: Constructs a basic_string taking the allocator as parameter, //! and is initialized by a specific number of characters of the s c-string. - basic_string(const CharT* s, size_type n, - const allocator_type& a = allocator_type()) + basic_string(const CharT* s, size_type n, const allocator_type& a = allocator_type()) : base_t(a) { this->priv_terminate_string(); @@ -716,8 +680,7 @@ class basic_string //! Effects: Constructs a basic_string taking the allocator as parameter, //! and is initialized by the null-terminated s c-string. - basic_string(const CharT* s, - const allocator_type& a = allocator_type()) + basic_string(const CharT* s, const allocator_type& a = allocator_type()) : base_t(a) { this->priv_terminate_string(); @@ -726,8 +689,7 @@ class basic_string //! Effects: Constructs a basic_string taking the allocator as parameter, //! and is initialized by n copies of c. - basic_string(size_type n, CharT c, - const allocator_type& a = allocator_type()) + basic_string(size_type n, CharT c, const allocator_type& a = allocator_type()) : base_t(a) { this->priv_terminate_string(); @@ -737,8 +699,7 @@ class basic_string //! Effects: Constructs a basic_string taking the allocator as parameter, //! and a range of iterators. template - basic_string(InputIterator f, InputIterator l, - const allocator_type& a = allocator_type()) + basic_string(InputIterator f, InputIterator l, const allocator_type& a = allocator_type()) : base_t(a) { this->priv_terminate_string(); @@ -750,7 +711,7 @@ class basic_string //! Throws: Nothing. //! //! Complexity: Constant. - ~basic_string() + ~basic_string() BOOST_CONTAINER_NOEXCEPT {} //! Effects: Copy constructs a string. @@ -784,7 +745,7 @@ class basic_string //! Throws: If allocator_type's copy constructor throws. //! //! Complexity: Constant. - basic_string& operator=(BOOST_RV_REF(basic_string) x) + basic_string& operator=(BOOST_RV_REF(basic_string) x) BOOST_CONTAINER_NOEXCEPT { if (&x != this){ allocator_type &this_alloc = this->alloc(); @@ -815,114 +776,12 @@ class basic_string basic_string& operator=(CharT c) { return this->assign(static_cast(1), c); } - //! Effects: Returns an iterator to the first element contained in the vector. - //! - //! Throws: Nothing. - //! - //! Complexity: Constant. - iterator begin() - { return this->priv_addr(); } - - //! Effects: Returns a const_iterator to the first element contained in the vector. - //! - //! Throws: Nothing. - //! - //! Complexity: Constant. - const_iterator begin() const - { return this->priv_addr(); } - - //! Effects: Returns a const_iterator to the first element contained in the vector. - //! - //! Throws: Nothing. - //! - //! Complexity: Constant. - const_iterator cbegin() const - { return this->priv_addr(); } - - //! Effects: Returns an iterator to the end of the vector. - //! - //! Throws: Nothing. - //! - //! Complexity: Constant. - iterator end() - { return this->priv_end_addr(); } - - //! Effects: Returns a const_iterator to the end of the vector. - //! - //! Throws: Nothing. - //! - //! Complexity: Constant. - const_iterator end() const - { return this->priv_end_addr(); } - - //! Effects: Returns a const_iterator to the end of the vector. - //! - //! Throws: Nothing. - //! - //! Complexity: Constant. - const_iterator cend() const - { return this->priv_end_addr(); } - - //! Effects: Returns a reverse_iterator pointing to the beginning - //! of the reversed vector. - //! - //! Throws: Nothing. - //! - //! Complexity: Constant. - reverse_iterator rbegin() - { return reverse_iterator(this->priv_end_addr()); } - - //! Effects: Returns a const_reverse_iterator pointing to the beginning - //! of the reversed vector. - //! - //! Throws: Nothing. - //! - //! Complexity: Constant. - const_reverse_iterator rbegin() const - { return this->crbegin(); } - - //! Effects: Returns a const_reverse_iterator pointing to the beginning - //! of the reversed vector. - //! - //! Throws: Nothing. - //! - //! Complexity: Constant. - const_reverse_iterator crbegin() const - { return const_reverse_iterator(this->priv_end_addr()); } - - //! Effects: Returns a reverse_iterator pointing to the end - //! of the reversed vector. - //! - //! Throws: Nothing. - //! - //! Complexity: Constant. - reverse_iterator rend() - { return reverse_iterator(this->priv_addr()); } - - //! Effects: Returns a const_reverse_iterator pointing to the end - //! of the reversed vector. - //! - //! Throws: Nothing. - //! - //! Complexity: Constant. - const_reverse_iterator rend() const - { return this->crend(); } - - //! Effects: Returns a const_reverse_iterator pointing to the end - //! of the reversed vector. - //! - //! Throws: Nothing. - //! - //! Complexity: Constant. - const_reverse_iterator crend() const - { return const_reverse_iterator(this->priv_addr()); } - //! Effects: Returns a copy of the internal allocator. //! //! Throws: If allocator's copy constructor throws. //! //! Complexity: Constant. - allocator_type get_allocator() const + allocator_type get_allocator() const BOOST_CONTAINER_NOEXCEPT { return this->alloc(); } //! Effects: Returns a reference to the internal allocator. @@ -945,12 +804,134 @@ class basic_string const stored_allocator_type &get_stored_allocator() const BOOST_CONTAINER_NOEXCEPT { return this->alloc(); } + ////////////////////////////////////////////// + // + // iterators + // + ////////////////////////////////////////////// + + //! Effects: Returns an iterator to the first element contained in the vector. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + iterator begin() BOOST_CONTAINER_NOEXCEPT + { return this->priv_addr(); } + + //! Effects: Returns a const_iterator to the first element contained in the vector. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_iterator begin() const BOOST_CONTAINER_NOEXCEPT + { return this->priv_addr(); } + + //! Effects: Returns an iterator to the end of the vector. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + iterator end() BOOST_CONTAINER_NOEXCEPT + { return this->priv_end_addr(); } + + //! Effects: Returns a const_iterator to the end of the vector. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_iterator end() const BOOST_CONTAINER_NOEXCEPT + { return this->priv_end_addr(); } + + //! Effects: Returns a reverse_iterator pointing to the beginning + //! of the reversed vector. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + reverse_iterator rbegin() BOOST_CONTAINER_NOEXCEPT + { return reverse_iterator(this->priv_end_addr()); } + + //! Effects: Returns a const_reverse_iterator pointing to the beginning + //! of the reversed vector. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_reverse_iterator rbegin() const BOOST_CONTAINER_NOEXCEPT + { return this->crbegin(); } + + //! Effects: Returns a reverse_iterator pointing to the end + //! of the reversed vector. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + reverse_iterator rend() BOOST_CONTAINER_NOEXCEPT + { return reverse_iterator(this->priv_addr()); } + + //! Effects: Returns a const_reverse_iterator pointing to the end + //! of the reversed vector. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_reverse_iterator rend() const BOOST_CONTAINER_NOEXCEPT + { return this->crend(); } + + //! Effects: Returns a const_iterator to the first element contained in the vector. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_iterator cbegin() const BOOST_CONTAINER_NOEXCEPT + { return this->priv_addr(); } + + //! Effects: Returns a const_iterator to the end of the vector. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_iterator cend() const BOOST_CONTAINER_NOEXCEPT + { return this->priv_end_addr(); } + + //! Effects: Returns a const_reverse_iterator pointing to the beginning + //! of the reversed vector. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_reverse_iterator crbegin() const BOOST_CONTAINER_NOEXCEPT + { return const_reverse_iterator(this->priv_end_addr()); } + + //! Effects: Returns a const_reverse_iterator pointing to the end + //! of the reversed vector. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_reverse_iterator crend() const BOOST_CONTAINER_NOEXCEPT + { return const_reverse_iterator(this->priv_addr()); } + + ////////////////////////////////////////////// + // + // capacity + // + ////////////////////////////////////////////// + + //! Effects: Returns true if the vector contains no elements. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + bool empty() const BOOST_CONTAINER_NOEXCEPT + { return !this->priv_size(); } + //! Effects: Returns the number of the elements contained in the vector. //! //! Throws: Nothing. //! //! Complexity: Constant. - size_type size() const + size_type size() const BOOST_CONTAINER_NOEXCEPT { return this->priv_size(); } //! Effects: Returns the number of the elements contained in the vector. @@ -958,7 +939,7 @@ class basic_string //! Throws: Nothing. //! //! Complexity: Constant. - size_type length() const + size_type length() const BOOST_CONTAINER_NOEXCEPT { return this->size(); } //! Effects: Returns the largest possible size of the vector. @@ -966,7 +947,7 @@ class basic_string //! Throws: Nothing. //! //! Complexity: Constant. - size_type max_size() const + size_type max_size() const BOOST_CONTAINER_NOEXCEPT { return base_t::max_size(); } //! Effects: Inserts or erases elements at the end such that @@ -990,7 +971,16 @@ class basic_string //! //! Complexity: Linear to the difference between size() and new_size. void resize(size_type n) - { resize(n, CharT(0)); } + { resize(n, CharT()); } + + //! Effects: Number of elements for which memory has been allocated. + //! capacity() is always greater than or equal to size(). + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + size_type capacity() const BOOST_CONTAINER_NOEXCEPT + { return this->priv_capacity(); } //! Effects: If n is less than or equal to capacity(), this call has no //! effect. Otherwise, it is a request for allocation of additional memory. @@ -1023,28 +1013,6 @@ class basic_string } } - //! Effects: Number of elements for which memory has been allocated. - //! capacity() is always greater than or equal to size(). - //! - //! Throws: Nothing. - //! - //! Complexity: Constant. - size_type capacity() const - { return this->priv_capacity(); } - - //! Effects: Erases all the elements of the vector. - //! - //! Throws: Nothing. - //! - //! Complexity: Linear to the number of elements in the vector. - void clear() - { - if (!this->empty()) { - Traits::assign(*this->priv_addr(), CharT(0)); - this->priv_size(0); - } - } - //! Effects: Tries to deallocate the excess of memory created //! with previous allocations. The size of the string is unchanged //! @@ -1076,13 +1044,11 @@ class basic_string } } - //! Effects: Returns true if the vector contains no elements. - //! - //! Throws: Nothing. - //! - //! Complexity: Constant. - bool empty() const - { return !this->priv_size(); } + ////////////////////////////////////////////// + // + // element access + // + ////////////////////////////////////////////// //! Requires: size() > n. //! @@ -1092,7 +1058,7 @@ class basic_string //! Throws: Nothing. //! //! Complexity: Constant. - reference operator[](size_type n) + reference operator[](size_type n) BOOST_CONTAINER_NOEXCEPT { return *(this->priv_addr() + n); } //! Requires: size() > n. @@ -1103,7 +1069,7 @@ class basic_string //! Throws: Nothing. //! //! Complexity: Constant. - const_reference operator[](size_type n) const + const_reference operator[](size_type n) const BOOST_CONTAINER_NOEXCEPT { return *(this->priv_addr() + n); } //! Requires: size() > n. @@ -1135,6 +1101,12 @@ class basic_string return *(this->priv_addr() + n); } + ////////////////////////////////////////////// + // + // modifiers + // + ////////////////////////////////////////////// + //! Effects: Calls append(str.data, str.size()). //! //! Returns: *this @@ -1240,7 +1212,7 @@ class basic_string //! Throws: Nothing //! //! Returns: *this - basic_string& assign(BOOST_RV_REF(basic_string) ms) + basic_string& assign(BOOST_RV_REF(basic_string) ms) BOOST_CONTAINER_NOEXCEPT { return this->swap_data(ms), *this; } //! Requires: pos <= str.size() @@ -1322,10 +1294,10 @@ class basic_string //! Returns: *this basic_string& insert(size_type pos, const basic_string& s) { - const size_type size_ = this->size(); - if (pos > size_) + const size_type sz = this->size(); + if (pos > sz) this->throw_out_of_range(); - if (size_ > this->max_size() - s.size()) + if (sz > this->max_size() - s.size()) this->throw_length_error(); this->insert(this->priv_addr() + pos, s.begin(), s.end()); return *this; @@ -1341,12 +1313,12 @@ class basic_string //! Returns: *this basic_string& insert(size_type pos1, const basic_string& s, size_type pos2, size_type n) { - const size_type size_ = this->size(); + const size_type sz = this->size(); const size_type str_size = s.size(); - if (pos1 > size_ || pos2 > str_size) + if (pos1 > sz || pos2 > str_size) this->throw_out_of_range(); size_type len = container_detail::min_value(n, str_size - pos2); - if (size_ > this->max_size() - len) + if (sz > this->max_size() - len) this->throw_length_error(); const CharT *beg_ptr = container_detail::to_raw_pointer(s.begin()) + pos2; const CharT *end_ptr = beg_ptr + len; @@ -1591,7 +1563,7 @@ class basic_string //! //! Returns: An iterator which points to the element immediately following p prior to the element being //! erased. If no such element exists, end() is returned. - iterator erase(const_iterator p) + iterator erase(const_iterator p) BOOST_CONTAINER_NOEXCEPT { // The move includes the terminating null. CharT * const ptr = const_cast(container_detail::to_raw_pointer(p)); @@ -1611,7 +1583,7 @@ class basic_string //! //! Returns: An iterator which points to the element pointed to by last prior to //! the other elements being erased. If no such element exists, end() is returned. - iterator erase(const_iterator first, const_iterator last) + iterator erase(const_iterator first, const_iterator last) BOOST_CONTAINER_NOEXCEPT { CharT * f = const_cast(container_detail::to_raw_pointer(first)); if (first != last) { // The move includes the terminating null. @@ -1631,13 +1603,26 @@ class basic_string //! Throws: Nothing //! //! Effects: Equivalent to erase(size() - 1, 1). - void pop_back() + void pop_back() BOOST_CONTAINER_NOEXCEPT { const size_type old_size = this->priv_size(); Traits::assign(this->priv_addr()[old_size-1], CharT(0)); this->priv_size(old_size-1);; } + //! Effects: Erases all the elements of the vector. + //! + //! Throws: Nothing. + //! + //! Complexity: Linear to the number of elements in the vector. + void clear() BOOST_CONTAINER_NOEXCEPT + { + if (!this->empty()) { + Traits::assign(*this->priv_addr(), CharT(0)); + this->priv_size(0); + } + } + //! Requires: pos1 <= size(). //! //! Effects: Calls replace(pos1, n1, str.data(), str.size()). @@ -1890,12 +1875,18 @@ class basic_string container_detail::swap_alloc(this->alloc(), x.alloc(), flag); } + ////////////////////////////////////////////// + // + // data access + // + ////////////////////////////////////////////// + //! Requires: The program shall not alter any of the values stored in the character array. //! //! Returns: Allocator pointer p such that p + i == &operator[](i) for each i in [0,size()]. //! //! Complexity: constant time. - const CharT* c_str() const + const CharT* c_str() const BOOST_CONTAINER_NOEXCEPT { return container_detail::to_raw_pointer(this->priv_addr()); } //! Requires: The program shall not alter any of the values stored in the character array. @@ -1903,9 +1894,15 @@ class basic_string //! Returns: Allocator pointer p such that p + i == &operator[](i) for each i in [0,size()]. //! //! Complexity: constant time. - const CharT* data() const + const CharT* data() const BOOST_CONTAINER_NOEXCEPT { return container_detail::to_raw_pointer(this->priv_addr()); } + ////////////////////////////////////////////// + // + // string operations + // + ////////////////////////////////////////////// + //! Effects: Determines the lowest position xpos, if possible, such that both //! of the following conditions obtain: 19 pos <= xpos and xpos + str.size() <= size(); //! 2) traits::eq(at(xpos+I), str.at(I)) for all elements I of the string controlled by str. @@ -1949,12 +1946,12 @@ class basic_string //! Returns: find(basic_string(1,c), pos). size_type find(CharT c, size_type pos = 0) const { - const size_type size_ = this->size(); - if (pos >= size_) + const size_type sz = this->size(); + if (pos >= sz) return npos; else { - const pointer addr = this->priv_addr(); - pointer finish = addr + size_; + const pointer addr = this->priv_addr(); + pointer finish = addr + sz; const const_iterator result = std::find_if(addr + pos, finish, std::bind2nd(Eq_traits(), c)); @@ -2039,12 +2036,12 @@ class basic_string //! Returns: find_first_of(basic_string(s, n), pos). size_type find_first_of(const CharT* s, size_type pos, size_type n) const { - const size_type size_ = this->size(); - if (pos >= size_) + const size_type sz = this->size(); + if (pos >= sz) return npos; else { - const pointer addr = this->priv_addr(); - pointer finish = addr + size_; + const pointer addr = this->priv_addr(); + pointer finish = addr + sz; const_iterator result = std::find_first_of (addr + pos, finish, s, s + n, Eq_traits()); return result != finish ? result - this->begin() : npos; @@ -2282,8 +2279,8 @@ class basic_string //! Throws: out_of_range if pos1 > size() or pos2 > str.size() //! //! Returns: basic_string(*this, pos1, n1).compare(basic_string(str, pos2, n2)). - int compare(size_type pos1, size_type n1, - const basic_string& str, size_type pos2, size_type n2) const { + int compare(size_type pos1, size_type n1, const basic_string& str, size_type pos2, size_type n2) const + { if (pos1 > this->size() || pos2 > str.size()) this->throw_out_of_range(); const pointer addr = this->priv_addr(); @@ -2309,8 +2306,7 @@ class basic_string //! Throws: out_of_range if pos1 > size() //! //! Returns: basic_string(*this, pos, n1).compare(basic_string(s, n2)). - int compare(size_type pos1, size_type n1, - const CharT* s, size_type n2) const + int compare(size_type pos1, size_type n1, const CharT* s, size_type n2) const { if (pos1 > this->size()) this->throw_out_of_range(); @@ -2352,7 +2348,7 @@ class basic_string const size_type long_size = this->priv_long_size(); const size_type long_storage = this->priv_long_storage(); //We can make this nothrow as chars are always NoThrowCopyables - try{ + BOOST_TRY{ const std::pair ret = this->allocation_command (allocate_new, long_size+1, long_size+1, real_cap, long_addr); //Copy and update @@ -2364,9 +2360,10 @@ class basic_string //And release old buffer this->alloc().deallocate(long_addr, long_storage); } - catch(...){ + BOOST_CATCH(...){ return; } + BOOST_CATCH_END } template @@ -2481,15 +2478,6 @@ typedef basic_string ,std::allocator > wstring; -/// @cond - -template -const typename basic_string::size_type -basic_string::npos - = (typename basic_string::size_type) -1; - -/// @endcond - // ------------------------------------------------------------ // Non-member functions. @@ -2857,15 +2845,14 @@ inline std::size_t hash_value(basic_string, Allocator> /// @cond namespace boost { -/* + //!has_trivial_destructor_after_move<> == true_type //!specialization for optimizations template struct has_trivial_destructor_after_move > -{ - static const bool value = has_trivial_destructor::value; -}; -*/ + : public ::boost::has_trivial_destructor_after_move +{}; + } /// @endcond diff --git a/include/boost/container/vector.hpp b/include/boost/container/vector.hpp index 972db9e..3c4c9c5 100644 --- a/include/boost/container/vector.hpp +++ b/include/boost/container/vector.hpp @@ -32,6 +32,7 @@ #include #include #include +#include #include #include #include @@ -39,9 +40,10 @@ #include #include #include -#include -#include -#include +#include +#include +#include +#include #include #include #include @@ -213,8 +215,7 @@ struct vector_value_traits typedef T value_type; typedef Allocator allocator_type; static const bool trivial_dctr = boost::has_trivial_destructor::value; - static const bool trivial_dctr_after_move = trivial_dctr; - //::boost::has_trivial_destructor_after_move::value || trivial_dctr; + static const bool trivial_dctr_after_move = ::boost::has_trivial_destructor_after_move::value; //static const bool trivial_copy = has_trivial_copy::value; //static const bool nothrow_copy = has_nothrow_copy::value; //static const bool trivial_assign = has_trivial_assign::value; @@ -286,42 +287,17 @@ struct vector_alloc_holder size_type preferred_size, size_type &received_size, const pointer &reuse = 0) { - return allocation_command(command, limit_size, preferred_size, - received_size, reuse, alloc_version()); - } - - std::pair - allocation_command(allocation_type command, - size_type limit_size, - size_type preferred_size, - size_type &received_size, - const pointer &reuse, - allocator_v1) - { - (void)limit_size; - (void)reuse; - if(!(command & allocate_new)) - return std::pair(pointer(0), false); - received_size = preferred_size; - return std::make_pair(this->alloc().allocate(received_size), false); - } - - std::pair - allocation_command(allocation_type command, - size_type limit_size, - size_type preferred_size, - size_type &received_size, - const pointer &reuse, - allocator_v2) - { - return this->alloc().allocation_command - (command, limit_size, preferred_size, received_size, reuse); + return allocator_version_traits::allocation_command + (this->alloc(), command, limit_size, preferred_size, received_size, reuse); } size_type next_capacity(size_type additional_objects) const { + std::size_t num_objects = this->members_.m_size + additional_objects; + std::size_t next_cap = this->members_.m_capacity + this->members_.m_capacity/2; + return num_objects > next_cap ? num_objects : next_cap;/* return get_next_capacity( allocator_traits_type::max_size(this->alloc()) - , this->members_.m_capacity, additional_objects); + , this->members_.m_capacity, additional_objects);*/ } struct members_holder @@ -435,7 +411,6 @@ class vector : private container_detail::vector_alloc_holder /// @cond private: BOOST_COPYABLE_AND_MOVABLE(vector) - typedef container_detail::advanced_insert_aux_int advanced_insert_aux_int_t; typedef container_detail::vector_value_traits value_traits; typedef typename base_t::allocator_v1 allocator_v1; @@ -443,8 +418,6 @@ class vector : private container_detail::vector_alloc_holder typedef typename base_t::alloc_version alloc_version; typedef constant_iterator cvalue_iterator; - typedef repeat_iterator repeat_it; - typedef boost::move_iterator repeat_move_it; /// @endcond public: @@ -857,7 +830,7 @@ class vector : private container_detail::vector_alloc_holder else{ const size_type n = new_size - this->size(); this->reserve(new_size); - container_detail::default_construct_aux_proxy proxy(this->alloc(), n); + container_detail::insert_default_constructed_n_proxy proxy(this->alloc()); this->priv_forward_range_insert(this->cend().get_ptr(), n, proxy); } } @@ -920,11 +893,10 @@ class vector : private container_detail::vector_alloc_holder //If there is no forward expansion, move objects else{ //We will reuse insert code, so create a dummy input iterator - T *dummy_it(container_detail::to_raw_pointer(this->members_.m_start)); - container_detail::advanced_insert_aux_proxy, T*> - proxy(this->alloc(), ::boost::make_move_iterator(dummy_it), ::boost::make_move_iterator(dummy_it)); + container_detail::insert_range_proxy, T*> + proxy(this->alloc(), ::boost::make_move_iterator((T *)0)); //Backwards (and possibly forward) expansion - if(ret.second){ + if(alloc_version::value > 1 && ret.second){ #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS ++this->num_expand_bwd; #endif @@ -1018,7 +990,7 @@ class vector : private container_detail::vector_alloc_holder //! Throws: Nothing. //! //! Complexity: Constant. - reference operator[](size_type n) + reference operator[](size_type n) BOOST_CONTAINER_NOEXCEPT { return this->members_.m_start[n]; } //! Requires: size() > n. @@ -1102,9 +1074,9 @@ class vector : private container_detail::vector_alloc_holder ++this->members_.m_size; } else{ - typedef container_detail::advanced_insert_aux_emplace type; - type &&proxy = type(this->alloc(), ::boost::forward(args)...); - this->priv_forward_range_insert(back_pos, 1, proxy); + typedef container_detail::insert_emplace_proxy type; + this->priv_forward_range_insert + (back_pos, 1, type(this->alloc(), ::boost::forward(args)...)); } } @@ -1122,11 +1094,9 @@ class vector : private container_detail::vector_alloc_holder iterator emplace(const_iterator position, Args && ...args) { //Just call more general insert(pos, size, value) and return iterator - size_type pos_n = position - cbegin(); - typedef container_detail::advanced_insert_aux_emplace type; - type &&proxy = type(this->alloc(), ::boost::forward(args)...); - this->priv_forward_range_insert(position.get_ptr(), 1, proxy); - return iterator(this->members_.m_start + pos_n); + typedef container_detail::insert_emplace_proxy type; + return this->priv_forward_range_insert + (position.get_ptr(), 1, type(this->alloc(), ::boost::forward(args)...)); } #else @@ -1143,8 +1113,8 @@ class vector : private container_detail::vector_alloc_holder ++this->members_.m_size; \ } \ else{ \ - container_detail::BOOST_PP_CAT(BOOST_PP_CAT(advanced_insert_aux_emplace, n), arg) \ - proxy \ + container_detail::BOOST_PP_CAT(insert_emplace_proxy_arg, n) \ + proxy \ (this->alloc() BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _)); \ this->priv_forward_range_insert(back_pos, 1, proxy); \ } \ @@ -1154,12 +1124,11 @@ class vector : private container_detail::vector_alloc_holder iterator emplace(const_iterator pos \ BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \ { \ - size_type pos_n = pos - cbegin(); \ - container_detail::BOOST_PP_CAT(BOOST_PP_CAT(advanced_insert_aux_emplace, n), arg) \ - proxy \ + container_detail::BOOST_PP_CAT(insert_emplace_proxy_arg, n) \ + proxy \ (this->alloc() BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _)); \ - this->priv_forward_range_insert(container_detail::to_raw_pointer(pos.get_ptr()), 1,proxy);\ - return iterator(this->members_.m_start + pos_n); \ + return this->priv_forward_range_insert \ + (container_detail::to_raw_pointer(pos.get_ptr()), 1, proxy); \ } \ //! #define BOOST_PP_LOCAL_LIMITS (0, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS) @@ -1222,7 +1191,10 @@ class vector : private container_detail::vector_alloc_holder //! //! Complexity: Linear to n. iterator insert(const_iterator p, size_type n, const T& x) - { return this->insert(p, cvalue_iterator(x, n), cvalue_iterator()); } + { + container_detail::insert_n_copies_proxy proxy(this->alloc(), x); + return this->priv_forward_range_insert(p.get_ptr(), n, proxy); + } //! Requires: p must be a valid iterator of *this. //! @@ -1250,7 +1222,7 @@ class vector : private container_detail::vector_alloc_holder it = this->emplace(it, *first); ++it; } - return this->begin() + n_pos; + return iterator(this->members_.m_start + n_pos); } #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED) @@ -1262,11 +1234,8 @@ class vector : private container_detail::vector_alloc_holder >::type * = 0 ) { - const size_type n_pos = pos - this->cbegin(); - const size_type n = std::distance(first, last); - container_detail::advanced_insert_aux_proxy proxy(this->alloc(), first, last); - this->priv_forward_range_insert(pos.get_ptr(), n, proxy); - return this->begin() + n_pos; + container_detail::insert_range_proxy proxy(this->alloc(), first); + return this->priv_forward_range_insert(pos.get_ptr(), std::distance(first, last), proxy); } #endif @@ -1275,7 +1244,7 @@ class vector : private container_detail::vector_alloc_holder //! Throws: Nothing. //! //! Complexity: Constant time. - void pop_back() + void pop_back() BOOST_CONTAINER_NOEXCEPT { //Destroy last element --this->members_.m_size; @@ -1290,8 +1259,8 @@ class vector : private container_detail::vector_alloc_holder //! last element. Constant if pos is the last element. iterator erase(const_iterator position) { - T *pos = container_detail::to_raw_pointer(position.get_ptr()); - T *beg = container_detail::to_raw_pointer(this->members_.m_start); + T *const pos = container_detail::to_raw_pointer(position.get_ptr()); + T *const beg = container_detail::to_raw_pointer(this->members_.m_start); ::boost::move(pos + 1, beg + this->members_.m_size, pos); --this->members_.m_size; //Destroy last element @@ -1307,14 +1276,14 @@ class vector : private container_detail::vector_alloc_holder //! plus linear to the elements between pos and the last element. iterator erase(const_iterator first, const_iterator last) { - if (first != last){ // worth doing, copy down over hole + if (first != last){ T* end_pos = container_detail::to_raw_pointer(this->members_.m_start) + this->members_.m_size; T* ptr = container_detail::to_raw_pointer(boost::move (container_detail::to_raw_pointer(last.get_ptr()) ,end_pos ,container_detail::to_raw_pointer(first.get_ptr()) )); - size_type destroyed = (end_pos - ptr); + const size_type destroyed = (end_pos - ptr); this->destroy_n(ptr, destroyed); this->members_.m_size -= destroyed; } @@ -1361,26 +1330,15 @@ class vector : private container_detail::vector_alloc_holder } private: - iterator priv_insert(const_iterator position, const T &x) + template + iterator priv_insert(const const_iterator &p, BOOST_FWD_REF(U) x) { - //Just call more general insert(pos, size, value) and return iterator - size_type pos_n = position - cbegin(); - this->insert(position, (size_type)1, x); - return iterator(this->members_.m_start + pos_n); - } - - iterator priv_insert(const_iterator position, BOOST_RV_REF(T) x) - { - //Just call more general insert(pos, size, value) and return iterator - size_type pos_n = position - cbegin(); - this->insert(position - ,repeat_move_it(repeat_it(x, 1)) - ,repeat_move_it(repeat_it())); - return iterator(this->members_.m_start + pos_n); + return this->priv_forward_range_insert + (p.get_ptr(), 1, container_detail::get_insert_value_proxy(this->alloc(), ::boost::forward(x))); } template - void priv_push_back(BOOST_MOVE_CATCH_FWD(U) x) + void priv_push_back(BOOST_FWD_REF(U) x) { if (this->members_.m_size < this->members_.m_capacity){ //There is more memory, just construct a new object at the end @@ -1391,7 +1349,7 @@ class vector : private container_detail::vector_alloc_holder ++this->members_.m_size; } else{ - this->insert(this->cend(), ::boost::forward(x)); + this->priv_insert(this->cend(), ::boost::forward(x)); } } @@ -1409,9 +1367,8 @@ class vector : private container_detail::vector_alloc_holder (allocate_new, this->size(), this->size(), real_cap, this->members_.m_start); if(real_cap < this->capacity()){ //We will reuse insert code, so create a dummy input iterator - T *dummy_it(container_detail::to_raw_pointer(this->members_.m_start)); - container_detail::advanced_insert_aux_proxy, T*> - proxy(this->alloc(), ::boost::make_move_iterator(dummy_it), ::boost::make_move_iterator(dummy_it)); + container_detail::insert_range_proxy, T*> + proxy(this->alloc(), ::boost::make_move_iterator((T *)0)); #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS ++this->num_alloc; #endif @@ -1450,65 +1407,79 @@ class vector : private container_detail::vector_alloc_holder } } - void priv_forward_range_insert(pointer pos, const size_type n, advanced_insert_aux_int_t &interf) + template + iterator priv_forward_range_insert + (const pointer &pos, const size_type n, const InsertionProxy insert_range_proxy) { //Check if we have enough memory or try to expand current memory - size_type remaining = this->members_.m_capacity - this->members_.m_size; - bool same_buffer_start; - std::pair ret; - size_type real_cap = this->members_.m_capacity; + const size_type remaining = this->members_.m_capacity - this->members_.m_size; + const size_type n_pos = pos - this->members_.m_start; + T *const raw_pos = container_detail::to_raw_pointer(pos); //Check if we already have room - if (n <= remaining){ - same_buffer_start = true; - } - else{ - //There is not enough memory, allocate a new - //buffer or expand the old one. - size_type new_cap = this->next_capacity(n); - ret = this->allocation_command - (allocate_new | expand_fwd | expand_bwd, - this->members_.m_size + n, new_cap, real_cap, this->members_.m_start); + if(alloc_version::value > 1){ //Version 2 allocator, compile time check + bool same_buffer_start = n <= remaining; + if (!same_buffer_start){ + size_type real_cap = 0; + //There is not enough memory, allocate a new + //buffer or expand the old one. + std::pair ret = (this->allocation_command + (allocate_new | expand_fwd | expand_bwd, + this->members_.m_size + n, this->next_capacity(n), real_cap, this->members_.m_start)); - //Check for forward expansion - same_buffer_start = ret.second && this->members_.m_start == ret.first; - if(same_buffer_start){ - this->members_.m_capacity = real_cap; + //Buffer reallocated + if(ret.second){ + //Forward expansion, delay insertion + if(this->members_.m_start == ret.first){ + #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS + ++this->num_expand_fwd; + #endif + this->members_.m_capacity = real_cap; + //Expand forward + this->priv_range_insert_expand_forward(raw_pos, n, insert_range_proxy); + } + //Backwards (and possibly forward) expansion + else{ + #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS + ++this->num_expand_bwd; + #endif + this->priv_range_insert_expand_backwards + ( container_detail::to_raw_pointer(ret.first) + , real_cap, raw_pos, n, insert_range_proxy); + } + } + //New buffer + else{ + #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS + ++this->num_alloc; + #endif + this->priv_range_insert_new_allocation + ( container_detail::to_raw_pointer(ret.first) + , real_cap, raw_pos, n, insert_range_proxy); + } + } + else{ + //Expand forward + this->priv_range_insert_expand_forward + (raw_pos, n, insert_range_proxy); } } - - //If we had room or we have expanded forward - if (same_buffer_start){ - #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS - ++this->num_expand_fwd; - #endif - this->priv_range_insert_expand_forward - (container_detail::to_raw_pointer(pos), n, interf); - } - //Backwards (and possibly forward) expansion - else if(ret.second){ - #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS - ++this->num_expand_bwd; - #endif - this->priv_range_insert_expand_backwards - ( container_detail::to_raw_pointer(ret.first) - , real_cap - , container_detail::to_raw_pointer(pos) - , n - , interf); - } - //New buffer - else{ - #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS - ++this->num_alloc; - #endif - this->priv_range_insert_new_allocation - ( container_detail::to_raw_pointer(ret.first) - , real_cap - , container_detail::to_raw_pointer(pos) - , n - , interf); + else{ //Version 1 allocator + if (n <= remaining){ + this->priv_range_insert_expand_forward + (raw_pos, n, insert_range_proxy); + } + else{ + const size_type new_cap = this->next_capacity(n); + T * new_buf = container_detail::to_raw_pointer(this->alloc().allocate(new_cap)); + #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS + ++this->num_alloc; + #endif + this->priv_range_insert_new_allocation + ( new_buf, new_cap, raw_pos, n, insert_range_proxy); + } } + return iterator(this->members_.m_start + n_pos); } //Absolutely experimental. This function might change, disappear or simply crash! @@ -1660,15 +1631,21 @@ class vector : private container_detail::vector_alloc_holder } private: - void priv_range_insert_expand_forward(T* pos, size_type n, advanced_insert_aux_int_t &interf) + template + void priv_range_insert_expand_forward(T* const pos, const size_type n, InsertionProxy insert_range_proxy) { //n can't be 0, because there is nothing to do in that case if(!n) return; //There is enough memory - T* old_finish = container_detail::to_raw_pointer(this->members_.m_start) + this->members_.m_size; + T* const old_finish = container_detail::to_raw_pointer(this->members_.m_start) + this->members_.m_size; const size_type elems_after = old_finish - pos; - if (elems_after >= n){ + if (!elems_after){ + //Copy first new elements in pos + insert_range_proxy.uninitialized_copy_n_and_update(pos, n); + this->members_.m_size += n; + } + else if (elems_after >= n){ //New elements can be just copied. //Move to uninitialized memory last objects ::boost::container::uninitialized_move_alloc @@ -1677,24 +1654,31 @@ class vector : private container_detail::vector_alloc_holder //Copy previous to last objects to the initialized end boost::move_backward(pos, old_finish - n, old_finish); //Insert new objects in the pos - interf.copy_remaining_to(pos); + insert_range_proxy.copy_n_and_update(pos, n); } else { - //The new elements don't fit in the [pos, end()) range. Copy - //to the beginning of the unallocated zone the last new elements. - interf.uninitialized_copy_some_and_update(old_finish, elems_after, false); - this->members_.m_size += n - elems_after; - //Copy old [pos, end()) elements to the uninitialized memory - ::boost::container::uninitialized_move_alloc - (this->alloc(), pos, old_finish, container_detail::to_raw_pointer(this->members_.m_start) + this->members_.m_size); - this->members_.m_size += elems_after; - //Copy first new elements in pos - interf.copy_remaining_to(pos); + //The new elements don't fit in the [pos, end()) range. + + //Copy old [pos, end()) elements to the uninitialized memory (a gap is created) + ::boost::container::uninitialized_move_alloc(this->alloc(), pos, old_finish, pos + n); + BOOST_TRY{ + //Copy first new elements in pos (gap is still there) + insert_range_proxy.copy_n_and_update(pos, elems_after); + //Copy to the beginning of the unallocated zone the last new elements (the gap is closed). + insert_range_proxy.uninitialized_copy_n_and_update(old_finish, n - elems_after); + this->members_.m_size += n; + } + BOOST_CATCH(...){ + this->destroy_n(pos + n, elems_after); + BOOST_RETHROW + } + BOOST_CATCH_END } } + template void priv_range_insert_new_allocation - (T* new_start, size_type new_cap, T* pos, size_type n, advanced_insert_aux_int_t &interf) + (T* const new_start, size_type new_cap, T* const pos, const size_type n, InsertionProxy insert_range_proxy) { //n can be zero, if we want to reallocate! T *new_finish = new_start; @@ -1712,7 +1696,7 @@ class vector : private container_detail::vector_alloc_holder constructed_values_destroyer.increment_size(new_finish - old_finish); } //Initialize new objects, starting from previous point - interf.uninitialized_copy_remaining_to(old_finish = new_finish); + insert_range_proxy.uninitialized_copy_n_and_update(old_finish = new_finish, n); new_finish += n; constructed_values_destroyer.increment_size(new_finish - old_finish); //Initialize from the rest of the old buffer, @@ -1734,19 +1718,21 @@ class vector : private container_detail::vector_alloc_holder scoped_alloc.release(); } + template void priv_range_insert_expand_backwards - (T* new_start, size_type new_capacity, - T* pos, const size_type n, advanced_insert_aux_int_t &interf) + (T* const new_start, const size_type new_capacity, + T* const pos, const size_type n, InsertionProxy insert_range_proxy) { //n can be zero to just expand capacity //Backup old data - T* old_start = container_detail::to_raw_pointer(this->members_.m_start); - T* old_finish = old_start + this->members_.m_size; - size_type old_size = this->members_.m_size; + T* const old_start = container_detail::to_raw_pointer(this->members_.m_start); + T* const old_finish = old_start + this->members_.m_size; + const size_type old_size = this->members_.m_size; //We can have 8 possibilities: - const size_type elemsbefore = (size_type)(pos - old_start); - const size_type s_before = (size_type)(old_start - new_start); + const size_type elemsbefore = static_cast(pos - old_start); + const size_type s_before = static_cast(old_start - new_start); + const size_type before_plus_new = elemsbefore + n; //Update the vector buffer information to a safe state this->members_.m_start = new_start; @@ -1757,15 +1743,16 @@ class vector : private container_detail::vector_alloc_holder //all the old objects to fulfill previous vector state typename value_traits::OldArrayDestructor old_values_destroyer(old_start, this->alloc(), old_size); //Check if s_before is big enough to hold the beginning of old data + new data - if(difference_type(s_before) >= difference_type(elemsbefore + n)){ + if(s_before >= before_plus_new){ //Copy first old values before pos, after that the new objects - ::boost::container::uninitialized_move_alloc(this->alloc(), old_start, pos, new_start); + T *const new_elem_pos = ::boost::container::uninitialized_move_alloc(this->alloc(), old_start, pos, new_start); this->members_.m_size = elemsbefore; - interf.uninitialized_copy_remaining_to(new_start + elemsbefore); + insert_range_proxy.uninitialized_copy_n_and_update(new_elem_pos, n); this->members_.m_size += n; //Check if s_before is so big that even copying the old data + new data //there is a gap between the new data and the old data - if(s_before >= (old_size + n)){ + const size_type new_size = old_size + n; + if(s_before >= new_size){ //Old situation: // _________________________________________________________ //| raw_mem | old_begin | old_end | @@ -1778,9 +1765,9 @@ class vector : private container_detail::vector_alloc_holder // //Now initialize the rest of memory with the last old values ::boost::container::uninitialized_move_alloc - (this->alloc(), pos, old_finish, new_start + elemsbefore + n); + (this->alloc(), pos, old_finish, new_start + before_plus_new); //All new elements correctly constructed, avoid new element destruction - this->members_.m_size = old_size + n; + this->members_.m_size = new_size; //Old values destroyed automatically with "old_values_destroyer" //when "old_values_destroyer" goes out of scope unless the have trivial //destructor after move. @@ -1801,17 +1788,17 @@ class vector : private container_detail::vector_alloc_holder // //Now initialize the rest of memory with the last old values //All new elements correctly constructed, avoid new element destruction - size_type raw_gap = s_before - (elemsbefore + n); + const size_type raw_gap = s_before - before_plus_new; //Now initialize the rest of s_before memory with the //first of elements after new values - ::boost::container::uninitialized_move_alloc - (this->alloc(), pos, pos + raw_gap, new_start + elemsbefore + n); + ::boost::container::uninitialized_move_alloc_n + (this->alloc(), pos, raw_gap, new_start + before_plus_new); //Update size since we have a contiguous buffer this->members_.m_size = old_size + s_before; //All new elements correctly constructed, avoid old element destruction old_values_destroyer.release(); //Now copy remaining last objects in the old buffer begin - T *to_destroy = ::boost::move(pos + raw_gap, old_finish, old_start); + T * const to_destroy = ::boost::move(pos + raw_gap, old_finish, old_start); //Now destroy redundant elements except if they were moved and //they have trivial destructor after move size_type n_destroy = old_finish - to_destroy; @@ -1840,7 +1827,7 @@ class vector : private container_detail::vector_alloc_holder //| old_begin + new + old_end | raw_mem | //|____________________________|____________________| // - bool do_after = n > s_before; + const bool do_after = n > s_before; //Now we can have two situations: the raw_mem of the //beginning divides the old_begin, or the new elements: @@ -1869,28 +1856,26 @@ class vector : private container_detail::vector_alloc_holder //|___________|_____|_________|_____________________| // //Copy the first part of old_begin to raw_mem - T *start_n = old_start + difference_type(s_before); - ::boost::container::uninitialized_move_alloc - (this->alloc(), old_start, start_n, new_start); + ::boost::container::uninitialized_move_alloc_n + (this->alloc(), old_start, s_before, new_start); //The buffer is all constructed until old_end, //release destroyer and update size old_values_destroyer.release(); this->members_.m_size = old_size + s_before; - //Now copy the second part of old_begin overwriting himself - T* next = ::boost::move(start_n, pos, old_start); + //Now copy the second part of old_begin overwriting itself + T *const next = ::boost::move(old_start + s_before, pos, old_start); if(do_after){ //Now copy the new_beg elements - interf.copy_some_and_update(next, s_before, true); + insert_range_proxy.copy_n_and_update(next, s_before); } else{ //Now copy the all the new elements - interf.copy_remaining_to(next); - T* move_start = next + n; + insert_range_proxy.copy_n_and_update(next, n); //Now displace old_end elements - T* move_end = ::boost::move(pos, old_finish, move_start); + T* const move_end = ::boost::move(pos, old_finish, next + n); //Destroy remaining moved elements from old_end except if //they have trivial destructor after being moved - difference_type n_destroy = s_before - n; + const size_type n_destroy = s_before - n; if(!value_traits::trivial_dctr_after_move) this->destroy_n(move_end, n_destroy); this->members_.m_size -= n_destroy; @@ -1923,30 +1908,30 @@ class vector : private container_detail::vector_alloc_holder //|___________|_____|_________|__________________________| // //First copy whole old_begin and part of new to raw_mem - ::boost::container::uninitialized_move_alloc + T * const new_pos = ::boost::container::uninitialized_move_alloc (this->alloc(), old_start, pos, new_start); this->members_.m_size = elemsbefore; - - const size_type mid_n = difference_type(s_before) - elemsbefore; - interf.uninitialized_copy_some_and_update(new_start + elemsbefore, mid_n, true); - this->members_.m_size = old_size + s_before; + const size_type mid_n = s_before - elemsbefore; + insert_range_proxy.uninitialized_copy_n_and_update(new_pos, mid_n); //The buffer is all constructed until old_end, - //release destroyer and update size + //release destroyer + this->members_.m_size = old_size + s_before; old_values_destroyer.release(); if(do_after){ //Copy new_beg part - interf.copy_some_and_update(old_start, s_before - mid_n, true); + insert_range_proxy.copy_n_and_update(old_start, elemsbefore); } else{ //Copy all new elements - interf.copy_remaining_to(old_start); - T* move_start = old_start + (n-mid_n); + const size_type rest_new = n - mid_n; + insert_range_proxy.copy_n_and_update(old_start, rest_new); + T* move_start = old_start + rest_new; //Displace old_end T* move_end = ::boost::move(pos, old_finish, move_start); //Destroy remaining moved elements from old_end except if they //have trivial destructor after being moved - difference_type n_destroy = s_before - n; + size_type n_destroy = s_before - n; if(!value_traits::trivial_dctr_after_move) this->destroy_n(move_end, n_destroy); this->members_.m_size -= n_destroy; @@ -1954,9 +1939,6 @@ class vector : private container_detail::vector_alloc_holder } //This is only executed if two phase construction is needed - //This can be executed without exception handling since we - //have to just copy and append in raw memory and - //old_values_destroyer has been released in phase 1. if(do_after){ //The raw memory divides the new elements // @@ -1975,11 +1957,11 @@ class vector : private container_detail::vector_alloc_holder //| old_begin + new | old_end |raw | //|_______________________________________|_________|____| // - const size_type n_after = n - s_before; - const difference_type elemsafter = old_size - elemsbefore; + const size_type n_after = n - s_before; + const size_type elemsafter = old_size - elemsbefore; //We can have two situations: - if (elemsafter > difference_type(n_after)){ + if (elemsafter >= n_after){ //The raw_mem from end will divide displaced old_end // //Old situation: @@ -1993,7 +1975,7 @@ class vector : private container_detail::vector_alloc_holder //|__________________________|_________|________|_________| // //First copy the part of old_end raw_mem - T* finish_n = old_finish - difference_type(n_after); + T* finish_n = old_finish - n_after; ::boost::container::uninitialized_move_alloc (this->alloc(), finish_n, old_finish, old_finish); this->members_.m_size += n_after; @@ -2001,7 +1983,7 @@ class vector : private container_detail::vector_alloc_holder boost::move_backward(pos, finish_n, old_finish); //Now overwrite with new_end //The new_end part is [first + (n - n_after), last) - interf.copy_remaining_to(pos); + insert_range_proxy.copy_n_and_update(pos, n_after); } else { //The raw_mem from end will divide new_end part @@ -2016,16 +1998,38 @@ class vector : private container_detail::vector_alloc_holder //| old_begin + new_beg | new_end |old_end | raw_mem | //|__________________________|_______________|________|_________| // + + const size_type mid_last_dist = n_after - elemsafter; + //First initialize data in raw memory + + //Copy to the old_end part to the uninitialized zone leaving a gap. + ::boost::container::uninitialized_move_alloc + (this->alloc(), pos, old_finish, old_finish + mid_last_dist); + + BOOST_TRY{ + //Copy the first part to the already constructed old_end zone + insert_range_proxy.copy_n_and_update(pos, elemsafter); + //Copy the rest to the uninitialized zone filling the gap + insert_range_proxy.uninitialized_copy_n_and_update(old_finish, mid_last_dist); + this->members_.m_size += n_after; + } + BOOST_CATCH(...){ + this->destroy_n(pos, mid_last_dist); + BOOST_RETHROW + } + BOOST_CATCH_END +/* size_type mid_last_dist = n_after - elemsafter; //First initialize data in raw memory + //The new_end part is [first + (n - n_after), last) - interf.uninitialized_copy_some_and_update(old_finish, elemsafter, false); + insert_range_proxy.uninitialized_copy_last_and_update(old_finish, elemsafter); this->members_.m_size += mid_last_dist; ::boost::container::uninitialized_move_alloc (this->alloc(), pos, old_finish, old_finish + mid_last_dist); this->members_.m_size += n_after - mid_last_dist; //Now copy the part of new_end over constructed elements - interf.copy_remaining_to(pos); + insert_range_proxy.copy_remaining_to(pos);*/ } } } @@ -2083,17 +2087,14 @@ inline void swap(vector& x, vector& y) namespace boost { -/* //!has_trivial_destructor_after_move<> == true_type //!specialization for optimizations template struct has_trivial_destructor_after_move > -{ - static const bool value = has_trivial_destructor::value; -}; + : public ::boost::has_trivial_destructor_after_move +{}; -*/ }