1 //////////////////////////////////////////////////////////////////////////////
2 //
3 // (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
4 // Software License, Version 1.0. (See accompanying file
5 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6 //
7 // See http://www.boost.org/libs/interprocess for documentation.
8 //
9 //////////////////////////////////////////////////////////////////////////////
10 
11 #ifndef BOOST_INTERPROCESS_NAMED_PROXY_HPP
12 #define BOOST_INTERPROCESS_NAMED_PROXY_HPP
13 
14 #ifndef BOOST_CONFIG_HPP
15 #  include <boost/config.hpp>
16 #endif
17 #
18 #if defined(BOOST_HAS_PRAGMA_ONCE)
19 #  pragma once
20 #endif
21 
22 #include <boost/interprocess/detail/config_begin.hpp>
23 #include <boost/interprocess/detail/workaround.hpp>
24 
25 // interprocess/detail
26 #include <boost/interprocess/detail/in_place_interface.hpp>
27 #include <boost/interprocess/detail/mpl.hpp>
28 #include <boost/move/utility_core.hpp>
29 #ifndef BOOST_INTERPROCESS_PERFECT_FORWARDING
30 #include <boost/move/detail/fwd_macros.hpp>
31 #else
32 #include <boost/move/utility_core.hpp>
33 #include <boost/interprocess/detail/variadic_templates_tools.hpp>
34 #endif   //#ifdef BOOST_INTERPROCESS_PERFECT_FORWARDING
35 #include <boost/container/detail/placement_new.hpp>
36 
37 //!\file
38 //!Describes a proxy class that implements named allocation syntax.
39 
40 namespace boost {
41 namespace interprocess {
42 namespace ipcdetail {
43 
44 #ifdef BOOST_INTERPROCESS_PERFECT_FORWARDING
45 
46 template<class T, bool is_iterator, class ...Args>
47 struct CtorArgN : public placement_destroy<T>
48 {
49    typedef bool_<is_iterator> IsIterator;
50    typedef CtorArgN<T, is_iterator, Args...> self_t;
51    typedef typename build_number_seq<sizeof...(Args)>::type index_tuple_t;
52 
operator ++boost::interprocess::ipcdetail::CtorArgN53    self_t& operator++()
54    {
55       this->do_increment(IsIterator(), index_tuple_t());
56       return *this;
57    }
58 
operator ++boost::interprocess::ipcdetail::CtorArgN59    self_t  operator++(int) {  return ++*this;   *this;  }
60 
CtorArgNboost::interprocess::ipcdetail::CtorArgN61    CtorArgN(Args && ...args)
62       :  args_(args...)
63    {}
64 
construct_nboost::interprocess::ipcdetail::CtorArgN65    virtual void construct_n(void *mem
66                      , std::size_t num
67                      , std::size_t &constructed)
68    {
69       T* memory      = static_cast<T*>(mem);
70       for(constructed = 0; constructed < num; ++constructed){
71          this->construct(memory++, IsIterator(), index_tuple_t());
72          this->do_increment(IsIterator(), index_tuple_t());
73       }
74    }
75 
76    private:
77    template<int ...IdxPack>
constructboost::interprocess::ipcdetail::CtorArgN78    void construct(void *mem, true_, const index_tuple<IdxPack...>&)
79    {  ::new((void*)mem, boost_container_new_t())T(*boost::forward<Args>(get<IdxPack>(args_))...); }
80 
81    template<int ...IdxPack>
constructboost::interprocess::ipcdetail::CtorArgN82    void construct(void *mem, false_, const index_tuple<IdxPack...>&)
83    {  ::new((void*)mem, boost_container_new_t())T(boost::forward<Args>(get<IdxPack>(args_))...); }
84 
85    template<int ...IdxPack>
do_incrementboost::interprocess::ipcdetail::CtorArgN86    void do_increment(true_, const index_tuple<IdxPack...>&)
87    {
88       this->expansion_helper(++get<IdxPack>(args_)...);
89    }
90 
91    template<class ...ExpansionArgs>
expansion_helperboost::interprocess::ipcdetail::CtorArgN92    void expansion_helper(ExpansionArgs &&...)
93    {}
94 
95    template<int ...IdxPack>
do_incrementboost::interprocess::ipcdetail::CtorArgN96    void do_increment(false_, const index_tuple<IdxPack...>&)
97    {}
98 
99    tuple<Args&...> args_;
100 };
101 
102 //!Describes a proxy class that implements named
103 //!allocation syntax.
104 template
105    < class SegmentManager  //segment manager to construct the object
106    , class T               //type of object to build
107    , bool is_iterator      //passing parameters are normal object or iterators?
108    >
109 class named_proxy
110 {
111    typedef typename SegmentManager::char_type char_type;
112    const char_type *    mp_name;
113    SegmentManager *     mp_mngr;
114    mutable std::size_t  m_num;
115    const bool           m_find;
116    const bool           m_dothrow;
117 
118    public:
named_proxy(SegmentManager * mngr,const char_type * name,bool find,bool dothrow)119    named_proxy(SegmentManager *mngr, const char_type *name, bool find, bool dothrow)
120       :  mp_name(name), mp_mngr(mngr), m_num(1)
121       ,  m_find(find),  m_dothrow(dothrow)
122    {}
123 
124    template<class ...Args>
operator ()(Args &&...args) const125    T *operator()(Args &&...args) const
126    {
127       CtorArgN<T, is_iterator, Args...> &&ctor_obj = CtorArgN<T, is_iterator, Args...>
128          (boost::forward<Args>(args)...);
129       return mp_mngr->template
130          generic_construct<T>(mp_name, m_num, m_find, m_dothrow, ctor_obj);
131    }
132 
133    //This operator allows --> named_new("Name")[3]; <-- syntax
operator [](std::size_t num) const134    const named_proxy &operator[](std::size_t num) const
135    {  m_num *= num; return *this;  }
136 };
137 
138 #else //#ifdef BOOST_INTERPROCESS_PERFECT_FORWARDING
139 
140 ////////////////////////////////////////////////////////////////
141 //    What the macro should generate (n == 2):
142 //
143 //    template<class T, bool is_iterator, class P1, class P2>
144 //    struct Ctor2Arg
145 //      :  public placement_destroy<T>
146 //    {
147 //       typedef bool_<is_iterator> IsIterator;
148 //       typedef Ctor2Arg self_t;
149 //
150 //       void do_increment(false_)
151 //       { ++m_p1; ++m_p2;  }
152 //
153 //       void do_increment(true_){}
154 //
155 //       self_t& operator++()
156 //       {
157 //          this->do_increment(IsIterator());
158 //          return *this;
159 //       }
160 //
161 //       self_t  operator++(int) {  return ++*this;   *this;  }
162 //
163 //       Ctor2Arg(const P1 &p1, const P2 &p2)
164 //          : p1((P1 &)p_1), p2((P2 &)p_2) {}
165 //
166 //       void construct(void *mem)
167 //       {  new((void*)object)T(m_p1, m_p2); }
168 //
169 //       virtual void construct_n(void *mem
170 //                                , std::size_t num
171 //                                , std::size_t &constructed)
172 //       {
173 //          T* memory      = static_cast<T*>(mem);
174 //          for(constructed = 0; constructed < num; ++constructed){
175 //             this->construct(memory++, IsIterator());
176 //             this->do_increment(IsIterator());
177 //          }
178 //       }
179 //
180 //       private:
181 //       void construct(void *mem, true_)
182 //       {  new((void*)mem)T(*m_p1, *m_p2); }
183 //
184 //       void construct(void *mem, false_)
185 //       {  new((void*)mem)T(m_p1, m_p2); }
186 //
187 //       P1 &m_p1; P2 &m_p2;
188 //    };
189 ////////////////////////////////////////////////////////////////
190 
191 #define BOOST_INTERPROCESS_NAMED_PROXY_CTORARGN(N)\
192 \
193 template<class T BOOST_MOVE_I##N BOOST_MOVE_CLASS##N >  \
194 struct CtorArg##N : placement_destroy<T>\
195 {\
196    typedef CtorArg##N self_t;\
197    \
198    CtorArg##N ( BOOST_MOVE_UREF##N  )\
199       BOOST_MOVE_COLON##N BOOST_MOVE_FWD_INIT##N{}\
200    \
201    virtual void construct_n(void *mem, std::size_t num, std::size_t &constructed)\
202    {\
203       T* memory      = static_cast<T*>(mem);\
204       for(constructed = 0; constructed < num; ++constructed){\
205          ::new((void*)memory++) T ( BOOST_MOVE_MFWD##N );\
206       }\
207    }\
208    \
209    private:\
210    BOOST_MOVE_MREF##N\
211 };\
212 //!
213 BOOST_MOVE_ITERATE_0TO9(BOOST_INTERPROCESS_NAMED_PROXY_CTORARGN)
214 #undef BOOST_INTERPROCESS_NAMED_PROXY_CTORARGN
215 
216 #define BOOST_INTERPROCESS_NAMED_PROXY_CTORITN(N)\
217 \
218 template<class T BOOST_MOVE_I##N BOOST_MOVE_CLASS##N > \
219 struct CtorIt##N : public placement_destroy<T>\
220 {\
221    typedef CtorIt##N self_t;\
222    \
223    self_t& operator++()\
224    {  BOOST_MOVE_MINC##N;  return *this;  }\
225    \
226    self_t  operator++(int) {  return ++*this; *this;  }\
227    \
228    CtorIt##N ( BOOST_MOVE_VAL##N  )\
229       BOOST_MOVE_COLON##N BOOST_MOVE_VAL_INIT##N{}\
230    \
231    virtual void construct_n(void *mem, std::size_t num, std::size_t &constructed)\
232    {\
233       T* memory      = static_cast<T*>(mem);\
234       for(constructed = 0; constructed < num; ++constructed){\
235          ::new((void*)memory++) T( BOOST_MOVE_MITFWD##N );\
236          ++(*this);\
237       }\
238    }\
239    \
240    private:\
241    BOOST_MOVE_MEMB##N\
242 };\
243 //!
244 BOOST_MOVE_ITERATE_0TO9(BOOST_INTERPROCESS_NAMED_PROXY_CTORITN)
245 #undef BOOST_INTERPROCESS_NAMED_PROXY_CTORITN
246 
247 //!Describes a proxy class that implements named
248 //!allocation syntax.
249 template
250    < class SegmentManager  //segment manager to construct the object
251    , class T               //type of object to build
252    , bool is_iterator      //passing parameters are normal object or iterators?
253    >
254 class named_proxy
255 {
256    typedef typename SegmentManager::char_type char_type;
257    const char_type *    mp_name;
258    SegmentManager *     mp_mngr;
259    mutable std::size_t  m_num;
260    const bool           m_find;
261    const bool           m_dothrow;
262 
263    public:
264    named_proxy(SegmentManager *mngr, const char_type *name, bool find, bool dothrow)
265       :  mp_name(name), mp_mngr(mngr), m_num(1)
266       ,  m_find(find),  m_dothrow(dothrow)
267    {}
268 
269    #define BOOST_INTERPROCESS_NAMED_PROXY_CALL_OPERATOR(N)\
270    \
271    BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
272    T *operator()( BOOST_MOVE_UREF##N ) const\
273    {\
274       typedef typename if_c<is_iterator \
275          , CtorIt##N<T BOOST_MOVE_I##N BOOST_MOVE_TARG##N> \
276          , CtorArg##N<T BOOST_MOVE_I##N BOOST_MOVE_TARG##N> \
277          >::type ctor_obj_t;\
278       ctor_obj_t ctor_obj = ctor_obj_t( BOOST_MOVE_FWD##N );\
279       return mp_mngr->template generic_construct<T>(mp_name, m_num, m_find, m_dothrow, ctor_obj);\
280    }\
281    //
282    BOOST_MOVE_ITERATE_0TO9(BOOST_INTERPROCESS_NAMED_PROXY_CALL_OPERATOR)
283    #undef BOOST_INTERPROCESS_NAMED_PROXY_CALL_OPERATOR
284 
285    ////////////////////////////////////////////////////////////////////////
286    //             What the macro should generate (n == 2)
287    ////////////////////////////////////////////////////////////////////////
288    //
289    // template <class P1, class P2>
290    // T *operator()(P1 &p1, P2 &p2) const
291    // {
292    //    typedef CtorArg2
293    //       <T, is_iterator, P1, P2>
294    //       ctor_obj_t;
295    //    ctor_obj_t ctor_obj(p1, p2);
296    //
297    //    return mp_mngr->template generic_construct<T>
298    //       (mp_name, m_num, m_find, m_dothrow, ctor_obj);
299    // }
300    //
301    //////////////////////////////////////////////////////////////////////////
302 
303    //This operator allows --> named_new("Name")[3]; <-- syntax
304    const named_proxy &operator[](std::size_t num) const
305       {  m_num *= num; return *this;  }
306 };
307 
308 #endif   //#ifdef BOOST_INTERPROCESS_PERFECT_FORWARDING
309 
310 }}}   //namespace boost { namespace interprocess { namespace ipcdetail {
311 
312 #include <boost/interprocess/detail/config_end.hpp>
313 
314 #endif //#ifndef BOOST_INTERPROCESS_NAMED_PROXY_HPP
315