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