• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include <cstddef>
38 
39 //!\file
40 //!Describes a proxy class that implements named allocation syntax.
41 
42 namespace boost {
43 namespace interprocess {
44 namespace ipcdetail {
45 
46 #ifdef BOOST_INTERPROCESS_PERFECT_FORWARDING
47 
48 template<class T, bool is_iterator, class ...Args>
49 struct CtorArgN : public placement_destroy<T>
50 {
51    typedef bool_<is_iterator> IsIterator;
52    typedef CtorArgN<T, is_iterator, Args...> self_t;
53    typedef typename build_number_seq<sizeof...(Args)>::type index_tuple_t;
54 
operator ++boost::interprocess::ipcdetail::CtorArgN55    self_t& operator++()
56    {
57       this->do_increment(IsIterator(), index_tuple_t());
58       return *this;
59    }
60 
operator ++boost::interprocess::ipcdetail::CtorArgN61    self_t  operator++(int) {  return ++*this;   *this;  }
62 
CtorArgNboost::interprocess::ipcdetail::CtorArgN63    CtorArgN(Args && ...args)
64       :  args_(args...)
65    {}
66 
construct_nboost::interprocess::ipcdetail::CtorArgN67    virtual void construct_n(void *mem
68                      , std::size_t num
69                      , std::size_t &constructed)
70    {
71       T* memory      = static_cast<T*>(mem);
72       for(constructed = 0; constructed < num; ++constructed){
73          this->construct(memory++, IsIterator(), index_tuple_t());
74          this->do_increment(IsIterator(), index_tuple_t());
75       }
76    }
77 
78    private:
79    template<std::size_t ...IdxPack>
constructboost::interprocess::ipcdetail::CtorArgN80    void construct(void *mem, true_, const index_tuple<IdxPack...>&)
81    {  ::new((void*)mem, boost_container_new_t())T(*boost::forward<Args>(get<IdxPack>(args_))...); }
82 
83    template<std::size_t ...IdxPack>
constructboost::interprocess::ipcdetail::CtorArgN84    void construct(void *mem, false_, const index_tuple<IdxPack...>&)
85    {  ::new((void*)mem, boost_container_new_t())T(boost::forward<Args>(get<IdxPack>(args_))...); }
86 
87    template<std::size_t ...IdxPack>
do_incrementboost::interprocess::ipcdetail::CtorArgN88    void do_increment(true_, const index_tuple<IdxPack...>&)
89    {
90       this->expansion_helper(++get<IdxPack>(args_)...);
91    }
92 
93    template<class ...ExpansionArgs>
expansion_helperboost::interprocess::ipcdetail::CtorArgN94    void expansion_helper(ExpansionArgs &&...)
95    {}
96 
97    template<std::size_t ...IdxPack>
do_incrementboost::interprocess::ipcdetail::CtorArgN98    void do_increment(false_, const index_tuple<IdxPack...>&)
99    {}
100 
101    tuple<Args&...> args_;
102 };
103 
104 //!Describes a proxy class that implements named
105 //!allocation syntax.
106 template
107    < class SegmentManager  //segment manager to construct the object
108    , class T               //type of object to build
109    , bool is_iterator      //passing parameters are normal object or iterators?
110    >
111 class named_proxy
112 {
113    typedef typename SegmentManager::char_type char_type;
114    const char_type *    mp_name;
115    SegmentManager *     mp_mngr;
116    mutable std::size_t  m_num;
117    const bool           m_find;
118    const bool           m_dothrow;
119 
120    public:
named_proxy(SegmentManager * mngr,const char_type * name,bool find,bool dothrow)121    named_proxy(SegmentManager *mngr, const char_type *name, bool find, bool dothrow)
122       :  mp_name(name), mp_mngr(mngr), m_num(1)
123       ,  m_find(find),  m_dothrow(dothrow)
124    {}
125 
126    template<class ...Args>
operator ()(Args &&...args) const127    T *operator()(Args &&...args) const
128    {
129       CtorArgN<T, is_iterator, Args...> &&ctor_obj = CtorArgN<T, is_iterator, Args...>
130          (boost::forward<Args>(args)...);
131       return mp_mngr->template
132          generic_construct<T>(mp_name, m_num, m_find, m_dothrow, ctor_obj);
133    }
134 
135    //This operator allows --> named_new("Name")[3]; <-- syntax
operator [](std::size_t num) const136    const named_proxy &operator[](std::size_t num) const
137    {  m_num *= num; return *this;  }
138 };
139 
140 #else //#ifdef BOOST_INTERPROCESS_PERFECT_FORWARDING
141 
142 ////////////////////////////////////////////////////////////////
143 //    What the macro should generate (n == 2):
144 //
145 //    template<class T, bool is_iterator, class P1, class P2>
146 //    struct Ctor2Arg
147 //      :  public placement_destroy<T>
148 //    {
149 //       typedef bool_<is_iterator> IsIterator;
150 //       typedef Ctor2Arg self_t;
151 //
152 //       void do_increment(false_)
153 //       { ++m_p1; ++m_p2;  }
154 //
155 //       void do_increment(true_){}
156 //
157 //       self_t& operator++()
158 //       {
159 //          this->do_increment(IsIterator());
160 //          return *this;
161 //       }
162 //
163 //       self_t  operator++(int) {  return ++*this;   *this;  }
164 //
165 //       Ctor2Arg(const P1 &p1, const P2 &p2)
166 //          : p1((P1 &)p_1), p2((P2 &)p_2) {}
167 //
168 //       void construct(void *mem)
169 //       {  new((void*)object)T(m_p1, m_p2); }
170 //
171 //       virtual void construct_n(void *mem
172 //                                , std::size_t num
173 //                                , std::size_t &constructed)
174 //       {
175 //          T* memory      = static_cast<T*>(mem);
176 //          for(constructed = 0; constructed < num; ++constructed){
177 //             this->construct(memory++, IsIterator());
178 //             this->do_increment(IsIterator());
179 //          }
180 //       }
181 //
182 //       private:
183 //       void construct(void *mem, true_)
184 //       {  new((void*)mem)T(*m_p1, *m_p2); }
185 //
186 //       void construct(void *mem, false_)
187 //       {  new((void*)mem)T(m_p1, m_p2); }
188 //
189 //       P1 &m_p1; P2 &m_p2;
190 //    };
191 ////////////////////////////////////////////////////////////////
192 
193 #define BOOST_INTERPROCESS_NAMED_PROXY_CTORARGN(N)\
194 \
195 template<class T BOOST_MOVE_I##N BOOST_MOVE_CLASS##N >  \
196 struct CtorArg##N : placement_destroy<T>\
197 {\
198    typedef CtorArg##N self_t;\
199    \
200    CtorArg##N ( BOOST_MOVE_UREF##N  )\
201       BOOST_MOVE_COLON##N BOOST_MOVE_FWD_INIT##N{}\
202    \
203    virtual void construct_n(void *mem, std::size_t num, std::size_t &constructed)\
204    {\
205       T* memory      = static_cast<T*>(mem);\
206       for(constructed = 0; constructed < num; ++constructed){\
207          ::new((void*)memory++) T ( BOOST_MOVE_MFWD##N );\
208       }\
209    }\
210    \
211    private:\
212    BOOST_MOVE_MREF##N\
213 };\
214 //!
215 BOOST_MOVE_ITERATE_0TO9(BOOST_INTERPROCESS_NAMED_PROXY_CTORARGN)
216 #undef BOOST_INTERPROCESS_NAMED_PROXY_CTORARGN
217 
218 #define BOOST_INTERPROCESS_NAMED_PROXY_CTORITN(N)\
219 \
220 template<class T BOOST_MOVE_I##N BOOST_MOVE_CLASS##N > \
221 struct CtorIt##N : public placement_destroy<T>\
222 {\
223    typedef CtorIt##N self_t;\
224    \
225    self_t& operator++()\
226    {  BOOST_MOVE_MINC##N;  return *this;  }\
227    \
228    self_t  operator++(int) {  return ++*this; *this;  }\
229    \
230    CtorIt##N ( BOOST_MOVE_VAL##N  )\
231       BOOST_MOVE_COLON##N BOOST_MOVE_VAL_INIT##N{}\
232    \
233    virtual void construct_n(void *mem, std::size_t num, std::size_t &constructed)\
234    {\
235       T* memory      = static_cast<T*>(mem);\
236       for(constructed = 0; constructed < num; ++constructed){\
237          ::new((void*)memory++) T( BOOST_MOVE_MITFWD##N );\
238          ++(*this);\
239       }\
240    }\
241    \
242    private:\
243    BOOST_MOVE_MEMB##N\
244 };\
245 //!
246 BOOST_MOVE_ITERATE_0TO9(BOOST_INTERPROCESS_NAMED_PROXY_CTORITN)
247 #undef BOOST_INTERPROCESS_NAMED_PROXY_CTORITN
248 
249 //!Describes a proxy class that implements named
250 //!allocation syntax.
251 template
252    < class SegmentManager  //segment manager to construct the object
253    , class T               //type of object to build
254    , bool is_iterator      //passing parameters are normal object or iterators?
255    >
256 class named_proxy
257 {
258    typedef typename SegmentManager::char_type char_type;
259    const char_type *    mp_name;
260    SegmentManager *     mp_mngr;
261    mutable std::size_t  m_num;
262    const bool           m_find;
263    const bool           m_dothrow;
264 
265    public:
266    named_proxy(SegmentManager *mngr, const char_type *name, bool find, bool dothrow)
267       :  mp_name(name), mp_mngr(mngr), m_num(1)
268       ,  m_find(find),  m_dothrow(dothrow)
269    {}
270 
271    #define BOOST_INTERPROCESS_NAMED_PROXY_CALL_OPERATOR(N)\
272    \
273    BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
274    T *operator()( BOOST_MOVE_UREF##N ) const\
275    {\
276       typedef typename if_c<is_iterator \
277          , CtorIt##N <T BOOST_MOVE_I##N BOOST_MOVE_TARG##N> \
278          , CtorArg##N<T BOOST_MOVE_I##N BOOST_MOVE_TARG##N> \
279          >::type ctor_obj_t;\
280       ctor_obj_t ctor_obj = ctor_obj_t( BOOST_MOVE_FWD##N );\
281       return mp_mngr->template generic_construct<T>(mp_name, m_num, m_find, m_dothrow, ctor_obj);\
282    }\
283    //
284    BOOST_MOVE_ITERATE_0TO9(BOOST_INTERPROCESS_NAMED_PROXY_CALL_OPERATOR)
285    #undef BOOST_INTERPROCESS_NAMED_PROXY_CALL_OPERATOR
286 
287    ////////////////////////////////////////////////////////////////////////
288    //             What the macro should generate (n == 2)
289    ////////////////////////////////////////////////////////////////////////
290    //
291    // template <class P1, class P2>
292    // T *operator()(P1 &p1, P2 &p2) const
293    // {
294    //    typedef CtorArg2
295    //       <T, is_iterator, P1, P2>
296    //       ctor_obj_t;
297    //    ctor_obj_t ctor_obj(p1, p2);
298    //
299    //    return mp_mngr->template generic_construct<T>
300    //       (mp_name, m_num, m_find, m_dothrow, ctor_obj);
301    // }
302    //
303    //////////////////////////////////////////////////////////////////////////
304 
305    //This operator allows --> named_new("Name")[3]; <-- syntax
306    const named_proxy &operator[](std::size_t num) const
307       {  m_num *= num; return *this;  }
308 };
309 
310 #endif   //#ifdef BOOST_INTERPROCESS_PERFECT_FORWARDING
311 
312 }}}   //namespace boost { namespace interprocess { namespace ipcdetail {
313 
314 #include <boost/interprocess/detail/config_end.hpp>
315 
316 #endif //#ifndef BOOST_INTERPROCESS_NAMED_PROXY_HPP
317