Chris@102: ////////////////////////////////////////////////////////////////////////////// Chris@102: // Chris@102: // (C) Copyright Ion Gaztanaga 2005-2013. Distributed under the Boost Chris@102: // Software License, Version 1.0. (See accompanying file Chris@102: // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) Chris@102: // Chris@102: // See http://www.boost.org/libs/container for documentation. Chris@102: // Chris@102: ////////////////////////////////////////////////////////////////////////////// Chris@102: #ifndef BOOST_CONTAINER_DETAIL_UTILITIES_HPP Chris@102: #define BOOST_CONTAINER_DETAIL_UTILITIES_HPP Chris@102: Chris@102: #ifndef BOOST_CONFIG_HPP Chris@102: # include Chris@102: #endif Chris@102: Chris@102: #if defined(BOOST_HAS_PRAGMA_ONCE) Chris@102: # pragma once Chris@102: #endif Chris@102: Chris@102: // container Chris@102: #include Chris@102: // container/detail Chris@102: #include Chris@102: #include Chris@102: #include Chris@102: #include Chris@102: // move Chris@102: #include Chris@102: #include Chris@102: #include Chris@102: // other Chris@102: #include Chris@102: // std Chris@102: #include //for emmove/memcpy Chris@102: Chris@102: namespace boost { Chris@102: namespace container { Chris@102: namespace container_detail { Chris@102: Chris@102: template Chris@102: struct are_elements_contiguous Chris@102: { Chris@102: static const bool value = false; Chris@102: }; Chris@102: Chris@102: ///////////////////////// Chris@102: // raw pointers Chris@102: ///////////////////////// Chris@102: Chris@102: template Chris@102: struct are_elements_contiguous Chris@102: { Chris@102: static const bool value = true; Chris@102: }; Chris@102: Chris@102: ///////////////////////// Chris@102: // move iterators Chris@102: ///////////////////////// Chris@102: Chris@102: template Chris@102: struct are_elements_contiguous< ::boost::move_iterator > Chris@102: : are_elements_contiguous Chris@102: {}; Chris@102: Chris@102: ///////////////////////// Chris@102: // predeclarations Chris@102: ///////////////////////// Chris@102: Chris@102: #ifndef BOOST_CONTAINER_VECTOR_ITERATOR_IS_POINTER Chris@102: Chris@102: template Chris@102: class vector_iterator; Chris@102: Chris@102: template Chris@102: class vector_const_iterator; Chris@102: Chris@102: #endif //BOOST_CONTAINER_VECTOR_ITERATOR_IS_POINTER Chris@102: Chris@102: } //namespace container_detail { Chris@102: } //namespace container { Chris@102: Chris@102: namespace interprocess { Chris@102: Chris@102: template Chris@102: class offset_ptr; Chris@102: Chris@102: } //namespace interprocess { Chris@102: Chris@102: namespace container { Chris@102: Chris@102: namespace container_detail { Chris@102: Chris@102: ///////////////////////// Chris@102: //vector_[const_]iterator Chris@102: ///////////////////////// Chris@102: Chris@102: #ifndef BOOST_CONTAINER_VECTOR_ITERATOR_IS_POINTER Chris@102: Chris@102: template Chris@102: struct are_elements_contiguous > Chris@102: { Chris@102: static const bool value = true; Chris@102: }; Chris@102: Chris@102: template Chris@102: struct are_elements_contiguous > Chris@102: { Chris@102: static const bool value = true; Chris@102: }; Chris@102: Chris@102: #endif //BOOST_CONTAINER_VECTOR_ITERATOR_IS_POINTER Chris@102: Chris@102: ///////////////////////// Chris@102: // offset_ptr Chris@102: ///////////////////////// Chris@102: Chris@102: template Chris@102: struct are_elements_contiguous< ::boost::interprocess::offset_ptr > Chris@102: { Chris@102: static const bool value = true; Chris@102: }; Chris@102: Chris@102: template Chris@102: struct are_contiguous_and_same Chris@102: { Chris@102: static const bool is_same_io = Chris@102: is_same< typename remove_const< typename ::boost::container::iterator_traits::value_type >::type Chris@102: , typename ::boost::container::iterator_traits::value_type Chris@102: >::value; Chris@102: static const bool value = is_same_io && Chris@102: are_elements_contiguous::value && Chris@102: are_elements_contiguous::value; Chris@102: }; Chris@102: Chris@102: template Chris@102: struct is_memtransfer_copy_assignable Chris@102: { Chris@102: static const bool value = are_contiguous_and_same::value && Chris@102: container_detail::is_trivially_copy_assignable< typename ::boost::container::iterator_traits::value_type >::value; Chris@102: }; Chris@102: Chris@102: template Chris@102: struct is_memtransfer_copy_constructible Chris@102: { Chris@102: static const bool value = are_contiguous_and_same::value && Chris@102: container_detail::is_trivially_copy_constructible< typename ::boost::container::iterator_traits::value_type >::value; Chris@102: }; Chris@102: Chris@102: template Chris@102: struct enable_if_memtransfer_copy_constructible Chris@102: : enable_if_c::value, R> Chris@102: {}; Chris@102: Chris@102: template Chris@102: struct disable_if_memtransfer_copy_constructible Chris@102: : enable_if_c::value, R> Chris@102: {}; Chris@102: Chris@102: template Chris@102: struct enable_if_memtransfer_copy_assignable Chris@102: : enable_if_c::value, R> Chris@102: {}; Chris@102: Chris@102: template Chris@102: struct disable_if_memtransfer_copy_assignable Chris@102: : enable_if_c::value, R> Chris@102: {}; Chris@102: Chris@102: template Chris@102: // F models ForwardIterator Chris@102: inline F memmove(I f, I l, F r) BOOST_NOEXCEPT_OR_NOTHROW Chris@102: { Chris@102: typedef typename boost::container::iterator_traits::value_type value_type; Chris@102: typename boost::container::iterator_traits::difference_type n = boost::container::iterator_distance(f, l); Chris@102: std::memmove((iterator_to_raw_pointer)(r), (iterator_to_raw_pointer)(f), sizeof(value_type)*n); Chris@102: boost::container::iterator_advance(r, n); Chris@102: return r; Chris@102: } Chris@102: Chris@102: template Chris@102: // F models ForwardIterator Chris@102: F memmove_n(I f, typename boost::container::iterator_traits::difference_type n, F r) BOOST_NOEXCEPT_OR_NOTHROW Chris@102: { Chris@102: typedef typename boost::container::iterator_traits::value_type value_type; Chris@102: std::memmove((iterator_to_raw_pointer)(r), (iterator_to_raw_pointer)(f), sizeof(value_type)*n); Chris@102: boost::container::iterator_advance(r, n); Chris@102: return r; Chris@102: } Chris@102: Chris@102: template Chris@102: // F models ForwardIterator Chris@102: I memmove_n_source(I f, typename boost::container::iterator_traits::difference_type n, F r) BOOST_NOEXCEPT_OR_NOTHROW Chris@102: { Chris@102: typedef typename boost::container::iterator_traits::value_type value_type; Chris@102: std::memmove((iterator_to_raw_pointer)(r), (iterator_to_raw_pointer)(f), sizeof(value_type)*n); Chris@102: boost::container::iterator_advance(f, n); Chris@102: return f; Chris@102: } Chris@102: Chris@102: template Chris@102: // F models ForwardIterator Chris@102: I memmove_n_source_dest(I f, typename boost::container::iterator_traits::difference_type n, F &r) BOOST_NOEXCEPT_OR_NOTHROW Chris@102: { Chris@102: typedef typename boost::container::iterator_traits::value_type value_type; Chris@102: std::memmove((iterator_to_raw_pointer)(r), (iterator_to_raw_pointer)(f), sizeof(value_type)*n); Chris@102: boost::container::iterator_advance(f, n); Chris@102: boost::container::iterator_advance(r, n); Chris@102: return f; Chris@102: } Chris@102: Chris@102: template Chris@102: struct is_memzero_initializable Chris@102: { Chris@102: typedef typename ::boost::container::iterator_traits::value_type value_type; Chris@102: static const bool value = are_elements_contiguous::value && Chris@102: ( container_detail::is_integral::value || container_detail::is_enum::value Chris@102: #if defined(BOOST_CONTAINER_MEMZEROED_POINTER_IS_NULL) Chris@102: || container_detail::is_pointer::value Chris@102: #endif Chris@102: #if defined(BOOST_CONTAINER_MEMZEROED_FLOATING_POINT_IS_ZERO) Chris@102: || container_detail::is_floating_point::value Chris@102: #endif Chris@102: #if defined(BOOST_CONTAINER_MEMZEROED_FLOATING_POINT_IS_ZERO) && defined(BOOST_CONTAINER_MEMZEROED_POINTER_IS_NULL) Chris@102: || container_detail::is_pod::value Chris@102: #endif Chris@102: ); Chris@102: }; Chris@102: Chris@102: template Chris@102: struct enable_if_memzero_initializable Chris@102: : enable_if_c::value, R> Chris@102: {}; Chris@102: Chris@102: template Chris@102: struct disable_if_memzero_initializable Chris@102: : enable_if_c::value, R> Chris@102: {}; Chris@102: Chris@102: template Chris@102: struct enable_if_trivially_destructible Chris@102: : enable_if_c < false/*container_detail::is_trivially_destructible Chris@102: ::value_type>::value*/ Chris@102: , R> Chris@102: {}; Chris@102: Chris@102: template Chris@102: struct disable_if_trivially_destructible Chris@102: : enable_if_c ::value_type>::value*/ Chris@102: , R> Chris@102: {}; Chris@102: Chris@102: } //namespace container_detail { Chris@102: Chris@102: ////////////////////////////////////////////////////////////////////////////// Chris@102: // Chris@102: // uninitialized_move_alloc Chris@102: // Chris@102: ////////////////////////////////////////////////////////////////////////////// Chris@102: Chris@102: Chris@102: //! Effects: Chris@102: //! \code Chris@102: //! for (; f != l; ++r, ++f) Chris@102: //! allocator_traits::construct(a, &*r, boost::move(*f)); Chris@102: //! \endcode Chris@102: //! Chris@102: //! Returns: r Chris@102: template Chris@102: // F models ForwardIterator Chris@102: inline typename container_detail::disable_if_memtransfer_copy_constructible::type Chris@102: uninitialized_move_alloc(Allocator &a, I f, I l, F r) Chris@102: { Chris@102: F back = r; Chris@102: BOOST_TRY{ Chris@102: while (f != l) { Chris@102: allocator_traits::construct(a, container_detail::iterator_to_raw_pointer(r), boost::move(*f)); Chris@102: ++f; ++r; Chris@102: } Chris@102: } Chris@102: BOOST_CATCH(...){ Chris@102: for (; back != r; ++back){ Chris@102: allocator_traits::destroy(a, container_detail::iterator_to_raw_pointer(back)); Chris@102: } Chris@102: BOOST_RETHROW; Chris@102: } Chris@102: BOOST_CATCH_END Chris@102: return r; Chris@102: } Chris@102: Chris@102: template Chris@102: // F models ForwardIterator Chris@102: inline typename container_detail::enable_if_memtransfer_copy_constructible::type Chris@102: uninitialized_move_alloc(Allocator &, I f, I l, F r) BOOST_NOEXCEPT_OR_NOTHROW Chris@102: { return container_detail::memmove(f, l, r); } Chris@102: Chris@102: ////////////////////////////////////////////////////////////////////////////// Chris@102: // Chris@102: // uninitialized_move_alloc_n Chris@102: // Chris@102: ////////////////////////////////////////////////////////////////////////////// Chris@102: Chris@102: //! Effects: Chris@102: //! \code Chris@102: //! for (; n--; ++r, ++f) Chris@102: //! allocator_traits::construct(a, &*r, boost::move(*f)); Chris@102: //! \endcode Chris@102: //! Chris@102: //! Returns: r Chris@102: template Chris@102: // F models ForwardIterator Chris@102: inline typename container_detail::disable_if_memtransfer_copy_constructible::type Chris@102: uninitialized_move_alloc_n(Allocator &a, I f, typename boost::container::iterator_traits::difference_type n, F r) Chris@102: { Chris@102: F back = r; Chris@102: BOOST_TRY{ Chris@102: while (n--) { Chris@102: allocator_traits::construct(a, container_detail::iterator_to_raw_pointer(r), boost::move(*f)); Chris@102: ++f; ++r; Chris@102: } Chris@102: } Chris@102: BOOST_CATCH(...){ Chris@102: for (; back != r; ++back){ Chris@102: allocator_traits::destroy(a, container_detail::iterator_to_raw_pointer(back)); Chris@102: } Chris@102: BOOST_RETHROW; Chris@102: } Chris@102: BOOST_CATCH_END Chris@102: return r; Chris@102: } Chris@102: Chris@102: template Chris@102: // F models ForwardIterator Chris@102: inline typename container_detail::enable_if_memtransfer_copy_constructible::type Chris@102: uninitialized_move_alloc_n(Allocator &, I f, typename boost::container::iterator_traits::difference_type n, F r) BOOST_NOEXCEPT_OR_NOTHROW Chris@102: { return container_detail::memmove_n(f, n, r); } Chris@102: Chris@102: ////////////////////////////////////////////////////////////////////////////// Chris@102: // Chris@102: // uninitialized_move_alloc_n_source Chris@102: // Chris@102: ////////////////////////////////////////////////////////////////////////////// Chris@102: Chris@102: //! Effects: Chris@102: //! \code Chris@102: //! for (; n--; ++r, ++f) Chris@102: //! allocator_traits::construct(a, &*r, boost::move(*f)); Chris@102: //! \endcode Chris@102: //! Chris@102: //! Returns: f (after incremented) Chris@102: template Chris@102: // F models ForwardIterator Chris@102: inline typename container_detail::disable_if_memtransfer_copy_constructible::type Chris@102: uninitialized_move_alloc_n_source(Allocator &a, I f, typename boost::container::iterator_traits::difference_type n, F r) Chris@102: { Chris@102: F back = r; Chris@102: BOOST_TRY{ Chris@102: while (n--) { Chris@102: allocator_traits::construct(a, container_detail::iterator_to_raw_pointer(r), boost::move(*f)); Chris@102: ++f; ++r; Chris@102: } Chris@102: } Chris@102: BOOST_CATCH(...){ Chris@102: for (; back != r; ++back){ Chris@102: allocator_traits::destroy(a, container_detail::iterator_to_raw_pointer(back)); Chris@102: } Chris@102: BOOST_RETHROW; Chris@102: } Chris@102: BOOST_CATCH_END Chris@102: return f; Chris@102: } Chris@102: Chris@102: template Chris@102: // F models ForwardIterator Chris@102: inline typename container_detail::enable_if_memtransfer_copy_constructible::type Chris@102: uninitialized_move_alloc_n_source(Allocator &, I f, typename boost::container::iterator_traits::difference_type n, F r) BOOST_NOEXCEPT_OR_NOTHROW Chris@102: { return container_detail::memmove_n_source(f, n, r); } Chris@102: Chris@102: ////////////////////////////////////////////////////////////////////////////// Chris@102: // Chris@102: // uninitialized_copy_alloc Chris@102: // Chris@102: ////////////////////////////////////////////////////////////////////////////// Chris@102: Chris@102: //! Effects: Chris@102: //! \code Chris@102: //! for (; f != l; ++r, ++f) Chris@102: //! allocator_traits::construct(a, &*r, *f); Chris@102: //! \endcode Chris@102: //! Chris@102: //! Returns: r Chris@102: template Chris@102: // F models ForwardIterator Chris@102: inline typename container_detail::disable_if_memtransfer_copy_constructible::type Chris@102: uninitialized_copy_alloc(Allocator &a, I f, I l, F r) Chris@102: { Chris@102: F back = r; Chris@102: BOOST_TRY{ Chris@102: while (f != l) { Chris@102: allocator_traits::construct(a, container_detail::iterator_to_raw_pointer(r), *f); Chris@102: ++f; ++r; Chris@102: } Chris@102: } Chris@102: BOOST_CATCH(...){ Chris@102: for (; back != r; ++back){ Chris@102: allocator_traits::destroy(a, container_detail::iterator_to_raw_pointer(back)); Chris@102: } Chris@102: BOOST_RETHROW; Chris@102: } Chris@102: BOOST_CATCH_END Chris@102: return r; Chris@102: } Chris@102: Chris@102: template Chris@102: // F models ForwardIterator Chris@102: inline typename container_detail::enable_if_memtransfer_copy_constructible::type Chris@102: uninitialized_copy_alloc(Allocator &, I f, I l, F r) BOOST_NOEXCEPT_OR_NOTHROW Chris@102: { return container_detail::memmove(f, l, r); } Chris@102: Chris@102: ////////////////////////////////////////////////////////////////////////////// Chris@102: // Chris@102: // uninitialized_copy_alloc_n Chris@102: // Chris@102: ////////////////////////////////////////////////////////////////////////////// Chris@102: Chris@102: //! Effects: Chris@102: //! \code Chris@102: //! for (; n--; ++r, ++f) Chris@102: //! allocator_traits::construct(a, &*r, *f); Chris@102: //! \endcode Chris@102: //! Chris@102: //! Returns: r Chris@102: template Chris@102: // F models ForwardIterator Chris@102: inline typename container_detail::disable_if_memtransfer_copy_constructible::type Chris@102: uninitialized_copy_alloc_n(Allocator &a, I f, typename boost::container::iterator_traits::difference_type n, F r) Chris@102: { Chris@102: F back = r; Chris@102: BOOST_TRY{ Chris@102: while (n--) { Chris@102: allocator_traits::construct(a, container_detail::iterator_to_raw_pointer(r), *f); Chris@102: ++f; ++r; Chris@102: } Chris@102: } Chris@102: BOOST_CATCH(...){ Chris@102: for (; back != r; ++back){ Chris@102: allocator_traits::destroy(a, container_detail::iterator_to_raw_pointer(back)); Chris@102: } Chris@102: BOOST_RETHROW; Chris@102: } Chris@102: BOOST_CATCH_END Chris@102: return r; Chris@102: } Chris@102: Chris@102: template Chris@102: // F models ForwardIterator Chris@102: inline typename container_detail::enable_if_memtransfer_copy_constructible::type Chris@102: uninitialized_copy_alloc_n(Allocator &, I f, typename boost::container::iterator_traits::difference_type n, F r) BOOST_NOEXCEPT_OR_NOTHROW Chris@102: { return container_detail::memmove_n(f, n, r); } Chris@102: Chris@102: ////////////////////////////////////////////////////////////////////////////// Chris@102: // Chris@102: // uninitialized_copy_alloc_n_source Chris@102: // Chris@102: ////////////////////////////////////////////////////////////////////////////// Chris@102: Chris@102: //! Effects: Chris@102: //! \code Chris@102: //! for (; n--; ++r, ++f) Chris@102: //! allocator_traits::construct(a, &*r, *f); Chris@102: //! \endcode Chris@102: //! Chris@102: //! Returns: f (after incremented) Chris@102: template Chris@102: // F models ForwardIterator Chris@102: inline typename container_detail::disable_if_memtransfer_copy_constructible::type Chris@102: uninitialized_copy_alloc_n_source(Allocator &a, I f, typename boost::container::iterator_traits::difference_type n, F r) Chris@102: { Chris@102: F back = r; Chris@102: BOOST_TRY{ Chris@102: while (n--) { Chris@102: allocator_traits::construct(a, container_detail::iterator_to_raw_pointer(r), *f); Chris@102: ++f; ++r; Chris@102: } Chris@102: } Chris@102: BOOST_CATCH(...){ Chris@102: for (; back != r; ++back){ Chris@102: allocator_traits::destroy(a, container_detail::iterator_to_raw_pointer(back)); Chris@102: } Chris@102: BOOST_RETHROW; Chris@102: } Chris@102: BOOST_CATCH_END Chris@102: return f; Chris@102: } Chris@102: Chris@102: template Chris@102: // F models ForwardIterator Chris@102: inline typename container_detail::enable_if_memtransfer_copy_constructible::type Chris@102: uninitialized_copy_alloc_n_source(Allocator &, I f, typename boost::container::iterator_traits::difference_type n, F r) BOOST_NOEXCEPT_OR_NOTHROW Chris@102: { return container_detail::memmove_n_source(f, n, r); } Chris@102: Chris@102: ////////////////////////////////////////////////////////////////////////////// Chris@102: // Chris@102: // uninitialized_value_init_alloc_n Chris@102: // Chris@102: ////////////////////////////////////////////////////////////////////////////// Chris@102: Chris@102: //! Effects: Chris@102: //! \code Chris@102: //! for (; n--; ++r, ++f) Chris@102: //! allocator_traits::construct(a, &*r); Chris@102: //! \endcode Chris@102: //! Chris@102: //! Returns: r Chris@102: template Chris@102: // F models ForwardIterator Chris@102: inline typename container_detail::disable_if_memzero_initializable::type Chris@102: uninitialized_value_init_alloc_n(Allocator &a, typename allocator_traits::difference_type n, F r) Chris@102: { Chris@102: F back = r; Chris@102: BOOST_TRY{ Chris@102: while (n--) { Chris@102: allocator_traits::construct(a, container_detail::iterator_to_raw_pointer(r)); Chris@102: ++r; Chris@102: } Chris@102: } Chris@102: BOOST_CATCH(...){ Chris@102: for (; back != r; ++back){ Chris@102: allocator_traits::destroy(a, container_detail::iterator_to_raw_pointer(back)); Chris@102: } Chris@102: BOOST_RETHROW; Chris@102: } Chris@102: BOOST_CATCH_END Chris@102: return r; Chris@102: } Chris@102: Chris@102: template Chris@102: // F models ForwardIterator Chris@102: inline typename container_detail::enable_if_memzero_initializable::type Chris@102: uninitialized_value_init_alloc_n(Allocator &, typename allocator_traits::difference_type n, F r) Chris@102: { Chris@102: typedef typename boost::container::iterator_traits::value_type value_type; Chris@102: std::memset((void*)container_detail::iterator_to_raw_pointer(r), 0, sizeof(value_type)*n); Chris@102: boost::container::iterator_advance(r, n); Chris@102: return r; Chris@102: } Chris@102: Chris@102: ////////////////////////////////////////////////////////////////////////////// Chris@102: // Chris@102: // uninitialized_default_init_alloc_n Chris@102: // Chris@102: ////////////////////////////////////////////////////////////////////////////// Chris@102: Chris@102: //! Effects: Chris@102: //! \code Chris@102: //! for (; n--; ++r, ++f) Chris@102: //! allocator_traits::construct(a, &*r); Chris@102: //! \endcode Chris@102: //! Chris@102: //! Returns: r Chris@102: template Chris@102: // F models ForwardIterator Chris@102: inline F uninitialized_default_init_alloc_n(Allocator &a, typename allocator_traits::difference_type n, F r) Chris@102: { Chris@102: F back = r; Chris@102: BOOST_TRY{ Chris@102: while (n--) { Chris@102: allocator_traits::construct(a, container_detail::iterator_to_raw_pointer(r), default_init); Chris@102: ++r; Chris@102: } Chris@102: } Chris@102: BOOST_CATCH(...){ Chris@102: for (; back != r; ++back){ Chris@102: allocator_traits::destroy(a, container_detail::iterator_to_raw_pointer(back)); Chris@102: } Chris@102: BOOST_RETHROW; Chris@102: } Chris@102: BOOST_CATCH_END Chris@102: return r; Chris@102: } Chris@102: Chris@102: ////////////////////////////////////////////////////////////////////////////// Chris@102: // Chris@102: // uninitialized_fill_alloc Chris@102: // Chris@102: ////////////////////////////////////////////////////////////////////////////// Chris@102: Chris@102: //! Effects: Chris@102: //! \code Chris@102: //! for (; f != l; ++r, ++f) Chris@102: //! allocator_traits::construct(a, &*r, *f); Chris@102: //! \endcode Chris@102: //! Chris@102: //! Returns: r Chris@102: template Chris@102: Chris@102: inline void uninitialized_fill_alloc(Allocator &a, F f, F l, const T &t) Chris@102: { Chris@102: F back = f; Chris@102: BOOST_TRY{ Chris@102: while (f != l) { Chris@102: allocator_traits::construct(a, container_detail::iterator_to_raw_pointer(f), t); Chris@102: ++f; Chris@102: } Chris@102: } Chris@102: BOOST_CATCH(...){ Chris@102: for (; back != l; ++back){ Chris@102: allocator_traits::destroy(a, container_detail::iterator_to_raw_pointer(back)); Chris@102: } Chris@102: BOOST_RETHROW; Chris@102: } Chris@102: BOOST_CATCH_END Chris@102: } Chris@102: Chris@102: Chris@102: ////////////////////////////////////////////////////////////////////////////// Chris@102: // Chris@102: // uninitialized_fill_alloc_n Chris@102: // Chris@102: ////////////////////////////////////////////////////////////////////////////// Chris@102: Chris@102: //! Effects: Chris@102: //! \code Chris@102: //! for (; n--; ++r, ++f) Chris@102: //! allocator_traits::construct(a, &*r, v); Chris@102: //! \endcode Chris@102: //! Chris@102: //! Returns: r Chris@102: template Chris@102: // F models ForwardIterator Chris@102: inline F uninitialized_fill_alloc_n(Allocator &a, const T &v, typename allocator_traits::difference_type n, F r) Chris@102: { Chris@102: F back = r; Chris@102: BOOST_TRY{ Chris@102: while (n--) { Chris@102: allocator_traits::construct(a, container_detail::iterator_to_raw_pointer(r), v); Chris@102: ++r; Chris@102: } Chris@102: } Chris@102: BOOST_CATCH(...){ Chris@102: for (; back != r; ++back){ Chris@102: allocator_traits::destroy(a, container_detail::iterator_to_raw_pointer(back)); Chris@102: } Chris@102: BOOST_RETHROW; Chris@102: } Chris@102: BOOST_CATCH_END Chris@102: return r; Chris@102: } Chris@102: Chris@102: ////////////////////////////////////////////////////////////////////////////// Chris@102: // Chris@102: // copy Chris@102: // Chris@102: ////////////////////////////////////////////////////////////////////////////// Chris@102: Chris@102: template Chris@102: // F models ForwardIterator Chris@102: inline typename container_detail::disable_if_memtransfer_copy_assignable::type Chris@102: copy(I f, I l, F r) Chris@102: { Chris@102: while (f != l) { Chris@102: *r = *f; Chris@102: ++f; ++r; Chris@102: } Chris@102: return r; Chris@102: } Chris@102: Chris@102: template Chris@102: // F models ForwardIterator Chris@102: inline typename container_detail::enable_if_memtransfer_copy_assignable::type Chris@102: copy(I f, I l, F r) BOOST_NOEXCEPT_OR_NOTHROW Chris@102: { return container_detail::memmove(f, l, r); } Chris@102: Chris@102: ////////////////////////////////////////////////////////////////////////////// Chris@102: // Chris@102: // copy_n Chris@102: // Chris@102: ////////////////////////////////////////////////////////////////////////////// Chris@102: Chris@102: template Chris@102: // F models ForwardIterator Chris@102: inline typename container_detail::disable_if_memtransfer_copy_assignable::type Chris@102: copy_n(I f, typename boost::container::iterator_traits::difference_type n, F r) Chris@102: { Chris@102: while (n--) { Chris@102: *r = *f; Chris@102: ++f; ++r; Chris@102: } Chris@102: return r; Chris@102: } Chris@102: Chris@102: template Chris@102: // F models ForwardIterator Chris@102: inline typename container_detail::enable_if_memtransfer_copy_assignable::type Chris@102: copy_n(I f, typename boost::container::iterator_traits::difference_type n, F r) BOOST_NOEXCEPT_OR_NOTHROW Chris@102: { return container_detail::memmove_n(f, n, r); } Chris@102: Chris@102: ////////////////////////////////////////////////////////////////////////////// Chris@102: // Chris@102: // copy_n_source Chris@102: // Chris@102: ////////////////////////////////////////////////////////////////////////////// Chris@102: Chris@102: template Chris@102: // F models ForwardIterator Chris@102: inline typename container_detail::disable_if_memtransfer_copy_assignable::type Chris@102: copy_n_source(I f, typename boost::container::iterator_traits::difference_type n, F r) Chris@102: { Chris@102: while (n--) { Chris@102: *r = *f; Chris@102: ++f; ++r; Chris@102: } Chris@102: return f; Chris@102: } Chris@102: Chris@102: template Chris@102: // F models ForwardIterator Chris@102: inline typename container_detail::enable_if_memtransfer_copy_assignable::type Chris@102: copy_n_source(I f, typename boost::container::iterator_traits::difference_type n, F r) BOOST_NOEXCEPT_OR_NOTHROW Chris@102: { return container_detail::memmove_n_source(f, n, r); } Chris@102: Chris@102: ////////////////////////////////////////////////////////////////////////////// Chris@102: // Chris@102: // copy_n_source_dest Chris@102: // Chris@102: ////////////////////////////////////////////////////////////////////////////// Chris@102: Chris@102: template Chris@102: // F models ForwardIterator Chris@102: inline typename container_detail::disable_if_memtransfer_copy_assignable::type Chris@102: copy_n_source_dest(I f, typename boost::container::iterator_traits::difference_type n, F &r) Chris@102: { Chris@102: while (n--) { Chris@102: *r = *f; Chris@102: ++f; ++r; Chris@102: } Chris@102: return f; Chris@102: } Chris@102: Chris@102: template Chris@102: // F models ForwardIterator Chris@102: inline typename container_detail::enable_if_memtransfer_copy_assignable::type Chris@102: copy_n_source_dest(I f, typename boost::container::iterator_traits::difference_type n, F &r) BOOST_NOEXCEPT_OR_NOTHROW Chris@102: { return container_detail::memmove_n_source_dest(f, n, r); } Chris@102: Chris@102: ////////////////////////////////////////////////////////////////////////////// Chris@102: // Chris@102: // move Chris@102: // Chris@102: ////////////////////////////////////////////////////////////////////////////// Chris@102: Chris@102: template Chris@102: // F models ForwardIterator Chris@102: inline typename container_detail::disable_if_memtransfer_copy_assignable::type Chris@102: move(I f, I l, F r) Chris@102: { Chris@102: while (f != l) { Chris@102: *r = ::boost::move(*f); Chris@102: ++f; ++r; Chris@102: } Chris@102: return r; Chris@102: } Chris@102: Chris@102: template Chris@102: // F models ForwardIterator Chris@102: inline typename container_detail::enable_if_memtransfer_copy_assignable::type Chris@102: move(I f, I l, F r) BOOST_NOEXCEPT_OR_NOTHROW Chris@102: { return container_detail::memmove(f, l, r); } Chris@102: Chris@102: ////////////////////////////////////////////////////////////////////////////// Chris@102: // Chris@102: // move_n Chris@102: // Chris@102: ////////////////////////////////////////////////////////////////////////////// Chris@102: Chris@102: template Chris@102: // F models ForwardIterator Chris@102: inline typename container_detail::disable_if_memtransfer_copy_assignable::type Chris@102: move_n(I f, typename boost::container::iterator_traits::difference_type n, F r) Chris@102: { Chris@102: while (n--) { Chris@102: *r = ::boost::move(*f); Chris@102: ++f; ++r; Chris@102: } Chris@102: return r; Chris@102: } Chris@102: Chris@102: template Chris@102: // F models ForwardIterator Chris@102: inline typename container_detail::enable_if_memtransfer_copy_assignable::type Chris@102: move_n(I f, typename boost::container::iterator_traits::difference_type n, F r) BOOST_NOEXCEPT_OR_NOTHROW Chris@102: { return container_detail::memmove_n(f, n, r); } Chris@102: Chris@102: Chris@102: ////////////////////////////////////////////////////////////////////////////// Chris@102: // Chris@102: // move_backward Chris@102: // Chris@102: ////////////////////////////////////////////////////////////////////////////// Chris@102: Chris@102: template Chris@102: // F models ForwardIterator Chris@102: inline typename container_detail::disable_if_memtransfer_copy_assignable::type Chris@102: move_backward(I f, I l, F r) Chris@102: { Chris@102: while (f != l) { Chris@102: --l; --r; Chris@102: *r = ::boost::move(*l); Chris@102: } Chris@102: return r; Chris@102: } Chris@102: Chris@102: template Chris@102: // F models ForwardIterator Chris@102: inline typename container_detail::enable_if_memtransfer_copy_assignable::type Chris@102: move_backward(I f, I l, F r) BOOST_NOEXCEPT_OR_NOTHROW Chris@102: { Chris@102: typedef typename boost::container::iterator_traits::value_type value_type; Chris@102: const typename boost::container::iterator_traits::difference_type n = boost::container::iterator_distance(f, l); Chris@102: r -= n; Chris@102: std::memmove((container_detail::iterator_to_raw_pointer)(r), (container_detail::iterator_to_raw_pointer)(f), sizeof(value_type)*n); Chris@102: return r; Chris@102: } Chris@102: Chris@102: ////////////////////////////////////////////////////////////////////////////// Chris@102: // Chris@102: // move_n_source_dest Chris@102: // Chris@102: ////////////////////////////////////////////////////////////////////////////// Chris@102: Chris@102: template Chris@102: // F models ForwardIterator Chris@102: inline typename container_detail::disable_if_memtransfer_copy_assignable::type Chris@102: move_n_source_dest(I f, typename boost::container::iterator_traits::difference_type n, F &r) Chris@102: { Chris@102: while (n--) { Chris@102: *r = ::boost::move(*f); Chris@102: ++f; ++r; Chris@102: } Chris@102: return f; Chris@102: } Chris@102: Chris@102: template Chris@102: // F models ForwardIterator Chris@102: inline typename container_detail::enable_if_memtransfer_copy_assignable::type Chris@102: move_n_source_dest(I f, typename boost::container::iterator_traits::difference_type n, F &r) BOOST_NOEXCEPT_OR_NOTHROW Chris@102: { return container_detail::memmove_n_source_dest(f, n, r); } Chris@102: Chris@102: ////////////////////////////////////////////////////////////////////////////// Chris@102: // Chris@102: // move_n_source Chris@102: // Chris@102: ////////////////////////////////////////////////////////////////////////////// Chris@102: Chris@102: template Chris@102: // F models ForwardIterator Chris@102: inline typename container_detail::disable_if_memtransfer_copy_assignable::type Chris@102: move_n_source(I f, typename boost::container::iterator_traits::difference_type n, F r) Chris@102: { Chris@102: while (n--) { Chris@102: *r = ::boost::move(*f); Chris@102: ++f; ++r; Chris@102: } Chris@102: return f; Chris@102: } Chris@102: Chris@102: template Chris@102: // F models ForwardIterator Chris@102: inline typename container_detail::enable_if_memtransfer_copy_assignable::type Chris@102: move_n_source(I f, typename boost::container::iterator_traits::difference_type n, F r) BOOST_NOEXCEPT_OR_NOTHROW Chris@102: { return container_detail::memmove_n_source(f, n, r); } Chris@102: Chris@102: ////////////////////////////////////////////////////////////////////////////// Chris@102: // Chris@102: // destroy_alloc_n Chris@102: // Chris@102: ////////////////////////////////////////////////////////////////////////////// Chris@102: Chris@102: template Chris@102: // U models unsigned integral constant Chris@102: inline typename container_detail::disable_if_trivially_destructible::type Chris@102: destroy_alloc_n(Allocator &a, I f, U n) Chris@102: { Chris@102: while(n--){ Chris@102: allocator_traits::destroy(a, container_detail::iterator_to_raw_pointer(f)); Chris@102: ++f; Chris@102: } Chris@102: } Chris@102: Chris@102: template Chris@102: // U models unsigned integral constant Chris@102: inline typename container_detail::enable_if_trivially_destructible::type Chris@102: destroy_alloc_n(Allocator &, I, U) Chris@102: {} Chris@102: Chris@102: ////////////////////////////////////////////////////////////////////////////// Chris@102: // Chris@102: // deep_swap_alloc_n Chris@102: // Chris@102: ////////////////////////////////////////////////////////////////////////////// Chris@102: Chris@102: template Chris@102: Chris@102: inline typename container_detail::disable_if_memtransfer_copy_assignable::type Chris@102: deep_swap_alloc_n( Allocator &a, F short_range_f, typename allocator_traits::size_type n_i Chris@102: , G large_range_f, typename allocator_traits::size_type n_j) Chris@102: { Chris@102: typename allocator_traits::size_type n = 0; Chris@102: for (; n != n_i ; ++short_range_f, ++large_range_f, ++n){ Chris@102: boost::adl_move_swap(*short_range_f, *large_range_f); Chris@102: } Chris@102: boost::container::uninitialized_move_alloc_n(a, large_range_f, n_j - n_i, short_range_f); // may throw Chris@102: boost::container::destroy_alloc_n(a, large_range_f, n_j - n_i); Chris@102: } Chris@102: Chris@102: static const std::size_t DeepSwapAllocNMaxStorage = std::size_t(1) << std::size_t(11); //2K bytes Chris@102: Chris@102: template Chris@102: Chris@102: inline typename container_detail::enable_if_c Chris@102: < container_detail::is_memtransfer_copy_assignable::value && (MaxTmpBytes <= DeepSwapAllocNMaxStorage) && false Chris@102: , void>::type Chris@102: deep_swap_alloc_n( Allocator &a, F short_range_f, typename allocator_traits::size_type n_i Chris@102: , G large_range_f, typename allocator_traits::size_type n_j) Chris@102: { Chris@102: typedef typename allocator_traits::value_type value_type; Chris@102: typedef typename container_detail::aligned_storage Chris@102: ::value>::type storage_type; Chris@102: storage_type storage; Chris@102: Chris@102: const std::size_t n_i_bytes = sizeof(value_type)*n_i; Chris@102: void *const large_ptr = static_cast(container_detail::iterator_to_raw_pointer(large_range_f)); Chris@102: void *const short_ptr = static_cast(container_detail::iterator_to_raw_pointer(short_range_f)); Chris@102: void *const stora_ptr = static_cast(container_detail::iterator_to_raw_pointer(storage)); Chris@102: std::memcpy(stora_ptr, large_ptr, n_i_bytes); Chris@102: std::memcpy(large_ptr, short_ptr, n_i_bytes); Chris@102: std::memcpy(short_ptr, stora_ptr, n_i_bytes); Chris@102: boost::container::iterator_advance(large_range_f, n_i); Chris@102: boost::container::iterator_advance(short_range_f, n_i); Chris@102: boost::container::uninitialized_move_alloc_n(a, large_range_f, n_j - n_i, short_range_f); // may throw Chris@102: boost::container::destroy_alloc_n(a, large_range_f, n_j - n_i); Chris@102: } Chris@102: Chris@102: template Chris@102: Chris@102: inline typename container_detail::enable_if_c Chris@102: < container_detail::is_memtransfer_copy_assignable::value && true//(MaxTmpBytes > DeepSwapAllocNMaxStorage) Chris@102: , void>::type Chris@102: deep_swap_alloc_n( Allocator &a, F short_range_f, typename allocator_traits::size_type n_i Chris@102: , G large_range_f, typename allocator_traits::size_type n_j) Chris@102: { Chris@102: typedef typename allocator_traits::value_type value_type; Chris@102: typedef typename container_detail::aligned_storage Chris@102: ::value>::type storage_type; Chris@102: storage_type storage; Chris@102: const std::size_t sizeof_storage = sizeof(storage); Chris@102: Chris@102: std::size_t n_i_bytes = sizeof(value_type)*n_i; Chris@102: char *large_ptr = static_cast(static_cast(container_detail::iterator_to_raw_pointer(large_range_f))); Chris@102: char *short_ptr = static_cast(static_cast(container_detail::iterator_to_raw_pointer(short_range_f))); Chris@102: char *stora_ptr = static_cast(static_cast(&storage)); Chris@102: Chris@102: std::size_t szt_times = n_i_bytes/sizeof_storage; Chris@102: const std::size_t szt_rem = n_i_bytes%sizeof_storage; Chris@102: Chris@102: //Loop unrolling using Duff's device, as it seems it helps on some architectures Chris@102: const std::size_t Unroll = 4; Chris@102: std::size_t n = (szt_times + (Unroll-1))/Unroll; Chris@102: const std::size_t branch_number = (!szt_times)*Unroll + (szt_times % Unroll); Chris@102: switch(branch_number){ Chris@102: case 4: Chris@102: break; Chris@102: case 0: do{ Chris@102: std::memcpy(stora_ptr, large_ptr, sizeof_storage); Chris@102: std::memcpy(large_ptr, short_ptr, sizeof_storage); Chris@102: std::memcpy(short_ptr, stora_ptr, sizeof_storage); Chris@102: large_ptr += sizeof_storage; Chris@102: short_ptr += sizeof_storage; Chris@102: BOOST_CONTAINER_FALLTHOUGH Chris@102: case 3: Chris@102: std::memcpy(stora_ptr, large_ptr, sizeof_storage); Chris@102: std::memcpy(large_ptr, short_ptr, sizeof_storage); Chris@102: std::memcpy(short_ptr, stora_ptr, sizeof_storage); Chris@102: large_ptr += sizeof_storage; Chris@102: short_ptr += sizeof_storage; Chris@102: BOOST_CONTAINER_FALLTHOUGH Chris@102: case 2: Chris@102: std::memcpy(stora_ptr, large_ptr, sizeof_storage); Chris@102: std::memcpy(large_ptr, short_ptr, sizeof_storage); Chris@102: std::memcpy(short_ptr, stora_ptr, sizeof_storage); Chris@102: large_ptr += sizeof_storage; Chris@102: short_ptr += sizeof_storage; Chris@102: BOOST_CONTAINER_FALLTHOUGH Chris@102: case 1: Chris@102: std::memcpy(stora_ptr, large_ptr, sizeof_storage); Chris@102: std::memcpy(large_ptr, short_ptr, sizeof_storage); Chris@102: std::memcpy(short_ptr, stora_ptr, sizeof_storage); Chris@102: large_ptr += sizeof_storage; Chris@102: short_ptr += sizeof_storage; Chris@102: } while(--n); Chris@102: } Chris@102: std::memcpy(stora_ptr, large_ptr, szt_rem); Chris@102: std::memcpy(large_ptr, short_ptr, szt_rem); Chris@102: std::memcpy(short_ptr, stora_ptr, szt_rem); Chris@102: boost::container::iterator_advance(large_range_f, n_i); Chris@102: boost::container::iterator_advance(short_range_f, n_i); Chris@102: boost::container::uninitialized_move_alloc_n(a, large_range_f, n_j - n_i, short_range_f); // may throw Chris@102: boost::container::destroy_alloc_n(a, large_range_f, n_j - n_i); Chris@102: } Chris@102: Chris@102: Chris@102: ////////////////////////////////////////////////////////////////////////////// Chris@102: // Chris@102: // copy_assign_range_alloc_n Chris@102: // Chris@102: ////////////////////////////////////////////////////////////////////////////// Chris@102: Chris@102: template Chris@102: Chris@102: void copy_assign_range_alloc_n( Allocator &a, I inp_start, typename allocator_traits::size_type n_i Chris@102: , O out_start, typename allocator_traits::size_type n_o ) Chris@102: { Chris@102: if (n_o < n_i){ Chris@102: inp_start = boost::container::copy_n_source_dest(inp_start, n_o, out_start); // may throw Chris@102: boost::container::uninitialized_copy_alloc_n(a, inp_start, n_i - n_o, out_start);// may throw Chris@102: } Chris@102: else{ Chris@102: out_start = boost::container::copy_n(inp_start, n_i, out_start); // may throw Chris@102: boost::container::destroy_alloc_n(a, out_start, n_o - n_i); Chris@102: } Chris@102: } Chris@102: Chris@102: ////////////////////////////////////////////////////////////////////////////// Chris@102: // Chris@102: // move_assign_range_alloc_n Chris@102: // Chris@102: ////////////////////////////////////////////////////////////////////////////// Chris@102: Chris@102: template Chris@102: Chris@102: void move_assign_range_alloc_n( Allocator &a, I inp_start, typename allocator_traits::size_type n_i Chris@102: , O out_start, typename allocator_traits::size_type n_o ) Chris@102: { Chris@102: if (n_o < n_i){ Chris@102: inp_start = boost::container::move_n_source_dest(inp_start, n_o, out_start); // may throw Chris@102: boost::container::uninitialized_move_alloc_n(a, inp_start, n_i - n_o, out_start); // may throw Chris@102: } Chris@102: else{ Chris@102: out_start = boost::container::move_n(inp_start, n_i, out_start); // may throw Chris@102: boost::container::destroy_alloc_n(a, out_start, n_o - n_i); Chris@102: } Chris@102: } Chris@102: Chris@102: } //namespace container { Chris@102: } //namespace boost { Chris@102: Chris@102: #endif //#ifndef BOOST_CONTAINER_DETAIL_UTILITIES_HPP