]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
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 | ||
55 | self_t& operator++() | |
56 | { | |
57 | this->do_increment(IsIterator(), index_tuple_t()); | |
58 | return *this; | |
59 | } | |
60 | ||
61 | self_t operator++(int) { return ++*this; *this; } | |
62 | ||
63 | CtorArgN(Args && ...args) | |
64 | : args_(args...) | |
65 | {} | |
66 | ||
67 | virtual void construct_n(void *mem | |
68 | , std::size_t num | |
1e59de90 | 69 | , std::size_t &constructed) BOOST_OVERRIDE |
7c673cae FG |
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> | |
80 | 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> | |
84 | 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> | |
88 | void do_increment(true_, const index_tuple<IdxPack...>&) | |
89 | { | |
90 | this->expansion_helper(++get<IdxPack>(args_)...); | |
91 | } | |
92 | ||
93 | template<class ...ExpansionArgs> | |
94 | void expansion_helper(ExpansionArgs &&...) | |
95 | {} | |
96 | ||
97 | template<std::size_t ...IdxPack> | |
98 | 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: | |
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> | |
127 | 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 | |
136 | 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 | \ | |
1e59de90 | 203 | virtual void construct_n(void *mem, std::size_t num, std::size_t &constructed) BOOST_OVERRIDE\ |
7c673cae FG |
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 | \ | |
1e59de90 | 233 | virtual void construct_n(void *mem, std::size_t num, std::size_t &constructed) BOOST_OVERRIDE\ |
7c673cae FG |
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 \ | |
11fdf7f2 | 277 | , CtorIt##N <T BOOST_MOVE_I##N BOOST_MOVE_TARG##N> \ |
7c673cae FG |
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 |