boost/interprocess/detail/advanced_insert_int.hpp
////////////////////////////////////////////////////////////////////////////// // // (C) Copyright Ion Gaztanaga 2008-2008. 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/interprocess for documentation. // ////////////////////////////////////////////////////////////////////////////// #ifndef BOOST_INTERPROCESS_ADVANCED_INSERT_INT_HPP #define BOOST_INTERPROCESS_ADVANCED_INSERT_INT_HPP #if (defined _MSC_VER) && (_MSC_VER >= 1200) # pragma once #endif #include <boost/interprocess/detail/config_begin.hpp> #include <boost/interprocess/detail/workaround.hpp> #include <boost/interprocess/detail/move.hpp> #include <iterator> //std::iterator_traits #include <algorithm> //std::copy, std::uninitialized_copy #include <new> //placement new #include <cassert> namespace boost { namespace interprocess { namespace detail { //This class will be interface for operations dependent on FwdIt types used advanced_insert_aux_impl template<class T, class Iterator> struct advanced_insert_aux_int { typedef typename std::iterator_traits<Iterator>::difference_type difference_type; virtual void copy_all_to(Iterator p) = 0; virtual void uninitialized_copy_all_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<class T, class FwdIt, class Iterator> struct advanced_insert_aux_proxy : public advanced_insert_aux_int<T, Iterator> { typedef typename advanced_insert_aux_int<T, Iterator>::difference_type difference_type; advanced_insert_aux_proxy(FwdIt first, FwdIt last) : first_(first), last_(last) {} virtual ~advanced_insert_aux_proxy() {} virtual void copy_all_to(Iterator p) { *std::copy(first_, last_, p); } virtual void uninitialized_copy_all_to(Iterator p) { std::uninitialized_copy(first_, last_, p); } virtual void uninitialized_copy_some_and_update(Iterator pos, difference_type division_count, bool first_n) { FwdIt mid = first_; std::advance(mid, division_count); if(first_n){ std::uninitialized_copy(first_, mid, pos); first_ = mid; } else{ std::uninitialized_copy(mid, last_, pos); last_ = mid; } } virtual void copy_some_and_update(Iterator pos, difference_type division_count, bool first_n) { FwdIt mid = first_; std::advance(mid, division_count); if(first_n){ std::copy(first_, mid, pos); first_ = mid; } else{ std::copy(mid, last_, pos); last_ = mid; } } FwdIt first_, last_; }; //This class template will adapt each FwIt types to advanced_insert_aux_int template<class T, class Iterator, class SizeType> struct default_construct_aux_proxy : public advanced_insert_aux_int<T, Iterator> { typedef typename advanced_insert_aux_int<T, Iterator>::difference_type difference_type; default_construct_aux_proxy(SizeType count) : count_(count) {} void uninitialized_copy_impl(Iterator p, const SizeType n) { assert(n <= count_); Iterator orig_p = p; SizeType i = 0; try{ for(; i < n; ++i, ++p){ new(detail::get_pointer(&*p))T(); } } catch(...){ while(i--){ detail::get_pointer(&*orig_p++)->~T(); } throw; } count_ -= n; } virtual ~default_construct_aux_proxy() {} virtual void copy_all_to(Iterator) { //This should never be called with any count assert(count_ == 0); } virtual void uninitialized_copy_all_to(Iterator p) { this->uninitialized_copy_impl(p, count_); } virtual void uninitialized_copy_some_and_update(Iterator pos, difference_type division_count, bool first_n) { SizeType new_count; if(first_n){ new_count = division_count; } else{ assert(difference_type(count_)>= division_count); new_count = count_ - division_count; } this->uninitialized_copy_impl(pos, new_count); } virtual void copy_some_and_update(Iterator , difference_type division_count, bool first_n) { assert(count_ == 0); SizeType new_count; if(first_n){ new_count = division_count; } else{ assert(difference_type(count_)>= division_count); new_count = count_ - division_count; } //This function should never called with a count different to zero assert(new_count == 0); (void)new_count; } SizeType count_; }; }}} //namespace boost { namespace interprocess { namespace detail { #ifdef BOOST_INTERPROCESS_PERFECT_FORWARDING #include <boost/interprocess/detail/variadic_templates_tools.hpp> #include <boost/interprocess/detail/move.hpp> #include <typeinfo> //#include <iostream> //For debugging purposes namespace boost { namespace interprocess { namespace detail { //This class template will adapt each FwIt types to advanced_insert_aux_int template<class T, class Iterator, class ...Args> struct advanced_insert_aux_emplace : public advanced_insert_aux_int<T, Iterator> { typedef typename advanced_insert_aux_int<T, Iterator>::difference_type difference_type; typedef typename build_number_seq<sizeof...(Args)>::type index_tuple_t; advanced_insert_aux_emplace(Args&&... args) : args_(args...), used_(false) {} ~advanced_insert_aux_emplace() {} virtual void copy_all_to(Iterator p) { this->priv_copy_all_to(index_tuple_t(), p); } virtual void uninitialized_copy_all_to(Iterator p) { this->priv_uninitialized_copy_all_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 p, difference_type division_count, bool first_n) { this->priv_copy_some_and_update(index_tuple_t(), p, division_count, first_n); } private: template<int ...IdxPack> void priv_copy_all_to(const index_tuple<IdxPack...>&, Iterator p) { if(!used_){ T object(detail::forward_impl<Args>(get<IdxPack>(args_))...); *p = detail::move_impl(object); used_ = true; } } template<int ...IdxPack> void priv_uninitialized_copy_all_to(const index_tuple<IdxPack...>&, Iterator p) { if(!used_){ new(detail::get_pointer(&*p))T(detail::forward_impl<Args>(get<IdxPack>(args_))...); used_ = true; } } template<int ...IdxPack> void priv_uninitialized_copy_some_and_update(const index_tuple<IdxPack...>&, Iterator p, difference_type division_count, bool first_n) { assert(division_count <=1); if((first_n && division_count == 1) || (!first_n && division_count == 0)){ if(!used_){ new(detail::get_pointer(&*p))T(detail::forward_impl<Args>(get<IdxPack>(args_))...); used_ = true; } } } template<int ...IdxPack> void priv_copy_some_and_update(const index_tuple<IdxPack...>&, Iterator p, difference_type division_count, bool first_n) { assert(division_count <=1); if((first_n && division_count == 1) || (!first_n && division_count == 0)){ if(!used_){ T object(detail::forward_impl<Args>(get<IdxPack>(args_))...); *p = detail::move_impl(object); used_ = true; } } } tuple<Args&&...> args_; bool used_; }; }}} //namespace boost { namespace interprocess { namespace detail { #else //#ifdef BOOST_INTERPROCESS_PERFECT_FORWARDING #include <boost/interprocess/detail/preprocessor.hpp> namespace boost { namespace interprocess { namespace detail { template<class T> struct value_init_helper { value_init_helper() : m_t() {} T m_t; }; //This class template will adapt each FwIt types to advanced_insert_aux_int template<class T, class Iterator> struct advanced_insert_aux_emplace : public advanced_insert_aux_int<T, Iterator> { typedef typename advanced_insert_aux_int<T, Iterator>::difference_type difference_type; advanced_insert_aux_emplace() : used_(false) {} ~advanced_insert_aux_emplace() {} virtual void copy_all_to(Iterator p) { if(!used_){ value_init_helper<T>v; *p = detail::move_impl(v.m_t); used_ = true; } } virtual void uninitialized_copy_all_to(Iterator p) { if(!used_){ new(detail::get_pointer(&*p))T(); used_ = true; } } virtual void uninitialized_copy_some_and_update(Iterator p, difference_type division_count, bool first_n) { assert(division_count <=1); if((first_n && division_count == 1) || (!first_n && division_count == 0)){ if(!used_){ new(detail::get_pointer(&*p))T(); used_ = true; } } } virtual void copy_some_and_update(Iterator p, difference_type division_count, bool first_n) { assert(division_count <=1); if((first_n && division_count == 1) || (!first_n && division_count == 0)){ if(!used_){ value_init_helper<T>v; *p = detail::move_impl(v.m_t); used_ = true; } } } private: bool used_; }; #define BOOST_PP_LOCAL_MACRO(n) \ template<class T, class Iterator, BOOST_PP_ENUM_PARAMS(n, class P) > \ struct BOOST_PP_CAT(BOOST_PP_CAT(advanced_insert_aux_emplace, n), arg) \ : public advanced_insert_aux_int<T, Iterator> \ { \ typedef typename advanced_insert_aux_int<T, Iterator>::difference_type difference_type; \ \ BOOST_PP_CAT(BOOST_PP_CAT(advanced_insert_aux_emplace, n), arg) \ ( BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_PARAM_LIST, _) ) \ : used_(false), BOOST_PP_ENUM(n, BOOST_INTERPROCESS_AUX_PARAM_INIT, _) {} \ \ virtual void copy_all_to(Iterator p) \ { \ if(!used_){ \ T v(BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_MEMBER_FORWARD, _)); \ *p = detail::move_impl(v); \ used_ = true; \ } \ } \ \ virtual void uninitialized_copy_all_to(Iterator p) \ { \ if(!used_){ \ new(detail::get_pointer(&*p))T \ (BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_MEMBER_FORWARD, _)); \ used_ = true; \ } \ } \ \ virtual void uninitialized_copy_some_and_update \ (Iterator p, difference_type division_count, bool first_n) \ { \ assert(division_count <=1); \ if((first_n && division_count == 1) || (!first_n && division_count == 0)){ \ if(!used_){ \ new(detail::get_pointer(&*p))T \ (BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_MEMBER_FORWARD, _)); \ used_ = true; \ } \ } \ } \ \ virtual void copy_some_and_update \ (Iterator p, difference_type division_count, bool first_n) \ { \ assert(division_count <=1); \ if((first_n && division_count == 1) || (!first_n && division_count == 0)){ \ if(!used_){ \ T v(BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_MEMBER_FORWARD, _)); \ *p = detail::move_impl(v); \ used_ = true; \ } \ } \ } \ \ bool used_; \ BOOST_PP_REPEAT(n, BOOST_INTERPROCESS_AUX_PARAM_DEFINE, _) \ }; \ //! #define BOOST_PP_LOCAL_LIMITS (1, BOOST_INTERPROCESS_MAX_CONSTRUCTOR_PARAMETERS) #include BOOST_PP_LOCAL_ITERATE() }}} //namespace boost { namespace interprocess { namespace detail { #endif //#ifdef BOOST_INTERPROCESS_PERFECT_FORWARDING #include <boost/interprocess/detail/config_end.hpp> #endif //#ifndef BOOST_INTERPROCESS_ADVANCED_INSERT_INT_HPP