Chris@16
|
1 //////////////////////////////////////////////////////////////////////////////
|
Chris@16
|
2 //
|
Chris@16
|
3 // (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
|
Chris@16
|
4 // Software License, Version 1.0. (See accompanying file
|
Chris@16
|
5 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
Chris@16
|
6 //
|
Chris@16
|
7 // See http://www.boost.org/libs/interprocess for documentation.
|
Chris@16
|
8 //
|
Chris@16
|
9 //////////////////////////////////////////////////////////////////////////////
|
Chris@16
|
10
|
Chris@16
|
11 #ifndef BOOST_INTERPROCESS_NAMED_PROXY_HPP
|
Chris@16
|
12 #define BOOST_INTERPROCESS_NAMED_PROXY_HPP
|
Chris@16
|
13
|
Chris@16
|
14 #if (defined _MSC_VER) && (_MSC_VER >= 1200)
|
Chris@16
|
15 # pragma once
|
Chris@16
|
16 #endif
|
Chris@16
|
17
|
Chris@16
|
18 #include <boost/interprocess/detail/config_begin.hpp>
|
Chris@16
|
19 #include <boost/interprocess/detail/workaround.hpp>
|
Chris@16
|
20
|
Chris@16
|
21 #include <new>
|
Chris@16
|
22 #include <iterator>
|
Chris@16
|
23 #include <boost/interprocess/detail/in_place_interface.hpp>
|
Chris@16
|
24 #include <boost/interprocess/detail/mpl.hpp>
|
Chris@16
|
25
|
Chris@16
|
26 #ifndef BOOST_INTERPROCESS_PERFECT_FORWARDING
|
Chris@16
|
27 #include <boost/interprocess/detail/preprocessor.hpp>
|
Chris@16
|
28 #else
|
Chris@16
|
29 #include <boost/move/move.hpp>
|
Chris@16
|
30 #include <boost/interprocess/detail/variadic_templates_tools.hpp>
|
Chris@16
|
31 #endif //#ifdef BOOST_INTERPROCESS_PERFECT_FORWARDING
|
Chris@16
|
32
|
Chris@16
|
33 //!\file
|
Chris@16
|
34 //!Describes a proxy class that implements named allocation syntax.
|
Chris@16
|
35
|
Chris@16
|
36 namespace boost {
|
Chris@16
|
37 namespace interprocess {
|
Chris@16
|
38 namespace ipcdetail {
|
Chris@16
|
39
|
Chris@16
|
40 #ifdef BOOST_INTERPROCESS_PERFECT_FORWARDING
|
Chris@16
|
41
|
Chris@16
|
42 template<class T, bool is_iterator, class ...Args>
|
Chris@16
|
43 struct CtorNArg : public placement_destroy<T>
|
Chris@16
|
44 {
|
Chris@16
|
45 typedef bool_<is_iterator> IsIterator;
|
Chris@16
|
46 typedef CtorNArg<T, is_iterator, Args...> self_t;
|
Chris@16
|
47 typedef typename build_number_seq<sizeof...(Args)>::type index_tuple_t;
|
Chris@16
|
48
|
Chris@16
|
49 self_t& operator++()
|
Chris@16
|
50 {
|
Chris@16
|
51 this->do_increment(IsIterator(), index_tuple_t());
|
Chris@16
|
52 return *this;
|
Chris@16
|
53 }
|
Chris@16
|
54
|
Chris@16
|
55 self_t operator++(int) { return ++*this; *this; }
|
Chris@16
|
56
|
Chris@16
|
57 CtorNArg(Args && ...args)
|
Chris@16
|
58 : args_(args...)
|
Chris@16
|
59 {}
|
Chris@16
|
60
|
Chris@16
|
61 virtual void construct_n(void *mem
|
Chris@16
|
62 , std::size_t num
|
Chris@16
|
63 , std::size_t &constructed)
|
Chris@16
|
64 {
|
Chris@16
|
65 T* memory = static_cast<T*>(mem);
|
Chris@16
|
66 for(constructed = 0; constructed < num; ++constructed){
|
Chris@16
|
67 this->construct(memory++, IsIterator(), index_tuple_t());
|
Chris@16
|
68 this->do_increment(IsIterator(), index_tuple_t());
|
Chris@16
|
69 }
|
Chris@16
|
70 }
|
Chris@16
|
71
|
Chris@16
|
72 private:
|
Chris@16
|
73 template<int ...IdxPack>
|
Chris@16
|
74 void construct(void *mem, true_, const index_tuple<IdxPack...>&)
|
Chris@16
|
75 { new((void*)mem)T(*boost::forward<Args>(get<IdxPack>(args_))...); }
|
Chris@16
|
76
|
Chris@16
|
77 template<int ...IdxPack>
|
Chris@16
|
78 void construct(void *mem, false_, const index_tuple<IdxPack...>&)
|
Chris@16
|
79 { new((void*)mem)T(boost::forward<Args>(get<IdxPack>(args_))...); }
|
Chris@16
|
80
|
Chris@16
|
81 template<int ...IdxPack>
|
Chris@16
|
82 void do_increment(true_, const index_tuple<IdxPack...>&)
|
Chris@16
|
83 {
|
Chris@16
|
84 this->expansion_helper(++get<IdxPack>(args_)...);
|
Chris@16
|
85 }
|
Chris@16
|
86
|
Chris@16
|
87 template<class ...ExpansionArgs>
|
Chris@16
|
88 void expansion_helper(ExpansionArgs &&...)
|
Chris@16
|
89 {}
|
Chris@16
|
90
|
Chris@16
|
91 template<int ...IdxPack>
|
Chris@16
|
92 void do_increment(false_, const index_tuple<IdxPack...>&)
|
Chris@16
|
93 {}
|
Chris@16
|
94
|
Chris@16
|
95 tuple<Args&...> args_;
|
Chris@16
|
96 };
|
Chris@16
|
97
|
Chris@16
|
98 //!Describes a proxy class that implements named
|
Chris@16
|
99 //!allocation syntax.
|
Chris@16
|
100 template
|
Chris@16
|
101 < class SegmentManager //segment manager to construct the object
|
Chris@16
|
102 , class T //type of object to build
|
Chris@16
|
103 , bool is_iterator //passing parameters are normal object or iterators?
|
Chris@16
|
104 >
|
Chris@16
|
105 class named_proxy
|
Chris@16
|
106 {
|
Chris@16
|
107 typedef typename SegmentManager::char_type char_type;
|
Chris@16
|
108 const char_type * mp_name;
|
Chris@16
|
109 SegmentManager * mp_mngr;
|
Chris@16
|
110 mutable std::size_t m_num;
|
Chris@16
|
111 const bool m_find;
|
Chris@16
|
112 const bool m_dothrow;
|
Chris@16
|
113
|
Chris@16
|
114 public:
|
Chris@16
|
115 named_proxy(SegmentManager *mngr, const char_type *name, bool find, bool dothrow)
|
Chris@16
|
116 : mp_name(name), mp_mngr(mngr), m_num(1)
|
Chris@16
|
117 , m_find(find), m_dothrow(dothrow)
|
Chris@16
|
118 {}
|
Chris@16
|
119
|
Chris@16
|
120 template<class ...Args>
|
Chris@16
|
121 T *operator()(Args &&...args) const
|
Chris@16
|
122 {
|
Chris@16
|
123 CtorNArg<T, is_iterator, Args...> &&ctor_obj = CtorNArg<T, is_iterator, Args...>
|
Chris@16
|
124 (boost::forward<Args>(args)...);
|
Chris@16
|
125 return mp_mngr->template
|
Chris@16
|
126 generic_construct<T>(mp_name, m_num, m_find, m_dothrow, ctor_obj);
|
Chris@16
|
127 }
|
Chris@16
|
128
|
Chris@16
|
129 //This operator allows --> named_new("Name")[3]; <-- syntax
|
Chris@16
|
130 const named_proxy &operator[](std::size_t num) const
|
Chris@16
|
131 { m_num *= num; return *this; }
|
Chris@16
|
132 };
|
Chris@16
|
133
|
Chris@16
|
134 #else //#ifdef BOOST_INTERPROCESS_PERFECT_FORWARDING
|
Chris@16
|
135
|
Chris@16
|
136 //!Function object that makes placement new
|
Chris@16
|
137 //!without arguments
|
Chris@16
|
138 template<class T>
|
Chris@16
|
139 struct Ctor0Arg : public placement_destroy<T>
|
Chris@16
|
140 {
|
Chris@16
|
141 typedef Ctor0Arg self_t;
|
Chris@16
|
142
|
Chris@16
|
143 Ctor0Arg(){}
|
Chris@16
|
144
|
Chris@16
|
145 self_t& operator++() { return *this; }
|
Chris@16
|
146 self_t operator++(int) { return *this; }
|
Chris@16
|
147
|
Chris@16
|
148 void construct(void *mem)
|
Chris@16
|
149 { new((void*)mem)T; }
|
Chris@16
|
150
|
Chris@16
|
151 virtual void construct_n(void *mem, std::size_t num, std::size_t &constructed)
|
Chris@16
|
152 {
|
Chris@16
|
153 T* memory = static_cast<T*>(mem);
|
Chris@16
|
154 for(constructed = 0; constructed < num; ++constructed)
|
Chris@16
|
155 new((void*)memory++)T;
|
Chris@16
|
156 }
|
Chris@16
|
157 };
|
Chris@16
|
158
|
Chris@16
|
159 ////////////////////////////////////////////////////////////////
|
Chris@16
|
160 // What the macro should generate (n == 2):
|
Chris@16
|
161 //
|
Chris@16
|
162 // template<class T, bool is_iterator, class P1, class P2>
|
Chris@16
|
163 // struct Ctor2Arg
|
Chris@16
|
164 // : public placement_destroy<T>
|
Chris@16
|
165 // {
|
Chris@16
|
166 // typedef bool_<is_iterator> IsIterator;
|
Chris@16
|
167 // typedef Ctor2Arg self_t;
|
Chris@16
|
168 //
|
Chris@16
|
169 // void do_increment(false_)
|
Chris@16
|
170 // { ++m_p1; ++m_p2; }
|
Chris@16
|
171 //
|
Chris@16
|
172 // void do_increment(true_){}
|
Chris@16
|
173 //
|
Chris@16
|
174 // self_t& operator++()
|
Chris@16
|
175 // {
|
Chris@16
|
176 // this->do_increment(IsIterator());
|
Chris@16
|
177 // return *this;
|
Chris@16
|
178 // }
|
Chris@16
|
179 //
|
Chris@16
|
180 // self_t operator++(int) { return ++*this; *this; }
|
Chris@16
|
181 //
|
Chris@16
|
182 // Ctor2Arg(const P1 &p1, const P2 &p2)
|
Chris@16
|
183 // : p1((P1 &)p_1), p2((P2 &)p_2) {}
|
Chris@16
|
184 //
|
Chris@16
|
185 // void construct(void *mem)
|
Chris@16
|
186 // { new((void*)object)T(m_p1, m_p2); }
|
Chris@16
|
187 //
|
Chris@16
|
188 // virtual void construct_n(void *mem
|
Chris@16
|
189 // , std::size_t num
|
Chris@16
|
190 // , std::size_t &constructed)
|
Chris@16
|
191 // {
|
Chris@16
|
192 // T* memory = static_cast<T*>(mem);
|
Chris@16
|
193 // for(constructed = 0; constructed < num; ++constructed){
|
Chris@16
|
194 // this->construct(memory++, IsIterator());
|
Chris@16
|
195 // this->do_increment(IsIterator());
|
Chris@16
|
196 // }
|
Chris@16
|
197 // }
|
Chris@16
|
198 //
|
Chris@16
|
199 // private:
|
Chris@16
|
200 // void construct(void *mem, true_)
|
Chris@16
|
201 // { new((void*)mem)T(*m_p1, *m_p2); }
|
Chris@16
|
202 //
|
Chris@16
|
203 // void construct(void *mem, false_)
|
Chris@16
|
204 // { new((void*)mem)T(m_p1, m_p2); }
|
Chris@16
|
205 //
|
Chris@16
|
206 // P1 &m_p1; P2 &m_p2;
|
Chris@16
|
207 // };
|
Chris@16
|
208 ////////////////////////////////////////////////////////////////
|
Chris@16
|
209
|
Chris@16
|
210 //Note:
|
Chris@16
|
211 //We define template parameters as const references to
|
Chris@16
|
212 //be able to bind temporaries. After that we will un-const them.
|
Chris@16
|
213 //This cast is ugly but it is necessary until "perfect forwarding"
|
Chris@16
|
214 //is achieved in C++0x. Meanwhile, if we want to be able to
|
Chris@16
|
215 //bind lvalues with non-const references, we have to be ugly
|
Chris@16
|
216 #define BOOST_PP_LOCAL_MACRO(n) \
|
Chris@16
|
217 template<class T, bool is_iterator, BOOST_PP_ENUM_PARAMS(n, class P) > \
|
Chris@16
|
218 struct BOOST_PP_CAT(BOOST_PP_CAT(Ctor, n), Arg) \
|
Chris@16
|
219 : public placement_destroy<T> \
|
Chris@16
|
220 { \
|
Chris@16
|
221 typedef bool_<is_iterator> IsIterator; \
|
Chris@16
|
222 typedef BOOST_PP_CAT(BOOST_PP_CAT(Ctor, n), Arg) self_t; \
|
Chris@16
|
223 \
|
Chris@16
|
224 void do_increment(true_) \
|
Chris@16
|
225 { BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_PARAM_INC, _); } \
|
Chris@16
|
226 \
|
Chris@16
|
227 void do_increment(false_){} \
|
Chris@16
|
228 \
|
Chris@16
|
229 self_t& operator++() \
|
Chris@16
|
230 { \
|
Chris@16
|
231 this->do_increment(IsIterator()); \
|
Chris@16
|
232 return *this; \
|
Chris@16
|
233 } \
|
Chris@16
|
234 \
|
Chris@16
|
235 self_t operator++(int) { return ++*this; *this; } \
|
Chris@16
|
236 \
|
Chris@16
|
237 BOOST_PP_CAT(BOOST_PP_CAT(Ctor, n), Arg) \
|
Chris@16
|
238 ( BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_PARAM_LIST, _) ) \
|
Chris@16
|
239 : BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_PARAM_INIT, _) {} \
|
Chris@16
|
240 \
|
Chris@16
|
241 virtual void construct_n(void *mem \
|
Chris@16
|
242 , std::size_t num \
|
Chris@16
|
243 , std::size_t &constructed) \
|
Chris@16
|
244 { \
|
Chris@16
|
245 T* memory = static_cast<T*>(mem); \
|
Chris@16
|
246 for(constructed = 0; constructed < num; ++constructed){ \
|
Chris@16
|
247 this->construct(memory++, IsIterator()); \
|
Chris@16
|
248 this->do_increment(IsIterator()); \
|
Chris@16
|
249 } \
|
Chris@16
|
250 } \
|
Chris@16
|
251 \
|
Chris@16
|
252 private: \
|
Chris@16
|
253 void construct(void *mem, true_) \
|
Chris@16
|
254 { \
|
Chris@16
|
255 new((void*)mem) T \
|
Chris@16
|
256 (BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_MEMBER_IT_FORWARD, _)); \
|
Chris@16
|
257 } \
|
Chris@16
|
258 \
|
Chris@16
|
259 void construct(void *mem, false_) \
|
Chris@16
|
260 { \
|
Chris@16
|
261 new((void*)mem) T \
|
Chris@16
|
262 (BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_MEMBER_FORWARD, _)); \
|
Chris@16
|
263 } \
|
Chris@16
|
264 \
|
Chris@16
|
265 BOOST_PP_REPEAT(n, BOOST_INTERPROCESS_PP_PARAM_DEFINE, _) \
|
Chris@16
|
266 }; \
|
Chris@16
|
267 //!
|
Chris@16
|
268 #define BOOST_PP_LOCAL_LIMITS (1, BOOST_INTERPROCESS_MAX_CONSTRUCTOR_PARAMETERS)
|
Chris@16
|
269 #include BOOST_PP_LOCAL_ITERATE()
|
Chris@16
|
270
|
Chris@16
|
271 //!Describes a proxy class that implements named
|
Chris@16
|
272 //!allocation syntax.
|
Chris@16
|
273 template
|
Chris@16
|
274 < class SegmentManager //segment manager to construct the object
|
Chris@16
|
275 , class T //type of object to build
|
Chris@16
|
276 , bool is_iterator //passing parameters are normal object or iterators?
|
Chris@16
|
277 >
|
Chris@16
|
278 class named_proxy
|
Chris@16
|
279 {
|
Chris@16
|
280 typedef typename SegmentManager::char_type char_type;
|
Chris@16
|
281 const char_type * mp_name;
|
Chris@16
|
282 SegmentManager * mp_mngr;
|
Chris@16
|
283 mutable std::size_t m_num;
|
Chris@16
|
284 const bool m_find;
|
Chris@16
|
285 const bool m_dothrow;
|
Chris@16
|
286
|
Chris@16
|
287 public:
|
Chris@16
|
288 named_proxy(SegmentManager *mngr, const char_type *name, bool find, bool dothrow)
|
Chris@16
|
289 : mp_name(name), mp_mngr(mngr), m_num(1)
|
Chris@16
|
290 , m_find(find), m_dothrow(dothrow)
|
Chris@16
|
291 {}
|
Chris@16
|
292
|
Chris@16
|
293 //!makes a named allocation and calls the
|
Chris@16
|
294 //!default constructor
|
Chris@16
|
295 T *operator()() const
|
Chris@16
|
296 {
|
Chris@16
|
297 Ctor0Arg<T> ctor_obj;
|
Chris@16
|
298 return mp_mngr->template
|
Chris@16
|
299 generic_construct<T>(mp_name, m_num, m_find, m_dothrow, ctor_obj);
|
Chris@16
|
300 }
|
Chris@16
|
301 //!
|
Chris@16
|
302
|
Chris@16
|
303 #define BOOST_PP_LOCAL_MACRO(n) \
|
Chris@16
|
304 template<BOOST_PP_ENUM_PARAMS(n, class P)> \
|
Chris@16
|
305 T *operator()(BOOST_PP_ENUM (n, BOOST_INTERPROCESS_PP_PARAM_LIST, _)) const\
|
Chris@16
|
306 { \
|
Chris@16
|
307 typedef BOOST_PP_CAT(BOOST_PP_CAT(Ctor, n), Arg) \
|
Chris@16
|
308 <T, is_iterator, BOOST_PP_ENUM_PARAMS(n, P)> \
|
Chris@16
|
309 ctor_obj_t; \
|
Chris@16
|
310 ctor_obj_t ctor_obj \
|
Chris@16
|
311 (BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_PARAM_FORWARD, _)); \
|
Chris@16
|
312 return mp_mngr->template generic_construct<T> \
|
Chris@16
|
313 (mp_name, m_num, m_find, m_dothrow, ctor_obj); \
|
Chris@16
|
314 } \
|
Chris@16
|
315 //!
|
Chris@16
|
316
|
Chris@16
|
317 #define BOOST_PP_LOCAL_LIMITS ( 1, BOOST_INTERPROCESS_MAX_CONSTRUCTOR_PARAMETERS )
|
Chris@16
|
318 #include BOOST_PP_LOCAL_ITERATE()
|
Chris@16
|
319
|
Chris@16
|
320 ////////////////////////////////////////////////////////////////////////
|
Chris@16
|
321 // What the macro should generate (n == 2)
|
Chris@16
|
322 ////////////////////////////////////////////////////////////////////////
|
Chris@16
|
323 //
|
Chris@16
|
324 // template <class P1, class P2>
|
Chris@16
|
325 // T *operator()(P1 &p1, P2 &p2) const
|
Chris@16
|
326 // {
|
Chris@16
|
327 // typedef Ctor2Arg
|
Chris@16
|
328 // <T, is_iterator, P1, P2>
|
Chris@16
|
329 // ctor_obj_t;
|
Chris@16
|
330 // ctor_obj_t ctor_obj(p1, p2);
|
Chris@16
|
331 //
|
Chris@16
|
332 // return mp_mngr->template generic_construct<T>
|
Chris@16
|
333 // (mp_name, m_num, m_find, m_dothrow, ctor_obj);
|
Chris@16
|
334 // }
|
Chris@16
|
335 //
|
Chris@16
|
336 //////////////////////////////////////////////////////////////////////////
|
Chris@16
|
337
|
Chris@16
|
338 //This operator allows --> named_new("Name")[3]; <-- syntax
|
Chris@16
|
339 const named_proxy &operator[](std::size_t num) const
|
Chris@16
|
340 { m_num *= num; return *this; }
|
Chris@16
|
341 };
|
Chris@16
|
342
|
Chris@16
|
343 #endif //#ifdef BOOST_INTERPROCESS_PERFECT_FORWARDING
|
Chris@16
|
344
|
Chris@16
|
345 }}} //namespace boost { namespace interprocess { namespace ipcdetail {
|
Chris@16
|
346
|
Chris@16
|
347 #include <boost/interprocess/detail/config_end.hpp>
|
Chris@16
|
348
|
Chris@16
|
349 #endif //#ifndef BOOST_INTERPROCESS_NAMED_PROXY_HPP
|