1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180 |
- //////////////////////////////////////////////////////////////////////////////
- //
- // (C) Copyright Ion Gaztanaga 2005-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_UTILITIES_HPP
- #define BOOST_CONTAINER_DETAIL_UTILITIES_HPP
- #include "config_begin.hpp"
- #include "workaround.hpp"
- #include <cstdio>
- #include <cstring> //for ::memcpy
- #include <boost/type_traits/is_fundamental.hpp>
- #include <boost/type_traits/is_pointer.hpp>
- #include <boost/type_traits/is_enum.hpp>
- #include <boost/type_traits/is_member_pointer.hpp>
- #include <boost/type_traits/is_class.hpp>
- #include <boost/type_traits/has_trivial_destructor.hpp>
- #include <boost/move/core.hpp>
- #include <boost/move/utility.hpp>
- #include <boost/move/iterator.hpp>
- #include <boost/container/detail/mpl.hpp>
- #include <boost/container/detail/type_traits.hpp>
- #include <boost/container/allocator_traits.hpp>
- #include <boost/detail/no_exceptions_support.hpp>
- #include <boost/type_traits/has_trivial_copy.hpp>
- #include <boost/type_traits/has_trivial_assign.hpp>
- #include <boost/container/detail/memory_util.hpp>
- #include <boost/aligned_storage.hpp>
- #include <algorithm>
- #include <iterator>
- #include <utility> //std::distance
- namespace boost {
- namespace container {
- //////////////////////////////////////////////////////////////////////////////
- //
- // swap
- //
- //////////////////////////////////////////////////////////////////////////////
- namespace container_swap {
- template<class T, bool IsClass = boost::is_class<T>::value >
- struct has_member_swap
- {
- static const bool value = boost::container::container_detail::
- has_member_function_callable_with_swap<T, T &>::value;
- };
- template<class T>
- struct has_member_swap<T, false>
- {
- static const bool value = false;
- };
- } //namespace container_swap {
- template<class T> inline
- typename container_detail::enable_if_c
- <container_swap::has_member_swap<T>::value, void>::type
- swap_dispatch(T &left, T &right) //swap using member swap
- {
- left.swap(right); // may throw
- }
- template<class T> inline
- typename container_detail::enable_if_c
- <!container_swap::has_member_swap<T>::value && boost::has_move_emulation_enabled<T>::value, void>::type
- swap_dispatch(T &left, T &right)
- {
- T temp(boost::move(left)); // may throw
- left = boost::move(right); // may throw
- right = boost::move(temp); // may throw
- }
- template<class T> inline
- typename container_detail::enable_if_c
- <!container_swap::has_member_swap<T>::value && !boost::has_move_emulation_enabled<T>::value, void>::type
- swap_dispatch(T &left, T &right)
- {
- using std::swap;
- swap(left, right); // may throw
- }
- namespace container_detail {
- template <typename T>
- inline T* addressof(T& obj)
- {
- return static_cast<T*>(
- static_cast<void*>(
- const_cast<char*>(
- &reinterpret_cast<const char&>(obj)
- )));
- }
- template<class T>
- const T &max_value(const T &a, const T &b)
- { return a > b ? a : b; }
- template<class T>
- const T &min_value(const T &a, const T &b)
- { return a < b ? a : b; }
- template <class SizeType>
- SizeType
- get_next_capacity(const SizeType max_size
- ,const SizeType capacity
- ,const SizeType n)
- {
- // if (n > max_size - capacity)
- // throw std::length_error("get_next_capacity");
- const SizeType m3 = max_size/3;
- if (capacity < m3)
- return capacity + max_value(3*(capacity+1)/5, n);
- if (capacity < m3*2)
- return capacity + max_value((capacity+1)/2, n);
- return max_size;
- }
- template <class T>
- inline T* to_raw_pointer(T* p)
- { return p; }
- template <class Pointer>
- inline typename Pointer::element_type*
- to_raw_pointer(const Pointer &p)
- { return boost::container::container_detail::to_raw_pointer(p.operator->()); }
- template<class AllocatorType>
- inline void swap_alloc(AllocatorType &, AllocatorType &, container_detail::false_type)
- BOOST_CONTAINER_NOEXCEPT
- {}
- template<class AllocatorType>
- inline void swap_alloc(AllocatorType &l, AllocatorType &r, container_detail::true_type)
- { boost::container::swap_dispatch(l, r); }
- template<class AllocatorType>
- inline void assign_alloc(AllocatorType &, const AllocatorType &, container_detail::false_type)
- BOOST_CONTAINER_NOEXCEPT
- {}
- template<class AllocatorType>
- inline void assign_alloc(AllocatorType &l, const AllocatorType &r, container_detail::true_type)
- { l = r; }
- template<class AllocatorType>
- inline void move_alloc(AllocatorType &, AllocatorType &, container_detail::false_type)
- BOOST_CONTAINER_NOEXCEPT
- {}
- template<class AllocatorType>
- inline void move_alloc(AllocatorType &l, AllocatorType &r, container_detail::true_type)
- { l = ::boost::move(r); }
- //Rounds "orig_size" by excess to round_to bytes
- template<class SizeType>
- inline SizeType get_rounded_size(SizeType orig_size, SizeType round_to)
- {
- return ((orig_size-1)/round_to+1)*round_to;
- }
- template <std::size_t OrigSize, std::size_t RoundTo>
- struct ct_rounded_size
- {
- enum { value = ((OrigSize-1)/RoundTo+1)*RoundTo };
- };
- template<class I>
- struct are_elements_contiguous
- {
- static const bool value = false;
- };
- /////////////////////////
- // raw pointers
- /////////////////////////
- template<class T>
- struct are_elements_contiguous<T*>
- {
- static const bool value = true;
- };
- /////////////////////////
- // predeclarations
- /////////////////////////
- #ifndef BOOST_CONTAINER_VECTOR_ITERATOR_IS_POINTER
- template<class Pointer>
- class vector_iterator;
- template<class Pointer>
- class vector_const_iterator;
- #endif //BOOST_CONTAINER_VECTOR_ITERATOR_IS_POINTER
- } //namespace container_detail {
- } //namespace container {
- namespace interprocess {
- template <class PointedType, class DifferenceType, class OffsetType, std::size_t OffsetAlignment>
- class offset_ptr;
- } //namespace interprocess {
- namespace container {
- namespace container_detail {
- /////////////////////////
- //vector_[const_]iterator
- /////////////////////////
- #ifndef BOOST_CONTAINER_VECTOR_ITERATOR_IS_POINTER
- template<class Pointer>
- struct are_elements_contiguous<boost::container::container_detail::vector_iterator<Pointer> >
- {
- static const bool value = true;
- };
- template<class Pointer>
- struct are_elements_contiguous<boost::container::container_detail::vector_const_iterator<Pointer> >
- {
- static const bool value = true;
- };
- #endif //BOOST_CONTAINER_VECTOR_ITERATOR_IS_POINTER
- /////////////////////////
- // offset_ptr
- /////////////////////////
- template <class PointedType, class DifferenceType, class OffsetType, std::size_t OffsetAlignment>
- struct are_elements_contiguous< ::boost::interprocess::offset_ptr<PointedType, DifferenceType, OffsetType, OffsetAlignment> >
- {
- static const bool value = true;
- };
- template <typename I, typename O>
- struct are_contiguous_and_same
- {
- static const bool is_same_io =
- is_same< typename remove_const< typename ::std::iterator_traits<I>::value_type >::type
- , typename ::std::iterator_traits<O>::value_type
- >::value;
- static const bool value = is_same_io &&
- are_elements_contiguous<I>::value &&
- are_elements_contiguous<O>::value;
- };
- template <typename I, typename O>
- struct is_memcpy_copy_assignable
- {
- static const bool value = are_contiguous_and_same<I, O>::value &&
- boost::has_trivial_assign< typename ::std::iterator_traits<I>::value_type >::value;
- };
- template <typename I, typename O>
- struct is_memcpy_copy_constructible
- {
- static const bool value = are_contiguous_and_same<I, O>::value &&
- boost::has_trivial_copy< typename ::std::iterator_traits<I>::value_type >::value;
- };
- template <typename I, typename O, typename R>
- struct enable_if_memcpy_copy_constructible
- : public enable_if_c<container_detail::is_memcpy_copy_constructible<I, O>::value, R>
- {};
- template <typename I, typename O, typename R>
- struct disable_if_memcpy_copy_constructible
- : public enable_if_c<!container_detail::is_memcpy_copy_constructible<I, O>::value, R>
- {};
- template <typename I, typename O, typename R>
- struct enable_if_memcpy_copy_assignable
- : public enable_if_c<container_detail::is_memcpy_copy_assignable<I, O>::value, R>
- {};
- template <typename I, typename O, typename R>
- struct disable_if_memcpy_copy_assignable
- : public enable_if_c<!container_detail::is_memcpy_copy_assignable<I, O>::value, R>
- {};
- template
- <typename I, // I models InputIterator
- typename F> // F models ForwardIterator
- inline F memcpy(I f, I l, F r) BOOST_CONTAINER_NOEXCEPT
- {
- typedef typename std::iterator_traits<I>::value_type value_type;
- typename std::iterator_traits<I>::difference_type n = std::distance(f, l);
- ::memcpy(container_detail::addressof(*r), container_detail::addressof(*f), sizeof(value_type)*n);
- std::advance(r, n);
- return r;
- }
- template
- <typename I, // I models InputIterator
- typename F> // F models ForwardIterator
- F memcpy_n(I f, typename std::iterator_traits<I>::difference_type n, F r) BOOST_CONTAINER_NOEXCEPT
- {
- typedef typename std::iterator_traits<I>::value_type value_type;
- ::memcpy(container_detail::addressof(*r), container_detail::addressof(*f), sizeof(value_type)*n);
- std::advance(r, n);
- return r;
- }
- template
- <typename I, // I models InputIterator
- typename F> // F models ForwardIterator
- I memcpy_n_source(I f, typename std::iterator_traits<I>::difference_type n, F r) BOOST_CONTAINER_NOEXCEPT
- {
- typedef typename std::iterator_traits<I>::value_type value_type;
- ::memcpy(container_detail::addressof(*r), container_detail::addressof(*f), sizeof(value_type)*n);
- std::advance(f, n);
- return f;
- }
- template
- <typename I, // I models InputIterator
- typename F> // F models ForwardIterator
- I memcpy_n_source_dest(I f, typename std::iterator_traits<I>::difference_type n, F &r) BOOST_CONTAINER_NOEXCEPT
- {
- typedef typename std::iterator_traits<I>::value_type value_type;
- ::memcpy(container_detail::addressof(*r), container_detail::addressof(*f), sizeof(value_type)*n);
- std::advance(f, n);
- std::advance(r, n);
- return f;
- }
- } //namespace container_detail {
- //////////////////////////////////////////////////////////////////////////////
- //
- // uninitialized_move_alloc
- //
- //////////////////////////////////////////////////////////////////////////////
- //! <b>Effects</b>:
- //! \code
- //! for (; f != l; ++r, ++f)
- //! allocator_traits::construct(a, &*r, boost::move(*f));
- //! \endcode
- //!
- //! <b>Returns</b>: r
- template
- <typename A,
- typename I, // I models InputIterator
- typename F> // F models ForwardIterator
- inline typename container_detail::disable_if_memcpy_copy_constructible<I, F, F>::type
- uninitialized_move_alloc(A &a, I f, I l, F r)
- {
- F back = r;
- BOOST_TRY{
- while (f != l) {
- allocator_traits<A>::construct(a, container_detail::to_raw_pointer(&*r), boost::move(*f));
- ++f; ++r;
- }
- }
- BOOST_CATCH(...){
- for (; back != r; ++back){
- allocator_traits<A>::destroy(a, container_detail::to_raw_pointer(&*back));
- }
- BOOST_RETHROW;
- }
- BOOST_CATCH_END
- return r;
- }
- template
- <typename A,
- typename I, // I models InputIterator
- typename F> // F models ForwardIterator
- inline typename container_detail::enable_if_memcpy_copy_constructible<I, F, F>::type
- uninitialized_move_alloc(A &, I f, I l, F r) BOOST_CONTAINER_NOEXCEPT
- { return container_detail::memcpy(f, l, r); }
- //////////////////////////////////////////////////////////////////////////////
- //
- // uninitialized_move_alloc_n
- //
- //////////////////////////////////////////////////////////////////////////////
- //! <b>Effects</b>:
- //! \code
- //! for (; n--; ++r, ++f)
- //! allocator_traits::construct(a, &*r, boost::move(*f));
- //! \endcode
- //!
- //! <b>Returns</b>: r
- template
- <typename A,
- typename I, // I models InputIterator
- typename F> // F models ForwardIterator
- inline typename container_detail::disable_if_memcpy_copy_constructible<I, F, F>::type
- uninitialized_move_alloc_n(A &a, I f, typename std::iterator_traits<I>::difference_type n, F r)
- {
- F back = r;
- BOOST_TRY{
- while (n--) {
- allocator_traits<A>::construct(a, container_detail::to_raw_pointer(&*r), boost::move(*f));
- ++f; ++r;
- }
- }
- BOOST_CATCH(...){
- for (; back != r; ++back){
- allocator_traits<A>::destroy(a, container_detail::to_raw_pointer(&*back));
- }
- BOOST_RETHROW;
- }
- BOOST_CATCH_END
- return r;
- }
- template
- <typename A,
- typename I, // I models InputIterator
- typename F> // F models ForwardIterator
- inline typename container_detail::enable_if_memcpy_copy_constructible<I, F, F>::type
- uninitialized_move_alloc_n(A &, I f, typename std::iterator_traits<I>::difference_type n, F r) BOOST_CONTAINER_NOEXCEPT
- { return container_detail::memcpy_n(f, n, r); }
- //////////////////////////////////////////////////////////////////////////////
- //
- // uninitialized_move_alloc_n_source
- //
- //////////////////////////////////////////////////////////////////////////////
- //! <b>Effects</b>:
- //! \code
- //! for (; n--; ++r, ++f)
- //! allocator_traits::construct(a, &*r, boost::move(*f));
- //! \endcode
- //!
- //! <b>Returns</b>: f (after incremented)
- template
- <typename A,
- typename I, // I models InputIterator
- typename F> // F models ForwardIterator
- inline typename container_detail::disable_if_memcpy_copy_constructible<I, F, I>::type
- uninitialized_move_alloc_n_source(A &a, I f, typename std::iterator_traits<I>::difference_type n, F r)
- {
- F back = r;
- BOOST_TRY{
- while (n--) {
- allocator_traits<A>::construct(a, container_detail::to_raw_pointer(&*r), boost::move(*f));
- ++f; ++r;
- }
- }
- BOOST_CATCH(...){
- for (; back != r; ++back){
- allocator_traits<A>::destroy(a, container_detail::to_raw_pointer(&*back));
- }
- BOOST_RETHROW;
- }
- BOOST_CATCH_END
- return f;
- }
- template
- <typename A,
- typename I, // I models InputIterator
- typename F> // F models ForwardIterator
- inline typename container_detail::enable_if_memcpy_copy_constructible<I, F, I>::type
- uninitialized_move_alloc_n_source(A &, I f, typename std::iterator_traits<I>::difference_type n, F r) BOOST_CONTAINER_NOEXCEPT
- { return container_detail::memcpy_n_source(f, n, r); }
- //////////////////////////////////////////////////////////////////////////////
- //
- // uninitialized_copy_alloc
- //
- //////////////////////////////////////////////////////////////////////////////
- //! <b>Effects</b>:
- //! \code
- //! for (; f != l; ++r, ++f)
- //! allocator_traits::construct(a, &*r, *f);
- //! \endcode
- //!
- //! <b>Returns</b>: r
- template
- <typename A,
- typename I, // I models InputIterator
- typename F> // F models ForwardIterator
- inline typename container_detail::disable_if_memcpy_copy_constructible<I, F, F>::type
- uninitialized_copy_alloc(A &a, I f, I l, F r)
- {
- F back = r;
- BOOST_TRY{
- while (f != l) {
- allocator_traits<A>::construct(a, container_detail::to_raw_pointer(&*r), *f);
- ++f; ++r;
- }
- }
- BOOST_CATCH(...){
- for (; back != r; ++back){
- allocator_traits<A>::destroy(a, container_detail::to_raw_pointer(&*back));
- }
- BOOST_RETHROW;
- }
- BOOST_CATCH_END
- return r;
- }
- template
- <typename A,
- typename I, // I models InputIterator
- typename F> // F models ForwardIterator
- inline typename container_detail::enable_if_memcpy_copy_constructible<I, F, F>::type
- uninitialized_copy_alloc(A &, I f, I l, F r) BOOST_CONTAINER_NOEXCEPT
- { return container_detail::memcpy(f, l, r); }
- //////////////////////////////////////////////////////////////////////////////
- //
- // uninitialized_copy_alloc_n
- //
- //////////////////////////////////////////////////////////////////////////////
- //! <b>Effects</b>:
- //! \code
- //! for (; n--; ++r, ++f)
- //! allocator_traits::construct(a, &*r, *f);
- //! \endcode
- //!
- //! <b>Returns</b>: r
- template
- <typename A,
- typename I, // I models InputIterator
- typename F> // F models ForwardIterator
- inline typename container_detail::disable_if_memcpy_copy_constructible<I, F, F>::type
- uninitialized_copy_alloc_n(A &a, I f, typename std::iterator_traits<I>::difference_type n, F r)
- {
- F back = r;
- BOOST_TRY{
- while (n--) {
- allocator_traits<A>::construct(a, container_detail::to_raw_pointer(&*r), *f);
- ++f; ++r;
- }
- }
- BOOST_CATCH(...){
- for (; back != r; ++back){
- allocator_traits<A>::destroy(a, container_detail::to_raw_pointer(&*back));
- }
- BOOST_RETHROW;
- }
- BOOST_CATCH_END
- return r;
- }
- template
- <typename A,
- typename I, // I models InputIterator
- typename F> // F models ForwardIterator
- inline typename container_detail::enable_if_memcpy_copy_constructible<I, F, F>::type
- uninitialized_copy_alloc_n(A &, I f, typename std::iterator_traits<I>::difference_type n, F r) BOOST_CONTAINER_NOEXCEPT
- { return container_detail::memcpy_n(f, n, r); }
- //////////////////////////////////////////////////////////////////////////////
- //
- // uninitialized_copy_alloc_n_source
- //
- //////////////////////////////////////////////////////////////////////////////
- //! <b>Effects</b>:
- //! \code
- //! for (; n--; ++r, ++f)
- //! allocator_traits::construct(a, &*r, *f);
- //! \endcode
- //!
- //! <b>Returns</b>: f (after incremented)
- template
- <typename A,
- typename I, // I models InputIterator
- typename F> // F models ForwardIterator
- inline typename container_detail::disable_if_memcpy_copy_constructible<I, F, I>::type
- uninitialized_copy_alloc_n_source(A &a, I f, typename std::iterator_traits<I>::difference_type n, F r)
- {
- F back = r;
- BOOST_TRY{
- while (n--) {
- allocator_traits<A>::construct(a, container_detail::to_raw_pointer(&*r), *f);
- ++f; ++r;
- }
- }
- BOOST_CATCH(...){
- for (; back != r; ++back){
- allocator_traits<A>::destroy(a, container_detail::to_raw_pointer(&*back));
- }
- BOOST_RETHROW;
- }
- BOOST_CATCH_END
- return f;
- }
- template
- <typename A,
- typename I, // I models InputIterator
- typename F> // F models ForwardIterator
- inline typename container_detail::enable_if_memcpy_copy_constructible<I, F, I>::type
- uninitialized_copy_alloc_n_source(A &, I f, typename std::iterator_traits<I>::difference_type n, F r) BOOST_CONTAINER_NOEXCEPT
- { return container_detail::memcpy_n_source(f, n, r); }
- //////////////////////////////////////////////////////////////////////////////
- //
- // uninitialized_value_init_alloc_n
- //
- //////////////////////////////////////////////////////////////////////////////
- //! <b>Effects</b>:
- //! \code
- //! for (; n--; ++r, ++f)
- //! allocator_traits::construct(a, &*r);
- //! \endcode
- //!
- //! <b>Returns</b>: r
- template
- <typename A,
- typename F> // F models ForwardIterator
- inline F uninitialized_value_init_alloc_n(A &a, typename allocator_traits<A>::difference_type n, F r)
- {
- F back = r;
- BOOST_TRY{
- while (n--) {
- allocator_traits<A>::construct(a, container_detail::to_raw_pointer(&*r));
- ++r;
- }
- }
- BOOST_CATCH(...){
- for (; back != r; ++back){
- allocator_traits<A>::destroy(a, container_detail::to_raw_pointer(&*back));
- }
- BOOST_RETHROW;
- }
- BOOST_CATCH_END
- return r;
- }
- //////////////////////////////////////////////////////////////////////////////
- //
- // uninitialized_default_init_alloc_n
- //
- //////////////////////////////////////////////////////////////////////////////
- //! <b>Effects</b>:
- //! \code
- //! for (; n--; ++r, ++f)
- //! allocator_traits::construct(a, &*r);
- //! \endcode
- //!
- //! <b>Returns</b>: r
- template
- <typename A,
- typename F> // F models ForwardIterator
- inline F uninitialized_default_init_alloc_n(A &a, typename allocator_traits<A>::difference_type n, F r)
- {
- F back = r;
- BOOST_TRY{
- while (n--) {
- allocator_traits<A>::construct(a, container_detail::to_raw_pointer(&*r), default_init);
- ++r;
- }
- }
- BOOST_CATCH(...){
- for (; back != r; ++back){
- allocator_traits<A>::destroy(a, container_detail::to_raw_pointer(&*back));
- }
- BOOST_RETHROW;
- }
- BOOST_CATCH_END
- return r;
- }
- //////////////////////////////////////////////////////////////////////////////
- //
- // uninitialized_fill_alloc
- //
- //////////////////////////////////////////////////////////////////////////////
- //! <b>Effects</b>:
- //! \code
- //! for (; f != l; ++r, ++f)
- //! allocator_traits::construct(a, &*r, *f);
- //! \endcode
- //!
- //! <b>Returns</b>: r
- template
- <typename A,
- typename F, // F models ForwardIterator
- typename T>
- inline void uninitialized_fill_alloc(A &a, F f, F l, const T &t)
- {
- F back = f;
- BOOST_TRY{
- while (f != l) {
- allocator_traits<A>::construct(a, container_detail::to_raw_pointer(&*f), t);
- ++f;
- }
- }
- BOOST_CATCH(...){
- for (; back != l; ++back){
- allocator_traits<A>::destroy(a, container_detail::to_raw_pointer(&*back));
- }
- BOOST_RETHROW;
- }
- BOOST_CATCH_END
- }
- //////////////////////////////////////////////////////////////////////////////
- //
- // uninitialized_fill_alloc_n
- //
- //////////////////////////////////////////////////////////////////////////////
- //! <b>Effects</b>:
- //! \code
- //! for (; n--; ++r, ++f)
- //! allocator_traits::construct(a, &*r, v);
- //! \endcode
- //!
- //! <b>Returns</b>: r
- template
- <typename A,
- typename T,
- typename F> // F models ForwardIterator
- inline F uninitialized_fill_alloc_n(A &a, const T &v, typename allocator_traits<A>::difference_type n, F r)
- {
- F back = r;
- BOOST_TRY{
- while (n--) {
- allocator_traits<A>::construct(a, container_detail::to_raw_pointer(&*r), v);
- ++r;
- }
- }
- BOOST_CATCH(...){
- for (; back != r; ++back){
- allocator_traits<A>::destroy(a, container_detail::to_raw_pointer(&*back));
- }
- BOOST_RETHROW;
- }
- BOOST_CATCH_END
- return r;
- }
- //////////////////////////////////////////////////////////////////////////////
- //
- // copy
- //
- //////////////////////////////////////////////////////////////////////////////
- template
- <typename I, // I models InputIterator
- typename F> // F models ForwardIterator
- inline typename container_detail::disable_if_memcpy_copy_assignable<I, F, F>::type
- copy(I f, I l, F r)
- {
- while (f != l) {
- *r = *f;
- ++f; ++r;
- }
- return r;
- }
- template
- <typename I, // I models InputIterator
- typename F> // F models ForwardIterator
- inline typename container_detail::enable_if_memcpy_copy_assignable<I, F, F>::type
- copy(I f, I l, F r) BOOST_CONTAINER_NOEXCEPT
- { return container_detail::memcpy(f, l, r); }
- //////////////////////////////////////////////////////////////////////////////
- //
- // copy_n
- //
- //////////////////////////////////////////////////////////////////////////////
- template
- <typename I, // I models InputIterator
- typename F> // F models ForwardIterator
- inline typename container_detail::disable_if_memcpy_copy_assignable<I, F, F>::type
- copy_n(I f, typename std::iterator_traits<I>::difference_type n, F r)
- {
- while (n--) {
- *r = *f;
- ++f; ++r;
- }
- return r;
- }
- template
- <typename I, // I models InputIterator
- typename F> // F models ForwardIterator
- inline typename container_detail::enable_if_memcpy_copy_assignable<I, F, F>::type
- copy_n(I f, typename std::iterator_traits<I>::difference_type n, F r) BOOST_CONTAINER_NOEXCEPT
- { return container_detail::memcpy_n(f, n, r); }
- //////////////////////////////////////////////////////////////////////////////
- //
- // copy_n_source
- //
- //////////////////////////////////////////////////////////////////////////////
- template
- <typename I, // I models InputIterator
- typename F> // F models ForwardIterator
- inline typename container_detail::disable_if_memcpy_copy_assignable<I, F, I>::type
- copy_n_source(I f, typename std::iterator_traits<I>::difference_type n, F r)
- {
- while (n--) {
- *r = *f;
- ++f; ++r;
- }
- return f;
- }
- template
- <typename I, // I models InputIterator
- typename F> // F models ForwardIterator
- inline typename container_detail::enable_if_memcpy_copy_assignable<I, F, I>::type
- copy_n_source(I f, typename std::iterator_traits<I>::difference_type n, F r) BOOST_CONTAINER_NOEXCEPT
- { return container_detail::memcpy_n_source(f, n, r); }
- //////////////////////////////////////////////////////////////////////////////
- //
- // copy_n_source_dest
- //
- //////////////////////////////////////////////////////////////////////////////
- template
- <typename I, // I models InputIterator
- typename F> // F models ForwardIterator
- inline typename container_detail::disable_if_memcpy_copy_assignable<I, F, I>::type
- copy_n_source_dest(I f, typename std::iterator_traits<I>::difference_type n, F &r)
- {
- while (n--) {
- *r = *f;
- ++f; ++r;
- }
- return f;
- }
- template
- <typename I, // I models InputIterator
- typename F> // F models ForwardIterator
- inline typename container_detail::enable_if_memcpy_copy_assignable<I, F, I>::type
- copy_n_source_dest(I f, typename std::iterator_traits<I>::difference_type n, F &r) BOOST_CONTAINER_NOEXCEPT
- { return container_detail::memcpy_n_source_dest(f, n, r); }
- //////////////////////////////////////////////////////////////////////////////
- //
- // move
- //
- //////////////////////////////////////////////////////////////////////////////
- template
- <typename I, // I models InputIterator
- typename F> // F models ForwardIterator
- inline typename container_detail::disable_if_memcpy_copy_assignable<I, F, F>::type
- move(I f, I l, F r)
- {
- while (f != l) {
- *r = ::boost::move(*f);
- ++f; ++r;
- }
- return r;
- }
- template
- <typename I, // I models InputIterator
- typename F> // F models ForwardIterator
- inline typename container_detail::enable_if_memcpy_copy_assignable<I, F, F>::type
- move(I f, I l, F r) BOOST_CONTAINER_NOEXCEPT
- { return container_detail::memcpy(f, l, r); }
- //////////////////////////////////////////////////////////////////////////////
- //
- // move_n
- //
- //////////////////////////////////////////////////////////////////////////////
- template
- <typename I, // I models InputIterator
- typename F> // F models ForwardIterator
- inline typename container_detail::disable_if_memcpy_copy_assignable<I, F, F>::type
- move_n(I f, typename std::iterator_traits<I>::difference_type n, F r)
- {
- while (n--) {
- *r = ::boost::move(*f);
- ++f; ++r;
- }
- return r;
- }
- template
- <typename I, // I models InputIterator
- typename F> // F models ForwardIterator
- inline typename container_detail::enable_if_memcpy_copy_assignable<I, F, F>::type
- move_n(I f, typename std::iterator_traits<I>::difference_type n, F r) BOOST_CONTAINER_NOEXCEPT
- { return container_detail::memcpy_n(f, n, r); }
- //////////////////////////////////////////////////////////////////////////////
- //
- // move_n_source
- //
- //////////////////////////////////////////////////////////////////////////////
- template
- <typename I // I models InputIterator
- ,typename F> // F models ForwardIterator
- inline typename container_detail::disable_if_memcpy_copy_assignable<I, F, I>::type
- move_n_source(I f, typename std::iterator_traits<I>::difference_type n, F r)
- {
- while (n--) {
- *r = ::boost::move(*f);
- ++f; ++r;
- }
- return f;
- }
- template
- <typename I // I models InputIterator
- ,typename F> // F models ForwardIterator
- inline typename container_detail::enable_if_memcpy_copy_assignable<I, F, I>::type
- move_n_source(I f, typename std::iterator_traits<I>::difference_type n, F r) BOOST_CONTAINER_NOEXCEPT
- { return container_detail::memcpy_n_source(f, n, r); }
- //////////////////////////////////////////////////////////////////////////////
- //
- // move_n_source_dest
- //
- //////////////////////////////////////////////////////////////////////////////
- template
- <typename I // I models InputIterator
- ,typename F> // F models ForwardIterator
- inline typename container_detail::disable_if_memcpy_copy_assignable<I, F, I>::type
- move_n_source_dest(I f, typename std::iterator_traits<I>::difference_type n, F &r)
- {
- while (n--) {
- *r = ::boost::move(*f);
- ++f; ++r;
- }
- return f;
- }
- template
- <typename I // I models InputIterator
- ,typename F> // F models ForwardIterator
- inline typename container_detail::enable_if_memcpy_copy_assignable<I, F, I>::type
- move_n_source_dest(I f, typename std::iterator_traits<I>::difference_type n, F &r) BOOST_CONTAINER_NOEXCEPT
- { return container_detail::memcpy_n_source_dest(f, n, r); }
- //////////////////////////////////////////////////////////////////////////////
- //
- // destroy_n
- //
- //////////////////////////////////////////////////////////////////////////////
- template
- <typename A
- ,typename I> // I models InputIterator
- inline void destroy_alloc_n(A &a, I f, typename std::iterator_traits<I>::difference_type n
- ,typename boost::container::container_detail::enable_if_c
- < !boost::has_trivial_destructor<typename std::iterator_traits<I>::value_type>::value >::type* = 0)
- {
- while(n--){
- allocator_traits<A>::destroy(a, container_detail::addressof(*f++));
- }
- }
- template
- <typename A
- ,typename I> // I models InputIterator
- inline void destroy_alloc_n(A &, I, typename std::iterator_traits<I>::difference_type
- ,typename boost::container::container_detail::enable_if_c
- < boost::has_trivial_destructor<typename std::iterator_traits<I>::value_type>::value >::type* = 0)
- {}
- //////////////////////////////////////////////////////////////////////////////
- //
- // deep_swap_alloc_n
- //
- //////////////////////////////////////////////////////////////////////////////
- template
- <std::size_t MaxTmpBytes
- ,typename A
- ,typename F // F models ForwardIterator
- ,typename G // G models ForwardIterator
- >
- inline typename container_detail::disable_if_memcpy_copy_assignable<F, G, void>::type
- deep_swap_alloc_n( A &a, F short_range_f, typename allocator_traits<A>::size_type n_i
- , G large_range_f, typename allocator_traits<A>::size_type n_j)
- {
- typename allocator_traits<A>::size_type n = 0;
- for (; n != n_i ; ++short_range_f, ++large_range_f, ++n){
- boost::container::swap_dispatch(*short_range_f, *large_range_f);
- }
- boost::container::uninitialized_move_alloc_n(a, large_range_f, n_j - n_i, short_range_f); // may throw
- boost::container::destroy_alloc_n(a, large_range_f, n_j - n_i);
- }
- static const std::size_t DeepSwapAllocNMaxStorage = std::size_t(1) << std::size_t(11); //2K bytes
- template
- <std::size_t MaxTmpBytes
- ,typename A
- ,typename F // F models ForwardIterator
- ,typename G // G models ForwardIterator
- >
- inline typename container_detail::enable_if_c
- < container_detail::is_memcpy_copy_assignable<F, G>::value && (MaxTmpBytes <= DeepSwapAllocNMaxStorage) && false
- , void>::type
- deep_swap_alloc_n( A &a, F short_range_f, typename allocator_traits<A>::size_type n_i
- , G large_range_f, typename allocator_traits<A>::size_type n_j)
- {
- typedef typename allocator_traits<A>::value_type value_type;
- typedef typename boost::aligned_storage
- <MaxTmpBytes, container_detail::alignment_of<value_type>::value>::type storage_type;
- storage_type storage;
- const std::size_t n_i_bytes = sizeof(value_type)*n_i;
- unsigned char *const large_ptr = static_cast<unsigned char*>(static_cast<void*>(container_detail::addressof(*large_range_f)));
- unsigned char *const short_ptr = static_cast<unsigned char*>(static_cast<void*>(container_detail::addressof(*short_range_f)));
- unsigned char *const stora_ptr = static_cast<unsigned char*>(static_cast<void*>(container_detail::addressof(storage)));
- ::memcpy(stora_ptr, large_ptr, n_i_bytes);
- ::memcpy(large_ptr, short_ptr, n_i_bytes);
- ::memcpy(short_ptr, stora_ptr, n_i_bytes);
- std::advance(large_range_f, n_i);
- std::advance(short_range_f, n_i);
- boost::container::uninitialized_move_alloc_n(a, large_range_f, n_j - n_i, short_range_f); // may throw
- boost::container::destroy_alloc_n(a, large_range_f, n_j - n_i);
- }
- template
- <std::size_t MaxTmpBytes
- ,typename A
- ,typename F // F models ForwardIterator
- ,typename G // G models ForwardIterator
- >
- inline typename container_detail::enable_if_c
- < container_detail::is_memcpy_copy_assignable<F, G>::value && true//(MaxTmpBytes > DeepSwapAllocNMaxStorage)
- , void>::type
- deep_swap_alloc_n( A &a, F short_range_f, typename allocator_traits<A>::size_type n_i
- , G large_range_f, typename allocator_traits<A>::size_type n_j)
- {
- typedef typename allocator_traits<A>::value_type value_type;
- typedef typename boost::aligned_storage
- <DeepSwapAllocNMaxStorage, container_detail::alignment_of<value_type>::value>::type storage_type;
- storage_type storage;
- const std::size_t sizeof_storage = sizeof(storage);
- std::size_t n_i_bytes = sizeof(value_type)*n_i;
- char *large_ptr = static_cast<char*>(static_cast<void*>(container_detail::addressof(*large_range_f)));
- char *short_ptr = static_cast<char*>(static_cast<void*>(container_detail::addressof(*short_range_f)));
- char *stora_ptr = static_cast<char*>(static_cast<void*>(container_detail::addressof(storage)));
- std::size_t szt_times = n_i_bytes/sizeof_storage;
- const std::size_t szt_rem = n_i_bytes%sizeof_storage;
- //Loop unrolling using Duff's device, as it seems it helps on some architectures
- const std::size_t Unroll = 4;
- std::size_t n = (szt_times + (Unroll-1))/Unroll;
- const std::size_t branch_number = ((!szt_times)*Unroll) + (szt_times % Unroll);
- switch(branch_number){
- case 4:
- break;
- case 0: do{
- ::memcpy(stora_ptr, large_ptr, sizeof_storage);
- ::memcpy(large_ptr, short_ptr, sizeof_storage);
- ::memcpy(short_ptr, stora_ptr, sizeof_storage);
- large_ptr += sizeof_storage;
- short_ptr += sizeof_storage;
- BOOST_CONTAINER_FALLTHOUGH
- case 3:
- ::memcpy(stora_ptr, large_ptr, sizeof_storage);
- ::memcpy(large_ptr, short_ptr, sizeof_storage);
- ::memcpy(short_ptr, stora_ptr, sizeof_storage);
- large_ptr += sizeof_storage;
- short_ptr += sizeof_storage;
- BOOST_CONTAINER_FALLTHOUGH
- case 2:
- ::memcpy(stora_ptr, large_ptr, sizeof_storage);
- ::memcpy(large_ptr, short_ptr, sizeof_storage);
- ::memcpy(short_ptr, stora_ptr, sizeof_storage);
- large_ptr += sizeof_storage;
- short_ptr += sizeof_storage;
- BOOST_CONTAINER_FALLTHOUGH
- case 1:
- ::memcpy(stora_ptr, large_ptr, sizeof_storage);
- ::memcpy(large_ptr, short_ptr, sizeof_storage);
- ::memcpy(short_ptr, stora_ptr, sizeof_storage);
- large_ptr += sizeof_storage;
- short_ptr += sizeof_storage;
- } while(--n);
- }
- ::memcpy(stora_ptr, large_ptr, szt_rem);
- ::memcpy(large_ptr, short_ptr, szt_rem);
- ::memcpy(short_ptr, stora_ptr, szt_rem);
- std::advance(large_range_f, n_i);
- std::advance(short_range_f, n_i);
- boost::container::uninitialized_move_alloc_n(a, large_range_f, n_j - n_i, short_range_f); // may throw
- boost::container::destroy_alloc_n(a, large_range_f, n_j - n_i);
- }
- //////////////////////////////////////////////////////////////////////////////
- //
- // copy_assign_range_alloc_n
- //
- //////////////////////////////////////////////////////////////////////////////
- template
- <typename A
- ,typename I // F models InputIterator
- ,typename O // G models OutputIterator
- >
- void copy_assign_range_alloc_n( A &a, I inp_start, typename allocator_traits<A>::size_type n_i
- , O out_start, typename allocator_traits<A>::size_type n_o )
- {
- if (n_o < n_i){
- inp_start = boost::container::copy_n_source_dest(inp_start, n_o, out_start); // may throw
- boost::container::uninitialized_copy_alloc_n(a, inp_start, n_i - n_o, out_start);// may throw
- }
- else{
- out_start = boost::container::copy_n(inp_start, n_i, out_start); // may throw
- boost::container::destroy_alloc_n(a, out_start, n_o - n_i);
- }
- }
- //////////////////////////////////////////////////////////////////////////////
- //
- // move_assign_range_alloc_n
- //
- //////////////////////////////////////////////////////////////////////////////
- template
- <typename A
- ,typename I // F models InputIterator
- ,typename O // G models OutputIterator
- >
- void move_assign_range_alloc_n( A &a, I inp_start, typename allocator_traits<A>::size_type n_i
- , O out_start, typename allocator_traits<A>::size_type n_o )
- {
- if (n_o < n_i){
- inp_start = boost::container::move_n_source_dest(inp_start, n_o, out_start); // may throw
- boost::container::uninitialized_move_alloc_n(a, inp_start, n_i - n_o, out_start); // may throw
- }
- else{
- out_start = boost::container::move_n(inp_start, n_i, out_start); // may throw
- boost::container::destroy_alloc_n(a, out_start, n_o - n_i);
- }
- }
- } //namespace container {
- } //namespace boost {
- #include <boost/container/detail/config_end.hpp>
- #endif //#ifndef BOOST_CONTAINER_DETAIL_UTILITIES_HPP
|