////////////////////////////////////////////////////////////////////////////// // // (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/interprocess for documentation. // ////////////////////////////////////////////////////////////////////////////// #ifndef BOOST_INTERPROCESS_NAMED_PROXY_HPP #define BOOST_INTERPROCESS_NAMED_PROXY_HPP #if (defined _MSC_VER) && (_MSC_VER >= 1200) # pragma once #endif #include #include #include #include #include #include #ifndef BOOST_INTERPROCESS_PERFECT_FORWARDING #include #else #include #include #endif //#ifdef BOOST_INTERPROCESS_PERFECT_FORWARDING //!\file //!Describes a proxy class that implements named allocation syntax. namespace boost { namespace interprocess { namespace ipcdetail { #ifdef BOOST_INTERPROCESS_PERFECT_FORWARDING template struct CtorNArg : public placement_destroy { typedef bool_ IsIterator; typedef CtorNArg self_t; typedef typename build_number_seq::type index_tuple_t; self_t& operator++() { this->do_increment(IsIterator(), index_tuple_t()); return *this; } self_t operator++(int) { return ++*this; *this; } CtorNArg(Args && ...args) : args_(args...) {} virtual void construct_n(void *mem , std::size_t num , std::size_t &constructed) { T* memory = static_cast(mem); for(constructed = 0; constructed < num; ++constructed){ this->construct(memory++, IsIterator(), index_tuple_t()); this->do_increment(IsIterator(), index_tuple_t()); } } private: template void construct(void *mem, true_, const index_tuple&) { new((void*)mem)T(*boost::forward(get(args_))...); } template void construct(void *mem, false_, const index_tuple&) { new((void*)mem)T(boost::forward(get(args_))...); } template void do_increment(true_, const index_tuple&) { this->expansion_helper(++get(args_)...); } template void expansion_helper(ExpansionArgs &&...) {} template void do_increment(false_, const index_tuple&) {} tuple args_; }; //!Describes a proxy class that implements named //!allocation syntax. template < class SegmentManager //segment manager to construct the object , class T //type of object to build , bool is_iterator //passing parameters are normal object or iterators? > class named_proxy { typedef typename SegmentManager::char_type char_type; const char_type * mp_name; SegmentManager * mp_mngr; mutable std::size_t m_num; const bool m_find; const bool m_dothrow; public: named_proxy(SegmentManager *mngr, const char_type *name, bool find, bool dothrow) : mp_name(name), mp_mngr(mngr), m_num(1) , m_find(find), m_dothrow(dothrow) {} template T *operator()(Args &&...args) const { CtorNArg &&ctor_obj = CtorNArg (boost::forward(args)...); return mp_mngr->template generic_construct(mp_name, m_num, m_find, m_dothrow, ctor_obj); } //This operator allows --> named_new("Name")[3]; <-- syntax const named_proxy &operator[](std::size_t num) const { m_num *= num; return *this; } }; #else //#ifdef BOOST_INTERPROCESS_PERFECT_FORWARDING //!Function object that makes placement new //!without arguments template struct Ctor0Arg : public placement_destroy { typedef Ctor0Arg self_t; Ctor0Arg(){} self_t& operator++() { return *this; } self_t operator++(int) { return *this; } void construct(void *mem) { new((void*)mem)T; } virtual void construct_n(void *mem, std::size_t num, std::size_t &constructed) { T* memory = static_cast(mem); for(constructed = 0; constructed < num; ++constructed) new((void*)memory++)T; } }; //////////////////////////////////////////////////////////////// // What the macro should generate (n == 2): // // template // struct Ctor2Arg // : public placement_destroy // { // typedef bool_ IsIterator; // typedef Ctor2Arg self_t; // // void do_increment(false_) // { ++m_p1; ++m_p2; } // // void do_increment(true_){} // // self_t& operator++() // { // this->do_increment(IsIterator()); // return *this; // } // // self_t operator++(int) { return ++*this; *this; } // // Ctor2Arg(const P1 &p1, const P2 &p2) // : p1((P1 &)p_1), p2((P2 &)p_2) {} // // void construct(void *mem) // { new((void*)object)T(m_p1, m_p2); } // // virtual void construct_n(void *mem // , std::size_t num // , std::size_t &constructed) // { // T* memory = static_cast(mem); // for(constructed = 0; constructed < num; ++constructed){ // this->construct(memory++, IsIterator()); // this->do_increment(IsIterator()); // } // } // // private: // void construct(void *mem, true_) // { new((void*)mem)T(*m_p1, *m_p2); } // // void construct(void *mem, false_) // { new((void*)mem)T(m_p1, m_p2); } // // P1 &m_p1; P2 &m_p2; // }; //////////////////////////////////////////////////////////////// //Note: //We define template parameters as const references to //be able to bind temporaries. After that we will un-const them. //This cast is ugly but it is necessary until "perfect forwarding" //is achieved in C++0x. Meanwhile, if we want to be able to //bind lvalues with non-const references, we have to be ugly #define BOOST_PP_LOCAL_MACRO(n) \ template \ struct BOOST_PP_CAT(BOOST_PP_CAT(Ctor, n), Arg) \ : public placement_destroy \ { \ typedef bool_ IsIterator; \ typedef BOOST_PP_CAT(BOOST_PP_CAT(Ctor, n), Arg) self_t; \ \ void do_increment(true_) \ { BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_PARAM_INC, _); } \ \ void do_increment(false_){} \ \ self_t& operator++() \ { \ this->do_increment(IsIterator()); \ return *this; \ } \ \ self_t operator++(int) { return ++*this; *this; } \ \ BOOST_PP_CAT(BOOST_PP_CAT(Ctor, n), Arg) \ ( BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_PARAM_LIST, _) ) \ : BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_PARAM_INIT, _) {} \ \ virtual void construct_n(void *mem \ , std::size_t num \ , std::size_t &constructed) \ { \ T* memory = static_cast(mem); \ for(constructed = 0; constructed < num; ++constructed){ \ this->construct(memory++, IsIterator()); \ this->do_increment(IsIterator()); \ } \ } \ \ private: \ void construct(void *mem, true_) \ { \ new((void*)mem) T \ (BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_MEMBER_IT_FORWARD, _)); \ } \ \ void construct(void *mem, false_) \ { \ new((void*)mem) T \ (BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_MEMBER_FORWARD, _)); \ } \ \ BOOST_PP_REPEAT(n, BOOST_INTERPROCESS_PP_PARAM_DEFINE, _) \ }; \ //! #define BOOST_PP_LOCAL_LIMITS (1, BOOST_INTERPROCESS_MAX_CONSTRUCTOR_PARAMETERS) #include BOOST_PP_LOCAL_ITERATE() //!Describes a proxy class that implements named //!allocation syntax. template < class SegmentManager //segment manager to construct the object , class T //type of object to build , bool is_iterator //passing parameters are normal object or iterators? > class named_proxy { typedef typename SegmentManager::char_type char_type; const char_type * mp_name; SegmentManager * mp_mngr; mutable std::size_t m_num; const bool m_find; const bool m_dothrow; public: named_proxy(SegmentManager *mngr, const char_type *name, bool find, bool dothrow) : mp_name(name), mp_mngr(mngr), m_num(1) , m_find(find), m_dothrow(dothrow) {} //!makes a named allocation and calls the //!default constructor T *operator()() const { Ctor0Arg ctor_obj; return mp_mngr->template generic_construct(mp_name, m_num, m_find, m_dothrow, ctor_obj); } //! #define BOOST_PP_LOCAL_MACRO(n) \ template \ T *operator()(BOOST_PP_ENUM (n, BOOST_INTERPROCESS_PP_PARAM_LIST, _)) const\ { \ typedef BOOST_PP_CAT(BOOST_PP_CAT(Ctor, n), Arg) \ \ ctor_obj_t; \ ctor_obj_t ctor_obj \ (BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_PARAM_FORWARD, _)); \ return mp_mngr->template generic_construct \ (mp_name, m_num, m_find, m_dothrow, ctor_obj); \ } \ //! #define BOOST_PP_LOCAL_LIMITS ( 1, BOOST_INTERPROCESS_MAX_CONSTRUCTOR_PARAMETERS ) #include BOOST_PP_LOCAL_ITERATE() //////////////////////////////////////////////////////////////////////// // What the macro should generate (n == 2) //////////////////////////////////////////////////////////////////////// // // template // T *operator()(P1 &p1, P2 &p2) const // { // typedef Ctor2Arg // // ctor_obj_t; // ctor_obj_t ctor_obj(p1, p2); // // return mp_mngr->template generic_construct // (mp_name, m_num, m_find, m_dothrow, ctor_obj); // } // ////////////////////////////////////////////////////////////////////////// //This operator allows --> named_new("Name")[3]; <-- syntax const named_proxy &operator[](std::size_t num) const { m_num *= num; return *this; } }; #endif //#ifdef BOOST_INTERPROCESS_PERFECT_FORWARDING }}} //namespace boost { namespace interprocess { namespace ipcdetail { #include #endif //#ifndef BOOST_INTERPROCESS_NAMED_PROXY_HPP