deconstruct.hpp 19 KB

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