]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/signals2/include/boost/signals2/deconstruct.hpp
bump version to 12.2.2-pve1
[ceph.git] / ceph / src / boost / libs / signals2 / include / boost / signals2 / deconstruct.hpp
1 #ifndef BOOST_SIGNALS2_DECONSTRUCT_HPP
2 #define BOOST_SIGNALS2_DECONSTRUCT_HPP
3
4 // deconstruct.hpp
5 //
6 // A factory function for creating a shared_ptr which creates
7 // an object and its owning shared_ptr with one allocation, similar
8 // to make_shared<T>(). It also supports postconstructors
9 // and predestructors through unqualified calls of adl_postconstruct() and
10 // adl_predestruct, relying on argument-dependent
11 // lookup to find the appropriate postconstructor or predestructor.
12 // Passing arguments to postconstructors is also supported.
13 //
14 // based on make_shared.hpp and make_shared_access patch from Michael Marcin
15 //
16 // Copyright (c) 2007, 2008 Peter Dimov
17 // Copyright (c) 2008 Michael Marcin
18 // Copyright (c) 2009 Frank Mori Hess
19 //
20 // Distributed under the Boost Software License, Version 1.0.
21 // See accompanying file LICENSE_1_0.txt or copy at
22 // http://www.boost.org/LICENSE_1_0.txt
23 //
24 // See http://www.boost.org
25 // for more information
26
27 #include <boost/config.hpp>
28 #include <boost/shared_ptr.hpp>
29 #include <boost/type_traits/alignment_of.hpp>
30 #include <boost/type_traits/remove_const.hpp>
31 #include <boost/type_traits/type_with_alignment.hpp>
32 #include <cstddef>
33 #include <new>
34
35 namespace boost
36 {
37 template<typename T> class enable_shared_from_this;
38
39 namespace signals2
40 {
41 class deconstruct_access;
42
43 namespace detail
44 {
45 inline void adl_predestruct(...) {}
46 } // namespace detail
47
48 template<typename T>
49 class postconstructor_invoker
50 {
51 public:
52 operator const shared_ptr<T> & () const
53 {
54 return postconstruct();
55 }
56 const shared_ptr<T>& postconstruct() const
57 {
58 if(!_postconstructed)
59 {
60 adl_postconstruct(_sp, const_cast<typename boost::remove_const<T>::type *>(_sp.get()));
61 _postconstructed = true;
62 }
63 return _sp;
64 }
65 #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
66 template<class... Args>
67 const shared_ptr<T>& postconstruct(Args && ... args)
68 {
69 if(!_postconstructed)
70 {
71 adl_postconstruct(_sp, const_cast<typename boost::remove_const<T>::type *>(_sp.get()),
72 std::forward<Args>(args)...);
73 _postconstructed = true;
74 }
75 return _sp;
76 }
77 #else // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
78 template<typename A1>
79 const shared_ptr<T>& postconstruct(const A1 &a1) const
80 {
81 if(!_postconstructed)
82 {
83 adl_postconstruct(_sp, const_cast<typename boost::remove_const<T>::type *>(_sp.get()),
84 a1);
85 _postconstructed = true;
86 }
87 return _sp;
88 }
89 template<typename A1, typename A2>
90 const shared_ptr<T>& postconstruct(const A1 &a1, const A2 &a2) const
91 {
92 if(!_postconstructed)
93 {
94 adl_postconstruct(_sp, const_cast<typename boost::remove_const<T>::type *>(_sp.get()),
95 a1, a2);
96 _postconstructed = true;
97 }
98 return _sp;
99 }
100 template<typename A1, typename A2, typename A3>
101 const shared_ptr<T>& postconstruct(const A1 &a1, const A2 &a2, const A3 &a3) const
102 {
103 if(!_postconstructed)
104 {
105 adl_postconstruct(_sp, const_cast<typename boost::remove_const<T>::type *>(_sp.get()),
106 a1, a2, a3);
107 _postconstructed = true;
108 }
109 return _sp;
110 }
111 template<typename A1, typename A2, typename A3, typename A4>
112 const shared_ptr<T>& postconstruct(const A1 &a1, const A2 &a2, const A3 &a3, const A4 &a4) const
113 {
114 if(!_postconstructed)
115 {
116 adl_postconstruct(_sp, const_cast<typename boost::remove_const<T>::type *>(_sp.get()),
117 a1, a2, a3, a4);
118 _postconstructed = true;
119 }
120 return _sp;
121 }
122 template<typename A1, typename A2, typename A3, typename A4, typename A5>
123 const shared_ptr<T>& postconstruct(const A1 &a1, const A2 &a2, const A3 &a3, const A4 &a4, const A5 &a5) const
124 {
125 if(!_postconstructed)
126 {
127 adl_postconstruct(_sp, const_cast<typename boost::remove_const<T>::type *>(_sp.get()),
128 a1, a2, a3, a4, a5);
129 _postconstructed = true;
130 }
131 return _sp;
132 }
133 template<typename A1, typename A2, typename A3, typename A4, typename A5,
134 typename A6>
135 const shared_ptr<T>& postconstruct(const A1 &a1, const A2 &a2, const A3 &a3, const A4 &a4, const A5 &a5,
136 const A6 &a6) const
137 {
138 if(!_postconstructed)
139 {
140 adl_postconstruct(_sp, const_cast<typename boost::remove_const<T>::type *>(_sp.get()),
141 a1, a2, a3, a4, a5, a6);
142 _postconstructed = true;
143 }
144 return _sp;
145 }
146 template<typename A1, typename A2, typename A3, typename A4, typename A5,
147 typename A6, typename A7>
148 const shared_ptr<T>& postconstruct(const A1 &a1, const A2 &a2, const A3 &a3, const A4 &a4, const A5 &a5,
149 const A6 &a6, const A7 &a7) const
150 {
151 if(!_postconstructed)
152 {
153 adl_postconstruct(_sp, const_cast<typename boost::remove_const<T>::type *>(_sp.get()),
154 a1, a2, a3, a4, a5, a6, a7);
155 _postconstructed = true;
156 }
157 return _sp;
158 }
159 template<typename A1, typename A2, typename A3, typename A4, typename A5,
160 typename A6, typename A7, typename A8>
161 const shared_ptr<T>& postconstruct(const A1 &a1, const A2 &a2, const A3 &a3, const A4 &a4, const A5 &a5,
162 const A6 &a6, const A7 &a7, const A8 &a8) const
163 {
164 if(!_postconstructed)
165 {
166 adl_postconstruct(_sp, const_cast<typename boost::remove_const<T>::type *>(_sp.get()),
167 a1, a2, a3, a4, a5, a6, a7, a8);
168 _postconstructed = true;
169 }
170 return _sp;
171 }
172 template<typename A1, typename A2, typename A3, typename A4, typename A5,
173 typename A6, typename A7, typename A8, typename A9>
174 const shared_ptr<T>& postconstruct(const A1 &a1, const A2 &a2, const A3 &a3, const A4 &a4, const A5 &a5,
175 const A6 &a6, const A7 &a7, const A8 &a8, const A9 &a9) const
176 {
177 if(!_postconstructed)
178 {
179 adl_postconstruct(_sp, const_cast<typename boost::remove_const<T>::type *>(_sp.get()),
180 a1, a2, a3, a4, a5, a6, a7, a8, a9);
181 _postconstructed = true;
182 }
183 return _sp;
184 }
185 #endif // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
186 private:
187 friend class boost::signals2::deconstruct_access;
188 postconstructor_invoker(const shared_ptr<T> & sp):
189 _sp(sp), _postconstructed(false)
190 {}
191 shared_ptr<T> _sp;
192 mutable bool _postconstructed;
193 };
194
195 namespace detail
196 {
197
198 template< std::size_t N, std::size_t A > struct sp_aligned_storage
199 {
200 union type
201 {
202 char data_[ N ];
203 typename boost::type_with_alignment< A >::type align_;
204 };
205 };
206
207 template< class T > class deconstruct_deleter
208 {
209 private:
210
211 typedef typename sp_aligned_storage< sizeof( T ), ::boost::alignment_of< T >::value >::type storage_type;
212
213 bool initialized_;
214 storage_type storage_;
215
216 private:
217
218 void destroy()
219 {
220 if( initialized_ )
221 {
222 T* p = reinterpret_cast< T* >( storage_.data_ );
223 using boost::signals2::detail::adl_predestruct;
224 adl_predestruct(const_cast<typename boost::remove_const<T>::type *>(p));
225 p->~T();
226 initialized_ = false;
227 }
228 }
229
230 public:
231
232 deconstruct_deleter(): initialized_( false )
233 {
234 }
235
236 // this copy constructor is an optimization: we don't need to copy the storage_ member,
237 // and shouldn't be copying anyways after initialized_ becomes true
238 deconstruct_deleter(const deconstruct_deleter &): initialized_( false )
239 {
240 }
241
242 ~deconstruct_deleter()
243 {
244 destroy();
245 }
246
247 void operator()( T * )
248 {
249 destroy();
250 }
251
252 void * address()
253 {
254 return storage_.data_;
255 }
256
257 void set_initialized()
258 {
259 initialized_ = true;
260 }
261 };
262 } // namespace detail
263
264 class deconstruct_access
265 {
266 public:
267
268 template< class T >
269 static postconstructor_invoker<T> deconstruct()
270 {
271 boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::deconstruct_deleter< T >() );
272
273 detail::deconstruct_deleter< T > * pd = boost::get_deleter< detail::deconstruct_deleter< T > >( pt );
274
275 void * pv = pd->address();
276
277 new( pv ) T();
278 pd->set_initialized();
279
280 boost::shared_ptr< T > retval( pt, static_cast< T* >( pv ) );
281 boost::detail::sp_enable_shared_from_this(&retval, retval.get(), retval.get());
282 return retval;
283
284 }
285
286 #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
287
288 // Variadic templates, rvalue reference
289
290 template< class T, class... Args >
291 static postconstructor_invoker<T> deconstruct( Args && ... args )
292 {
293 boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::deconstruct_deleter< T >() );
294
295 detail::deconstruct_deleter< T > * pd = boost::get_deleter< detail::deconstruct_deleter< T > >( pt );
296
297 void * pv = pd->address();
298
299 new( pv ) T( std::forward<Args>( args )... );
300 pd->set_initialized();
301
302 boost::shared_ptr< T > retval( pt, static_cast< T* >( pv ) );
303 boost::detail::sp_enable_shared_from_this(&retval, retval.get(), retval.get());
304 return retval;
305 }
306
307 #else
308
309 template< class T, class A1 >
310 static postconstructor_invoker<T> deconstruct( A1 const & a1 )
311 {
312 boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::deconstruct_deleter< T >() );
313
314 detail::deconstruct_deleter< T > * pd = boost::get_deleter< detail::deconstruct_deleter< T > >( pt );
315
316 void * pv = pd->address();
317
318 new( pv ) T( a1 );
319 pd->set_initialized();
320
321 boost::shared_ptr< T > retval( pt, static_cast< T* >( pv ) );
322 boost::detail::sp_enable_shared_from_this(&retval, retval.get(), retval.get());
323 return retval;
324 }
325
326 template< class T, class A1, class A2 >
327 static postconstructor_invoker<T> deconstruct( A1 const & a1, A2 const & a2 )
328 {
329 boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::deconstruct_deleter< T >() );
330
331 detail::deconstruct_deleter< T > * pd = boost::get_deleter< detail::deconstruct_deleter< T > >( pt );
332
333 void * pv = pd->address();
334
335 new( pv ) T( a1, a2 );
336 pd->set_initialized();
337
338 boost::shared_ptr< T > retval( pt, static_cast< T* >( pv ) );
339 boost::detail::sp_enable_shared_from_this(&retval, retval.get(), retval.get());
340 return retval;
341 }
342
343 template< class T, class A1, class A2, class A3 >
344 static postconstructor_invoker<T> deconstruct( A1 const & a1, A2 const & a2, A3 const & a3 )
345 {
346 boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::deconstruct_deleter< T >() );
347
348 detail::deconstruct_deleter< T > * pd = boost::get_deleter< detail::deconstruct_deleter< T > >( pt );
349
350 void * pv = pd->address();
351
352 new( pv ) T( a1, a2, a3 );
353 pd->set_initialized();
354
355 boost::shared_ptr< T > retval( pt, static_cast< T* >( pv ) );
356 boost::detail::sp_enable_shared_from_this(&retval, retval.get(), retval.get());
357 return retval;
358 }
359
360 template< class T, class A1, class A2, class A3, class A4 >
361 static postconstructor_invoker<T> deconstruct( A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4 )
362 {
363 boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::deconstruct_deleter< T >() );
364
365 detail::deconstruct_deleter< T > * pd = boost::get_deleter< detail::deconstruct_deleter< T > >( pt );
366
367 void * pv = pd->address();
368
369 new( pv ) T( a1, a2, a3, a4 );
370 pd->set_initialized();
371
372 boost::shared_ptr< T > retval( pt, static_cast< T* >( pv ) );
373 boost::detail::sp_enable_shared_from_this(&retval, retval.get(), retval.get());
374 return retval;
375 }
376
377 template< class T, class A1, class A2, class A3, class A4, class A5 >
378 static postconstructor_invoker<T> deconstruct( A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4, A5 const & a5 )
379 {
380 boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::deconstruct_deleter< T >() );
381
382 detail::deconstruct_deleter< T > * pd = boost::get_deleter< detail::deconstruct_deleter< T > >( pt );
383
384 void * pv = pd->address();
385
386 new( pv ) T( a1, a2, a3, a4, a5 );
387 pd->set_initialized();
388
389 boost::shared_ptr< T > retval( pt, static_cast< T* >( pv ) );
390 boost::detail::sp_enable_shared_from_this(&retval, retval.get(), retval.get());
391 return retval;
392 }
393
394 template< class T, class A1, class A2, class A3, class A4, class A5, class A6 >
395 static postconstructor_invoker<T> deconstruct( A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4, A5 const & a5, A6 const & a6 )
396 {
397 boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::deconstruct_deleter< T >() );
398
399 detail::deconstruct_deleter< T > * pd = boost::get_deleter< detail::deconstruct_deleter< T > >( pt );
400
401 void * pv = pd->address();
402
403 new( pv ) T( a1, a2, a3, a4, a5, a6 );
404 pd->set_initialized();
405
406 boost::shared_ptr< T > retval( pt, static_cast< T* >( pv ) );
407 boost::detail::sp_enable_shared_from_this(&retval, retval.get(), retval.get());
408 return retval;
409 }
410
411 template< class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7 >
412 static postconstructor_invoker<T> deconstruct( A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4, A5 const & a5, A6 const & a6, A7 const & a7 )
413 {
414 boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::deconstruct_deleter< T >() );
415
416 detail::deconstruct_deleter< T > * pd = boost::get_deleter< detail::deconstruct_deleter< T > >( pt );
417
418 void * pv = pd->address();
419
420 new( pv ) T( a1, a2, a3, a4, a5, a6, a7 );
421 pd->set_initialized();
422
423 boost::shared_ptr< T > retval( pt, static_cast< T* >( pv ) );
424 boost::detail::sp_enable_shared_from_this(&retval, retval.get(), retval.get());
425 return retval;
426 }
427
428 template< class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8 >
429 static postconstructor_invoker<T> deconstruct( A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4, A5 const & a5, A6 const & a6, A7 const & a7, A8 const & a8 )
430 {
431 boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::deconstruct_deleter< T >() );
432
433 detail::deconstruct_deleter< T > * pd = boost::get_deleter< detail::deconstruct_deleter< T > >( pt );
434
435 void * pv = pd->address();
436
437 new( pv ) T( a1, a2, a3, a4, a5, a6, a7, a8 );
438 pd->set_initialized();
439
440 boost::shared_ptr< T > retval( pt, static_cast< T* >( pv ) );
441 boost::detail::sp_enable_shared_from_this(&retval, retval.get(), retval.get());
442 return retval;
443 }
444
445 template< class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9 >
446 static postconstructor_invoker<T> deconstruct( A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4, A5 const & a5, A6 const & a6, A7 const & a7, A8 const & a8, A9 const & a9 )
447 {
448 boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::deconstruct_deleter< T >() );
449
450 detail::deconstruct_deleter< T > * pd = boost::get_deleter< detail::deconstruct_deleter< T > >( pt );
451
452 void * pv = pd->address();
453
454 new( pv ) T( a1, a2, a3, a4, a5, a6, a7, a8, a9 );
455 pd->set_initialized();
456
457 boost::shared_ptr< T > retval( pt, static_cast< T* >( pv ) );
458 boost::detail::sp_enable_shared_from_this(&retval, retval.get(), retval.get());
459 return retval;
460 }
461
462 #endif
463 };
464
465 // Zero-argument versions
466 //
467 // Used even when variadic templates are available because of the new T() vs new T issue
468
469 template< class T > postconstructor_invoker<T> deconstruct()
470 {
471 return deconstruct_access::deconstruct<T>();
472 }
473
474 #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
475
476 // Variadic templates, rvalue reference
477
478 template< class T, class... Args > postconstructor_invoker< T > deconstruct( Args && ... args )
479 {
480 return deconstruct_access::deconstruct<T>( std::forward<Args>( args )... );
481 }
482
483 #else
484
485 // C++03 version
486
487 template< class T, class A1 >
488 postconstructor_invoker<T> deconstruct( A1 const & a1 )
489 {
490 return deconstruct_access::deconstruct<T>(a1);
491 }
492
493 template< class T, class A1, class A2 >
494 postconstructor_invoker<T> deconstruct( A1 const & a1, A2 const & a2 )
495 {
496 return deconstruct_access::deconstruct<T>(a1,a2);
497 }
498
499 template< class T, class A1, class A2, class A3 >
500 postconstructor_invoker<T> deconstruct( A1 const & a1, A2 const & a2, A3 const & a3 )
501 {
502 return deconstruct_access::deconstruct<T>(a1,a2,a3);
503 }
504
505 template< class T, class A1, class A2, class A3, class A4 >
506 postconstructor_invoker<T> deconstruct( A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4 )
507 {
508 return deconstruct_access::deconstruct<T>(a1,a2,a3,a4);
509 }
510
511 template< class T, class A1, class A2, class A3, class A4, class A5 >
512 postconstructor_invoker<T> deconstruct( A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4, A5 const & a5 )
513 {
514 return deconstruct_access::deconstruct<T>(a1,a2,a3,a4,a5);
515 }
516
517 template< class T, class A1, class A2, class A3, class A4, class A5, class A6 >
518 postconstructor_invoker<T> deconstruct( A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4, A5 const & a5, A6 const & a6 )
519 {
520 return deconstruct_access::deconstruct<T>(a1,a2,a3,a4,a5,a6);
521 }
522
523 template< class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7 >
524 postconstructor_invoker<T> deconstruct( A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4, A5 const & a5, A6 const & a6, A7 const & a7 )
525 {
526 return deconstruct_access::deconstruct<T>(a1,a2,a3,a4,a5,a6,a7);
527 }
528
529 template< class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8 >
530 postconstructor_invoker<T> deconstruct( A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4, A5 const & a5, A6 const & a6, A7 const & a7, A8 const & a8 )
531 {
532 return deconstruct_access::deconstruct<T>(a1,a2,a3,a4,a5,a6,a7,a8);
533 }
534
535 template< class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9 >
536 postconstructor_invoker<T> deconstruct( A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4, A5 const & a5, A6 const & a6, A7 const & a7, A8 const & a8, A9 const & a9 )
537 {
538 return deconstruct_access::deconstruct<T>(a1,a2,a3,a4,a5,a6,a7,a8,a9);
539 }
540
541 #endif
542
543 } // namespace signals2
544 } // namespace boost
545
546 #endif // #ifndef BOOST_SIGNALS2_DECONSTRUCT_HPP