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