shared_count.hpp 12 KB

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