shared_count.hpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668
  1. #ifndef BOOST_SMART_PTR_DETAIL_SHARED_COUNT_HPP_INCLUDED
  2. #define BOOST_SMART_PTR_DETAIL_SHARED_COUNT_HPP_INCLUDED
  3. // MS compatible compilers support #pragma once
  4. #if defined(_MSC_VER) && (_MSC_VER >= 1020)
  5. # pragma once
  6. #endif
  7. //
  8. // detail/shared_count.hpp
  9. //
  10. // Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd.
  11. // Copyright 2004-2005 Peter Dimov
  12. //
  13. // Distributed under the Boost Software License, Version 1.0. (See
  14. // accompanying file LICENSE_1_0.txt or copy at
  15. // http://www.boost.org/LICENSE_1_0.txt)
  16. //
  17. #ifdef __BORLANDC__
  18. # pragma warn -8027 // Functions containing try are not expanded inline
  19. #endif
  20. #include <boost/config.hpp>
  21. #include <boost/checked_delete.hpp>
  22. #include <boost/throw_exception.hpp>
  23. #include <boost/smart_ptr/bad_weak_ptr.hpp>
  24. #include <boost/smart_ptr/detail/sp_counted_base.hpp>
  25. #include <boost/smart_ptr/detail/sp_counted_impl.hpp>
  26. #include <boost/smart_ptr/detail/sp_disable_deprecated.hpp>
  27. #include <boost/smart_ptr/detail/sp_noexcept.hpp>
  28. #include <boost/config/workaround.hpp>
  29. // In order to avoid circular dependencies with Boost.TR1
  30. // we make sure that our include of <memory> doesn't try to
  31. // pull in the TR1 headers: that's why we use this header
  32. // rather than including <memory> directly:
  33. #include <boost/config/no_tr1/memory.hpp> // std::auto_ptr
  34. #include <functional> // std::less
  35. #ifdef BOOST_NO_EXCEPTIONS
  36. # include <new> // std::bad_alloc
  37. #endif
  38. #include <boost/core/addressof.hpp>
  39. #if defined( BOOST_SP_DISABLE_DEPRECATED )
  40. #pragma GCC diagnostic push
  41. #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
  42. #endif
  43. namespace boost
  44. {
  45. namespace movelib
  46. {
  47. template< class T, class D > class unique_ptr;
  48. } // namespace movelib
  49. namespace detail
  50. {
  51. #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
  52. int const shared_count_id = 0x2C35F101;
  53. int const weak_count_id = 0x298C38A4;
  54. #endif
  55. struct sp_nothrow_tag {};
  56. template< class D > struct sp_inplace_tag
  57. {
  58. };
  59. template< class T > class sp_reference_wrapper
  60. {
  61. public:
  62. explicit sp_reference_wrapper( T & t): t_( boost::addressof( t ) )
  63. {
  64. }
  65. template< class Y > void operator()( Y * p ) const
  66. {
  67. (*t_)( p );
  68. }
  69. private:
  70. T * t_;
  71. };
  72. template< class D > struct sp_convert_reference
  73. {
  74. typedef D type;
  75. };
  76. template< class D > struct sp_convert_reference< D& >
  77. {
  78. typedef sp_reference_wrapper< D > type;
  79. };
  80. class weak_count;
  81. class shared_count
  82. {
  83. private:
  84. sp_counted_base * pi_;
  85. #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
  86. int id_;
  87. #endif
  88. friend class weak_count;
  89. public:
  90. BOOST_CONSTEXPR shared_count() BOOST_SP_NOEXCEPT: pi_(0)
  91. #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
  92. , id_(shared_count_id)
  93. #endif
  94. {
  95. }
  96. BOOST_CONSTEXPR explicit shared_count( sp_counted_base * pi ) BOOST_SP_NOEXCEPT: pi_( pi )
  97. #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
  98. , id_(shared_count_id)
  99. #endif
  100. {
  101. }
  102. template<class Y> explicit shared_count( Y * p ): pi_( 0 )
  103. #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
  104. , id_(shared_count_id)
  105. #endif
  106. {
  107. #ifndef BOOST_NO_EXCEPTIONS
  108. try
  109. {
  110. pi_ = new sp_counted_impl_p<Y>( p );
  111. }
  112. catch(...)
  113. {
  114. boost::checked_delete( p );
  115. throw;
  116. }
  117. #else
  118. pi_ = new sp_counted_impl_p<Y>( p );
  119. if( pi_ == 0 )
  120. {
  121. boost::checked_delete( p );
  122. boost::throw_exception( std::bad_alloc() );
  123. }
  124. #endif
  125. }
  126. #if defined( BOOST_MSVC ) && BOOST_WORKAROUND( BOOST_MSVC, <= 1200 )
  127. template<class Y, class D> shared_count( Y * p, D d ): pi_(0)
  128. #else
  129. template<class P, class D> shared_count( P p, D d ): pi_(0)
  130. #endif
  131. #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
  132. , id_(shared_count_id)
  133. #endif
  134. {
  135. #if defined( BOOST_MSVC ) && BOOST_WORKAROUND( BOOST_MSVC, <= 1200 )
  136. typedef Y* P;
  137. #endif
  138. #ifndef BOOST_NO_EXCEPTIONS
  139. try
  140. {
  141. pi_ = new sp_counted_impl_pd<P, D>(p, d);
  142. }
  143. catch(...)
  144. {
  145. d(p); // delete p
  146. throw;
  147. }
  148. #else
  149. pi_ = new sp_counted_impl_pd<P, D>(p, d);
  150. if(pi_ == 0)
  151. {
  152. d(p); // delete p
  153. boost::throw_exception(std::bad_alloc());
  154. }
  155. #endif
  156. }
  157. #if !defined( BOOST_NO_FUNCTION_TEMPLATE_ORDERING )
  158. template< class P, class D > shared_count( P p, sp_inplace_tag<D> ): pi_( 0 )
  159. #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
  160. , id_(shared_count_id)
  161. #endif
  162. {
  163. #ifndef BOOST_NO_EXCEPTIONS
  164. try
  165. {
  166. pi_ = new sp_counted_impl_pd< P, D >( p );
  167. }
  168. catch( ... )
  169. {
  170. D::operator_fn( p ); // delete p
  171. throw;
  172. }
  173. #else
  174. pi_ = new sp_counted_impl_pd< P, D >( p );
  175. if( pi_ == 0 )
  176. {
  177. D::operator_fn( p ); // delete p
  178. boost::throw_exception( std::bad_alloc() );
  179. }
  180. #endif // #ifndef BOOST_NO_EXCEPTIONS
  181. }
  182. #endif // !defined( BOOST_NO_FUNCTION_TEMPLATE_ORDERING )
  183. template<class P, class D, class A> shared_count( P p, D d, A a ): pi_( 0 )
  184. #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
  185. , id_(shared_count_id)
  186. #endif
  187. {
  188. typedef sp_counted_impl_pda<P, D, A> impl_type;
  189. #if !defined( BOOST_NO_CXX11_ALLOCATOR )
  190. typedef typename std::allocator_traits<A>::template rebind_alloc< impl_type > A2;
  191. #else
  192. typedef typename A::template rebind< impl_type >::other A2;
  193. #endif
  194. A2 a2( a );
  195. #ifndef BOOST_NO_EXCEPTIONS
  196. try
  197. {
  198. pi_ = a2.allocate( 1 );
  199. ::new( static_cast< void* >( pi_ ) ) impl_type( p, d, a );
  200. }
  201. catch(...)
  202. {
  203. d( p );
  204. if( pi_ != 0 )
  205. {
  206. a2.deallocate( static_cast< impl_type* >( pi_ ), 1 );
  207. }
  208. throw;
  209. }
  210. #else
  211. pi_ = a2.allocate( 1 );
  212. if( pi_ != 0 )
  213. {
  214. ::new( static_cast< void* >( pi_ ) ) impl_type( p, d, a );
  215. }
  216. else
  217. {
  218. d( p );
  219. boost::throw_exception( std::bad_alloc() );
  220. }
  221. #endif
  222. }
  223. #if !defined( BOOST_NO_FUNCTION_TEMPLATE_ORDERING )
  224. template< class P, class D, class A > shared_count( P p, sp_inplace_tag< D >, A a ): pi_( 0 )
  225. #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
  226. , id_(shared_count_id)
  227. #endif
  228. {
  229. typedef sp_counted_impl_pda< P, D, A > impl_type;
  230. #if !defined( BOOST_NO_CXX11_ALLOCATOR )
  231. typedef typename std::allocator_traits<A>::template rebind_alloc< impl_type > A2;
  232. #else
  233. typedef typename A::template rebind< impl_type >::other A2;
  234. #endif
  235. A2 a2( a );
  236. #ifndef BOOST_NO_EXCEPTIONS
  237. try
  238. {
  239. pi_ = a2.allocate( 1 );
  240. ::new( static_cast< void* >( pi_ ) ) impl_type( p, a );
  241. }
  242. catch(...)
  243. {
  244. D::operator_fn( p );
  245. if( pi_ != 0 )
  246. {
  247. a2.deallocate( static_cast< impl_type* >( pi_ ), 1 );
  248. }
  249. throw;
  250. }
  251. #else
  252. pi_ = a2.allocate( 1 );
  253. if( pi_ != 0 )
  254. {
  255. ::new( static_cast< void* >( pi_ ) ) impl_type( p, a );
  256. }
  257. else
  258. {
  259. D::operator_fn( p );
  260. boost::throw_exception( std::bad_alloc() );
  261. }
  262. #endif // #ifndef BOOST_NO_EXCEPTIONS
  263. }
  264. #endif // !defined( BOOST_NO_FUNCTION_TEMPLATE_ORDERING )
  265. #ifndef BOOST_NO_AUTO_PTR
  266. // auto_ptr<Y> is special cased to provide the strong guarantee
  267. template<class Y>
  268. explicit shared_count( std::auto_ptr<Y> & r ): pi_( new sp_counted_impl_p<Y>( r.get() ) )
  269. #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
  270. , id_(shared_count_id)
  271. #endif
  272. {
  273. #ifdef BOOST_NO_EXCEPTIONS
  274. if( pi_ == 0 )
  275. {
  276. boost::throw_exception(std::bad_alloc());
  277. }
  278. #endif
  279. r.release();
  280. }
  281. #endif
  282. #if !defined( BOOST_NO_CXX11_SMART_PTR )
  283. template<class Y, class D>
  284. explicit shared_count( std::unique_ptr<Y, D> & r ): pi_( 0 )
  285. #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
  286. , id_(shared_count_id)
  287. #endif
  288. {
  289. typedef typename sp_convert_reference<D>::type D2;
  290. D2 d2( r.get_deleter() );
  291. pi_ = new sp_counted_impl_pd< typename std::unique_ptr<Y, D>::pointer, D2 >( r.get(), d2 );
  292. #ifdef BOOST_NO_EXCEPTIONS
  293. if( pi_ == 0 )
  294. {
  295. boost::throw_exception( std::bad_alloc() );
  296. }
  297. #endif
  298. r.release();
  299. }
  300. #endif
  301. template<class Y, class D>
  302. explicit shared_count( boost::movelib::unique_ptr<Y, D> & r ): pi_( 0 )
  303. #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
  304. , id_(shared_count_id)
  305. #endif
  306. {
  307. typedef typename sp_convert_reference<D>::type D2;
  308. D2 d2( r.get_deleter() );
  309. pi_ = new sp_counted_impl_pd< typename boost::movelib::unique_ptr<Y, D>::pointer, D2 >( r.get(), d2 );
  310. #ifdef BOOST_NO_EXCEPTIONS
  311. if( pi_ == 0 )
  312. {
  313. boost::throw_exception( std::bad_alloc() );
  314. }
  315. #endif
  316. r.release();
  317. }
  318. ~shared_count() /*BOOST_SP_NOEXCEPT*/
  319. {
  320. if( pi_ != 0 ) pi_->release();
  321. #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
  322. id_ = 0;
  323. #endif
  324. }
  325. shared_count(shared_count const & r) BOOST_SP_NOEXCEPT: pi_(r.pi_)
  326. #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
  327. , id_(shared_count_id)
  328. #endif
  329. {
  330. if( pi_ != 0 ) pi_->add_ref_copy();
  331. }
  332. #if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
  333. shared_count(shared_count && r) BOOST_SP_NOEXCEPT: pi_(r.pi_)
  334. #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
  335. , id_(shared_count_id)
  336. #endif
  337. {
  338. r.pi_ = 0;
  339. }
  340. #endif
  341. explicit shared_count(weak_count const & r); // throws bad_weak_ptr when r.use_count() == 0
  342. shared_count( weak_count const & r, sp_nothrow_tag ) BOOST_SP_NOEXCEPT; // constructs an empty *this when r.use_count() == 0
  343. shared_count & operator= (shared_count const & r) BOOST_SP_NOEXCEPT
  344. {
  345. sp_counted_base * tmp = r.pi_;
  346. if( tmp != pi_ )
  347. {
  348. if( tmp != 0 ) tmp->add_ref_copy();
  349. if( pi_ != 0 ) pi_->release();
  350. pi_ = tmp;
  351. }
  352. return *this;
  353. }
  354. void swap(shared_count & r) BOOST_SP_NOEXCEPT
  355. {
  356. sp_counted_base * tmp = r.pi_;
  357. r.pi_ = pi_;
  358. pi_ = tmp;
  359. }
  360. long use_count() const BOOST_SP_NOEXCEPT
  361. {
  362. return pi_ != 0? pi_->use_count(): 0;
  363. }
  364. bool unique() const BOOST_SP_NOEXCEPT
  365. {
  366. return use_count() == 1;
  367. }
  368. bool empty() const BOOST_SP_NOEXCEPT
  369. {
  370. return pi_ == 0;
  371. }
  372. friend inline bool operator==(shared_count const & a, shared_count const & b) BOOST_SP_NOEXCEPT
  373. {
  374. return a.pi_ == b.pi_;
  375. }
  376. friend inline bool operator<(shared_count const & a, shared_count const & b) BOOST_SP_NOEXCEPT
  377. {
  378. return std::less<sp_counted_base *>()( a.pi_, b.pi_ );
  379. }
  380. void * get_deleter( sp_typeinfo_ const & ti ) const BOOST_SP_NOEXCEPT
  381. {
  382. return pi_? pi_->get_deleter( ti ): 0;
  383. }
  384. void * get_local_deleter( sp_typeinfo_ const & ti ) const BOOST_SP_NOEXCEPT
  385. {
  386. return pi_? pi_->get_local_deleter( ti ): 0;
  387. }
  388. void * get_untyped_deleter() const BOOST_SP_NOEXCEPT
  389. {
  390. return pi_? pi_->get_untyped_deleter(): 0;
  391. }
  392. };
  393. class weak_count
  394. {
  395. private:
  396. sp_counted_base * pi_;
  397. #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
  398. int id_;
  399. #endif
  400. friend class shared_count;
  401. public:
  402. BOOST_CONSTEXPR weak_count() BOOST_SP_NOEXCEPT: pi_(0)
  403. #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
  404. , id_(weak_count_id)
  405. #endif
  406. {
  407. }
  408. weak_count(shared_count const & r) BOOST_SP_NOEXCEPT: pi_(r.pi_)
  409. #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
  410. , id_(weak_count_id)
  411. #endif
  412. {
  413. if(pi_ != 0) pi_->weak_add_ref();
  414. }
  415. weak_count(weak_count const & r) BOOST_SP_NOEXCEPT: pi_(r.pi_)
  416. #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
  417. , id_(weak_count_id)
  418. #endif
  419. {
  420. if(pi_ != 0) pi_->weak_add_ref();
  421. }
  422. // Move support
  423. #if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
  424. weak_count(weak_count && r) BOOST_SP_NOEXCEPT: pi_(r.pi_)
  425. #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
  426. , id_(weak_count_id)
  427. #endif
  428. {
  429. r.pi_ = 0;
  430. }
  431. #endif
  432. ~weak_count() /*BOOST_SP_NOEXCEPT*/
  433. {
  434. if(pi_ != 0) pi_->weak_release();
  435. #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
  436. id_ = 0;
  437. #endif
  438. }
  439. weak_count & operator= (shared_count const & r) BOOST_SP_NOEXCEPT
  440. {
  441. sp_counted_base * tmp = r.pi_;
  442. if( tmp != pi_ )
  443. {
  444. if(tmp != 0) tmp->weak_add_ref();
  445. if(pi_ != 0) pi_->weak_release();
  446. pi_ = tmp;
  447. }
  448. return *this;
  449. }
  450. weak_count & operator= (weak_count const & r) BOOST_SP_NOEXCEPT
  451. {
  452. sp_counted_base * tmp = r.pi_;
  453. if( tmp != pi_ )
  454. {
  455. if(tmp != 0) tmp->weak_add_ref();
  456. if(pi_ != 0) pi_->weak_release();
  457. pi_ = tmp;
  458. }
  459. return *this;
  460. }
  461. void swap(weak_count & r) BOOST_SP_NOEXCEPT
  462. {
  463. sp_counted_base * tmp = r.pi_;
  464. r.pi_ = pi_;
  465. pi_ = tmp;
  466. }
  467. long use_count() const BOOST_SP_NOEXCEPT
  468. {
  469. return pi_ != 0? pi_->use_count(): 0;
  470. }
  471. bool empty() const BOOST_SP_NOEXCEPT
  472. {
  473. return pi_ == 0;
  474. }
  475. friend inline bool operator==(weak_count const & a, weak_count const & b) BOOST_SP_NOEXCEPT
  476. {
  477. return a.pi_ == b.pi_;
  478. }
  479. friend inline bool operator<(weak_count const & a, weak_count const & b) BOOST_SP_NOEXCEPT
  480. {
  481. return std::less<sp_counted_base *>()(a.pi_, b.pi_);
  482. }
  483. };
  484. inline shared_count::shared_count( weak_count const & r ): pi_( r.pi_ )
  485. #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
  486. , id_(shared_count_id)
  487. #endif
  488. {
  489. if( pi_ == 0 || !pi_->add_ref_lock() )
  490. {
  491. boost::throw_exception( boost::bad_weak_ptr() );
  492. }
  493. }
  494. inline shared_count::shared_count( weak_count const & r, sp_nothrow_tag ) BOOST_SP_NOEXCEPT: pi_( r.pi_ )
  495. #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
  496. , id_(shared_count_id)
  497. #endif
  498. {
  499. if( pi_ != 0 && !pi_->add_ref_lock() )
  500. {
  501. pi_ = 0;
  502. }
  503. }
  504. } // namespace detail
  505. } // namespace boost
  506. #if defined( BOOST_SP_DISABLE_DEPRECATED )
  507. #pragma GCC diagnostic pop
  508. #endif
  509. #ifdef __BORLANDC__
  510. # pragma warn .8027 // Functions containing try are not expanded inline
  511. #endif
  512. #endif // #ifndef BOOST_SMART_PTR_DETAIL_SHARED_COUNT_HPP_INCLUDED