shared_ptr.hpp 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035
  1. #ifndef BOOST_SMART_PTR_SHARED_PTR_HPP_INCLUDED
  2. #define BOOST_SMART_PTR_SHARED_PTR_HPP_INCLUDED
  3. //
  4. // shared_ptr.hpp
  5. //
  6. // (C) Copyright Greg Colvin and Beman Dawes 1998, 1999.
  7. // Copyright (c) 2001-2008 Peter Dimov
  8. //
  9. // Distributed under the Boost Software License, Version 1.0. (See
  10. // accompanying file LICENSE_1_0.txt or copy at
  11. // http://www.boost.org/LICENSE_1_0.txt)
  12. //
  13. // See http://www.boost.org/libs/smart_ptr/shared_ptr.htm for documentation.
  14. //
  15. #include <boost/config.hpp> // for broken compiler workarounds
  16. #if defined(BOOST_NO_MEMBER_TEMPLATES) && !defined(BOOST_MSVC6_MEMBER_TEMPLATES)
  17. #include <boost/smart_ptr/detail/shared_ptr_nmt.hpp>
  18. #else
  19. // In order to avoid circular dependencies with Boost.TR1
  20. // we make sure that our include of <memory> doesn't try to
  21. // pull in the TR1 headers: that's why we use this header
  22. // rather than including <memory> directly:
  23. #include <boost/config/no_tr1/memory.hpp> // std::auto_ptr
  24. #include <boost/assert.hpp>
  25. #include <boost/checked_delete.hpp>
  26. #include <boost/throw_exception.hpp>
  27. #include <boost/smart_ptr/detail/shared_count.hpp>
  28. #include <boost/detail/workaround.hpp>
  29. #include <boost/smart_ptr/detail/sp_convertible.hpp>
  30. #include <boost/smart_ptr/detail/sp_nullptr_t.hpp>
  31. #if !defined(BOOST_SP_NO_ATOMIC_ACCESS)
  32. #include <boost/smart_ptr/detail/spinlock_pool.hpp>
  33. #include <boost/memory_order.hpp>
  34. #endif
  35. #include <algorithm> // for std::swap
  36. #include <functional> // for std::less
  37. #include <typeinfo> // for std::bad_cast
  38. #include <cstddef> // for std::size_t
  39. #if !defined(BOOST_NO_IOSTREAM)
  40. #if !defined(BOOST_NO_IOSFWD)
  41. #include <iosfwd> // for std::basic_ostream
  42. #else
  43. #include <ostream>
  44. #endif
  45. #endif
  46. namespace boost
  47. {
  48. template<class T> class shared_ptr;
  49. template<class T> class weak_ptr;
  50. template<class T> class enable_shared_from_this;
  51. class enable_shared_from_raw;
  52. namespace detail
  53. {
  54. // sp_element, element_type
  55. template< class T > struct sp_element
  56. {
  57. typedef T type;
  58. };
  59. #if !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
  60. template< class T > struct sp_element< T[] >
  61. {
  62. typedef T type;
  63. };
  64. #if !defined( __BORLANDC__ ) || !BOOST_WORKAROUND( __BORLANDC__, < 0x600 )
  65. template< class T, std::size_t N > struct sp_element< T[N] >
  66. {
  67. typedef T type;
  68. };
  69. #endif
  70. #endif // !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
  71. // sp_dereference, return type of operator*
  72. template< class T > struct sp_dereference
  73. {
  74. typedef T & type;
  75. };
  76. template<> struct sp_dereference< void >
  77. {
  78. typedef void type;
  79. };
  80. #if !defined(BOOST_NO_CV_VOID_SPECIALIZATIONS)
  81. template<> struct sp_dereference< void const >
  82. {
  83. typedef void type;
  84. };
  85. template<> struct sp_dereference< void volatile >
  86. {
  87. typedef void type;
  88. };
  89. template<> struct sp_dereference< void const volatile >
  90. {
  91. typedef void type;
  92. };
  93. #endif // !defined(BOOST_NO_CV_VOID_SPECIALIZATIONS)
  94. #if !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
  95. template< class T > struct sp_dereference< T[] >
  96. {
  97. typedef void type;
  98. };
  99. #if !defined( __BORLANDC__ ) || !BOOST_WORKAROUND( __BORLANDC__, < 0x600 )
  100. template< class T, std::size_t N > struct sp_dereference< T[N] >
  101. {
  102. typedef void type;
  103. };
  104. #endif
  105. #endif // !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
  106. // sp_member_access, return type of operator->
  107. template< class T > struct sp_member_access
  108. {
  109. typedef T * type;
  110. };
  111. #if !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
  112. template< class T > struct sp_member_access< T[] >
  113. {
  114. typedef void type;
  115. };
  116. #if !defined( __BORLANDC__ ) || !BOOST_WORKAROUND( __BORLANDC__, < 0x600 )
  117. template< class T, std::size_t N > struct sp_member_access< T[N] >
  118. {
  119. typedef void type;
  120. };
  121. #endif
  122. #endif // !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
  123. // sp_array_access, return type of operator[]
  124. template< class T > struct sp_array_access
  125. {
  126. typedef void type;
  127. };
  128. #if !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
  129. template< class T > struct sp_array_access< T[] >
  130. {
  131. typedef T & type;
  132. };
  133. #if !defined( __BORLANDC__ ) || !BOOST_WORKAROUND( __BORLANDC__, < 0x600 )
  134. template< class T, std::size_t N > struct sp_array_access< T[N] >
  135. {
  136. typedef T & type;
  137. };
  138. #endif
  139. #endif // !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
  140. // sp_extent, for operator[] index check
  141. template< class T > struct sp_extent
  142. {
  143. enum _vt { value = 0 };
  144. };
  145. #if !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
  146. template< class T, std::size_t N > struct sp_extent< T[N] >
  147. {
  148. enum _vt { value = N };
  149. };
  150. #endif // !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
  151. // enable_shared_from_this support
  152. template< class X, class Y, class T > inline void sp_enable_shared_from_this( boost::shared_ptr<X> const * ppx, Y const * py, boost::enable_shared_from_this< T > const * pe )
  153. {
  154. if( pe != 0 )
  155. {
  156. pe->_internal_accept_owner( ppx, const_cast< Y* >( py ) );
  157. }
  158. }
  159. template< class X, class Y > inline void sp_enable_shared_from_this( boost::shared_ptr<X> * ppx, Y const * py, boost::enable_shared_from_raw const * pe );
  160. #ifdef _MANAGED
  161. // Avoid C4793, ... causes native code generation
  162. struct sp_any_pointer
  163. {
  164. template<class T> sp_any_pointer( T* ) {}
  165. };
  166. inline void sp_enable_shared_from_this( sp_any_pointer, sp_any_pointer, sp_any_pointer )
  167. {
  168. }
  169. #else // _MANAGED
  170. inline void sp_enable_shared_from_this( ... )
  171. {
  172. }
  173. #endif // _MANAGED
  174. #if !defined( BOOST_NO_SFINAE ) && !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION ) && !defined( BOOST_NO_AUTO_PTR )
  175. // rvalue auto_ptr support based on a technique by Dave Abrahams
  176. template< class T, class R > struct sp_enable_if_auto_ptr
  177. {
  178. };
  179. template< class T, class R > struct sp_enable_if_auto_ptr< std::auto_ptr< T >, R >
  180. {
  181. typedef R type;
  182. };
  183. #endif
  184. // sp_assert_convertible
  185. template< class Y, class T > inline void sp_assert_convertible()
  186. {
  187. #if !defined( BOOST_SP_NO_SP_CONVERTIBLE )
  188. // static_assert( sp_convertible< Y, T >::value );
  189. typedef char tmp[ sp_convertible< Y, T >::value? 1: -1 ];
  190. (void)sizeof( tmp );
  191. #else
  192. T* p = static_cast< Y* >( 0 );
  193. (void)p;
  194. #endif
  195. }
  196. // pointer constructor helper
  197. template< class T, class Y > inline void sp_pointer_construct( boost::shared_ptr< T > * ppx, Y * p, boost::detail::shared_count & pn )
  198. {
  199. boost::detail::shared_count( p ).swap( pn );
  200. boost::detail::sp_enable_shared_from_this( ppx, p, p );
  201. }
  202. #if !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
  203. template< class T, class Y > inline void sp_pointer_construct( boost::shared_ptr< T[] > * /*ppx*/, Y * p, boost::detail::shared_count & pn )
  204. {
  205. sp_assert_convertible< Y[], T[] >();
  206. boost::detail::shared_count( p, boost::checked_array_deleter< T >() ).swap( pn );
  207. }
  208. template< class T, std::size_t N, class Y > inline void sp_pointer_construct( boost::shared_ptr< T[N] > * /*ppx*/, Y * p, boost::detail::shared_count & pn )
  209. {
  210. sp_assert_convertible< Y[N], T[N] >();
  211. boost::detail::shared_count( p, boost::checked_array_deleter< T >() ).swap( pn );
  212. }
  213. #endif // !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
  214. // deleter constructor helper
  215. template< class T, class Y > inline void sp_deleter_construct( boost::shared_ptr< T > * ppx, Y * p )
  216. {
  217. boost::detail::sp_enable_shared_from_this( ppx, p, p );
  218. }
  219. #if !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
  220. template< class T, class Y > inline void sp_deleter_construct( boost::shared_ptr< T[] > * /*ppx*/, Y * /*p*/ )
  221. {
  222. sp_assert_convertible< Y[], T[] >();
  223. }
  224. template< class T, std::size_t N, class Y > inline void sp_deleter_construct( boost::shared_ptr< T[N] > * /*ppx*/, Y * /*p*/ )
  225. {
  226. sp_assert_convertible< Y[N], T[N] >();
  227. }
  228. #endif // !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
  229. } // namespace detail
  230. //
  231. // shared_ptr
  232. //
  233. // An enhanced relative of scoped_ptr with reference counted copy semantics.
  234. // The object pointed to is deleted when the last shared_ptr pointing to it
  235. // is destroyed or reset.
  236. //
  237. template<class T> class shared_ptr
  238. {
  239. private:
  240. // Borland 5.5.1 specific workaround
  241. typedef shared_ptr<T> this_type;
  242. public:
  243. typedef typename boost::detail::sp_element< T >::type element_type;
  244. shared_ptr() BOOST_NOEXCEPT : px( 0 ), pn() // never throws in 1.30+
  245. {
  246. }
  247. #if !defined( BOOST_NO_CXX11_NULLPTR )
  248. shared_ptr( boost::detail::sp_nullptr_t ) BOOST_NOEXCEPT : px( 0 ), pn() // never throws
  249. {
  250. }
  251. #endif
  252. template<class Y>
  253. explicit shared_ptr( Y * p ): px( p ), pn() // Y must be complete
  254. {
  255. boost::detail::sp_pointer_construct( this, p, pn );
  256. }
  257. //
  258. // Requirements: D's copy constructor must not throw
  259. //
  260. // shared_ptr will release p by calling d(p)
  261. //
  262. template<class Y, class D> shared_ptr( Y * p, D d ): px( p ), pn( p, d )
  263. {
  264. boost::detail::sp_deleter_construct( this, p );
  265. }
  266. #if !defined( BOOST_NO_CXX11_NULLPTR )
  267. template<class D> shared_ptr( boost::detail::sp_nullptr_t p, D d ): px( p ), pn( p, d )
  268. {
  269. }
  270. #endif
  271. // As above, but with allocator. A's copy constructor shall not throw.
  272. template<class Y, class D, class A> shared_ptr( Y * p, D d, A a ): px( p ), pn( p, d, a )
  273. {
  274. boost::detail::sp_deleter_construct( this, p );
  275. }
  276. #if !defined( BOOST_NO_CXX11_NULLPTR )
  277. template<class D, class A> shared_ptr( boost::detail::sp_nullptr_t p, D d, A a ): px( p ), pn( p, d, a )
  278. {
  279. }
  280. #endif
  281. // generated copy constructor, destructor are fine...
  282. #if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
  283. // ... except in C++0x, move disables the implicit copy
  284. shared_ptr( shared_ptr const & r ) BOOST_NOEXCEPT : px( r.px ), pn( r.pn )
  285. {
  286. }
  287. #endif
  288. template<class Y>
  289. explicit shared_ptr( weak_ptr<Y> const & r ): pn( r.pn ) // may throw
  290. {
  291. boost::detail::sp_assert_convertible< Y, T >();
  292. // it is now safe to copy r.px, as pn(r.pn) did not throw
  293. px = r.px;
  294. }
  295. template<class Y>
  296. shared_ptr( weak_ptr<Y> const & r, boost::detail::sp_nothrow_tag )
  297. BOOST_NOEXCEPT : px( 0 ), pn( r.pn, boost::detail::sp_nothrow_tag() )
  298. {
  299. if( !pn.empty() )
  300. {
  301. px = r.px;
  302. }
  303. }
  304. template<class Y>
  305. #if !defined( BOOST_SP_NO_SP_CONVERTIBLE )
  306. shared_ptr( shared_ptr<Y> const & r, typename boost::detail::sp_enable_if_convertible<Y,T>::type = boost::detail::sp_empty() )
  307. #else
  308. shared_ptr( shared_ptr<Y> const & r )
  309. #endif
  310. BOOST_NOEXCEPT : px( r.px ), pn( r.pn )
  311. {
  312. boost::detail::sp_assert_convertible< Y, T >();
  313. }
  314. // aliasing
  315. template< class Y >
  316. shared_ptr( shared_ptr<Y> const & r, element_type * p ) BOOST_NOEXCEPT : px( p ), pn( r.pn )
  317. {
  318. }
  319. #ifndef BOOST_NO_AUTO_PTR
  320. template<class Y>
  321. explicit shared_ptr( std::auto_ptr<Y> & r ): px(r.get()), pn()
  322. {
  323. boost::detail::sp_assert_convertible< Y, T >();
  324. Y * tmp = r.get();
  325. pn = boost::detail::shared_count( r );
  326. boost::detail::sp_deleter_construct( this, tmp );
  327. }
  328. #if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
  329. template<class Y>
  330. shared_ptr( std::auto_ptr<Y> && r ): px(r.get()), pn()
  331. {
  332. boost::detail::sp_assert_convertible< Y, T >();
  333. Y * tmp = r.get();
  334. pn = boost::detail::shared_count( r );
  335. boost::detail::sp_deleter_construct( this, tmp );
  336. }
  337. #elif !defined( BOOST_NO_SFINAE ) && !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
  338. template<class Ap>
  339. explicit shared_ptr( Ap r, typename boost::detail::sp_enable_if_auto_ptr<Ap, int>::type = 0 ): px( r.get() ), pn()
  340. {
  341. typedef typename Ap::element_type Y;
  342. boost::detail::sp_assert_convertible< Y, T >();
  343. Y * tmp = r.get();
  344. pn = boost::detail::shared_count( r );
  345. boost::detail::sp_deleter_construct( this, tmp );
  346. }
  347. #endif // BOOST_NO_SFINAE, BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
  348. #endif // BOOST_NO_AUTO_PTR
  349. #if !defined( BOOST_NO_CXX11_SMART_PTR ) && !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
  350. template< class Y, class D >
  351. shared_ptr( std::unique_ptr< Y, D > && r ): px( r.get() ), pn()
  352. {
  353. boost::detail::sp_assert_convertible< Y, T >();
  354. typename std::unique_ptr< Y, D >::pointer tmp = r.get();
  355. pn = boost::detail::shared_count( r );
  356. boost::detail::sp_deleter_construct( this, tmp );
  357. }
  358. #endif
  359. // assignment
  360. shared_ptr & operator=( shared_ptr const & r ) BOOST_NOEXCEPT
  361. {
  362. this_type(r).swap(*this);
  363. return *this;
  364. }
  365. #if !defined(BOOST_MSVC) || (BOOST_MSVC >= 1400)
  366. template<class Y>
  367. shared_ptr & operator=(shared_ptr<Y> const & r) BOOST_NOEXCEPT
  368. {
  369. this_type(r).swap(*this);
  370. return *this;
  371. }
  372. #endif
  373. #ifndef BOOST_NO_AUTO_PTR
  374. template<class Y>
  375. shared_ptr & operator=( std::auto_ptr<Y> & r )
  376. {
  377. this_type( r ).swap( *this );
  378. return *this;
  379. }
  380. #if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
  381. template<class Y>
  382. shared_ptr & operator=( std::auto_ptr<Y> && r )
  383. {
  384. this_type( static_cast< std::auto_ptr<Y> && >( r ) ).swap( *this );
  385. return *this;
  386. }
  387. #elif !defined( BOOST_NO_SFINAE ) && !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
  388. template<class Ap>
  389. typename boost::detail::sp_enable_if_auto_ptr< Ap, shared_ptr & >::type operator=( Ap r )
  390. {
  391. this_type( r ).swap( *this );
  392. return *this;
  393. }
  394. #endif // BOOST_NO_SFINAE, BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
  395. #endif // BOOST_NO_AUTO_PTR
  396. #if !defined( BOOST_NO_CXX11_SMART_PTR ) && !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
  397. template<class Y, class D>
  398. shared_ptr & operator=( std::unique_ptr<Y, D> && r )
  399. {
  400. this_type( static_cast< std::unique_ptr<Y, D> && >( r ) ).swap(*this);
  401. return *this;
  402. }
  403. #endif
  404. // Move support
  405. #if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
  406. shared_ptr( shared_ptr && r ) BOOST_NOEXCEPT : px( r.px ), pn()
  407. {
  408. pn.swap( r.pn );
  409. r.px = 0;
  410. }
  411. template<class Y>
  412. #if !defined( BOOST_SP_NO_SP_CONVERTIBLE )
  413. shared_ptr( shared_ptr<Y> && r, typename boost::detail::sp_enable_if_convertible<Y,T>::type = boost::detail::sp_empty() )
  414. #else
  415. shared_ptr( shared_ptr<Y> && r )
  416. #endif
  417. BOOST_NOEXCEPT : px( r.px ), pn()
  418. {
  419. boost::detail::sp_assert_convertible< Y, T >();
  420. pn.swap( r.pn );
  421. r.px = 0;
  422. }
  423. shared_ptr & operator=( shared_ptr && r ) BOOST_NOEXCEPT
  424. {
  425. this_type( static_cast< shared_ptr && >( r ) ).swap( *this );
  426. return *this;
  427. }
  428. template<class Y>
  429. shared_ptr & operator=( shared_ptr<Y> && r ) BOOST_NOEXCEPT
  430. {
  431. this_type( static_cast< shared_ptr<Y> && >( r ) ).swap( *this );
  432. return *this;
  433. }
  434. #endif
  435. #if !defined( BOOST_NO_CXX11_NULLPTR )
  436. shared_ptr & operator=( boost::detail::sp_nullptr_t ) BOOST_NOEXCEPT // never throws
  437. {
  438. this_type().swap(*this);
  439. return *this;
  440. }
  441. #endif
  442. void reset() BOOST_NOEXCEPT // never throws in 1.30+
  443. {
  444. this_type().swap(*this);
  445. }
  446. template<class Y> void reset( Y * p ) // Y must be complete
  447. {
  448. BOOST_ASSERT( p == 0 || p != px ); // catch self-reset errors
  449. this_type( p ).swap( *this );
  450. }
  451. template<class Y, class D> void reset( Y * p, D d )
  452. {
  453. this_type( p, d ).swap( *this );
  454. }
  455. template<class Y, class D, class A> void reset( Y * p, D d, A a )
  456. {
  457. this_type( p, d, a ).swap( *this );
  458. }
  459. template<class Y> void reset( shared_ptr<Y> const & r, element_type * p )
  460. {
  461. this_type( r, p ).swap( *this );
  462. }
  463. // never throws (but has a BOOST_ASSERT in it, so not marked with BOOST_NOEXCEPT)
  464. typename boost::detail::sp_dereference< T >::type operator* () const
  465. {
  466. BOOST_ASSERT( px != 0 );
  467. return *px;
  468. }
  469. // never throws (but has a BOOST_ASSERT in it, so not marked with BOOST_NOEXCEPT)
  470. typename boost::detail::sp_member_access< T >::type operator-> () const
  471. {
  472. BOOST_ASSERT( px != 0 );
  473. return px;
  474. }
  475. // never throws (but has a BOOST_ASSERT in it, so not marked with BOOST_NOEXCEPT)
  476. typename boost::detail::sp_array_access< T >::type operator[] ( std::ptrdiff_t i ) const
  477. {
  478. BOOST_ASSERT( px != 0 );
  479. BOOST_ASSERT( i >= 0 && ( i < boost::detail::sp_extent< T >::value || boost::detail::sp_extent< T >::value == 0 ) );
  480. return px[ i ];
  481. }
  482. element_type * get() const BOOST_NOEXCEPT
  483. {
  484. return px;
  485. }
  486. // implicit conversion to "bool"
  487. #include <boost/smart_ptr/detail/operator_bool.hpp>
  488. bool unique() const BOOST_NOEXCEPT
  489. {
  490. return pn.unique();
  491. }
  492. long use_count() const BOOST_NOEXCEPT
  493. {
  494. return pn.use_count();
  495. }
  496. void swap( shared_ptr & other ) BOOST_NOEXCEPT
  497. {
  498. std::swap(px, other.px);
  499. pn.swap(other.pn);
  500. }
  501. template<class Y> bool owner_before( shared_ptr<Y> const & rhs ) const BOOST_NOEXCEPT
  502. {
  503. return pn < rhs.pn;
  504. }
  505. template<class Y> bool owner_before( weak_ptr<Y> const & rhs ) const BOOST_NOEXCEPT
  506. {
  507. return pn < rhs.pn;
  508. }
  509. void * _internal_get_deleter( boost::detail::sp_typeinfo const & ti ) const BOOST_NOEXCEPT
  510. {
  511. return pn.get_deleter( ti );
  512. }
  513. void * _internal_get_untyped_deleter() const BOOST_NOEXCEPT
  514. {
  515. return pn.get_untyped_deleter();
  516. }
  517. bool _internal_equiv( shared_ptr const & r ) const BOOST_NOEXCEPT
  518. {
  519. return px == r.px && pn == r.pn;
  520. }
  521. // Tasteless as this may seem, making all members public allows member templates
  522. // to work in the absence of member template friends. (Matthew Langston)
  523. #ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS
  524. private:
  525. template<class Y> friend class shared_ptr;
  526. template<class Y> friend class weak_ptr;
  527. #endif
  528. element_type * px; // contained pointer
  529. boost::detail::shared_count pn; // reference counter
  530. }; // shared_ptr
  531. template<class T, class U> inline bool operator==(shared_ptr<T> const & a, shared_ptr<U> const & b) BOOST_NOEXCEPT
  532. {
  533. return a.get() == b.get();
  534. }
  535. template<class T, class U> inline bool operator!=(shared_ptr<T> const & a, shared_ptr<U> const & b) BOOST_NOEXCEPT
  536. {
  537. return a.get() != b.get();
  538. }
  539. #if __GNUC__ == 2 && __GNUC_MINOR__ <= 96
  540. // Resolve the ambiguity between our op!= and the one in rel_ops
  541. template<class T> inline bool operator!=(shared_ptr<T> const & a, shared_ptr<T> const & b) BOOST_NOEXCEPT
  542. {
  543. return a.get() != b.get();
  544. }
  545. #endif
  546. #if !defined( BOOST_NO_CXX11_NULLPTR )
  547. template<class T> inline bool operator==( shared_ptr<T> const & p, boost::detail::sp_nullptr_t ) BOOST_NOEXCEPT
  548. {
  549. return p.get() == 0;
  550. }
  551. template<class T> inline bool operator==( boost::detail::sp_nullptr_t, shared_ptr<T> const & p ) BOOST_NOEXCEPT
  552. {
  553. return p.get() == 0;
  554. }
  555. template<class T> inline bool operator!=( shared_ptr<T> const & p, boost::detail::sp_nullptr_t ) BOOST_NOEXCEPT
  556. {
  557. return p.get() != 0;
  558. }
  559. template<class T> inline bool operator!=( boost::detail::sp_nullptr_t, shared_ptr<T> const & p ) BOOST_NOEXCEPT
  560. {
  561. return p.get() != 0;
  562. }
  563. #endif
  564. template<class T, class U> inline bool operator<(shared_ptr<T> const & a, shared_ptr<U> const & b) BOOST_NOEXCEPT
  565. {
  566. return a.owner_before( b );
  567. }
  568. template<class T> inline void swap(shared_ptr<T> & a, shared_ptr<T> & b) BOOST_NOEXCEPT
  569. {
  570. a.swap(b);
  571. }
  572. template<class T, class U> shared_ptr<T> static_pointer_cast( shared_ptr<U> const & r ) BOOST_NOEXCEPT
  573. {
  574. (void) static_cast< T* >( static_cast< U* >( 0 ) );
  575. typedef typename shared_ptr<T>::element_type E;
  576. E * p = static_cast< E* >( r.get() );
  577. return shared_ptr<T>( r, p );
  578. }
  579. template<class T, class U> shared_ptr<T> const_pointer_cast( shared_ptr<U> const & r ) BOOST_NOEXCEPT
  580. {
  581. (void) const_cast< T* >( static_cast< U* >( 0 ) );
  582. typedef typename shared_ptr<T>::element_type E;
  583. E * p = const_cast< E* >( r.get() );
  584. return shared_ptr<T>( r, p );
  585. }
  586. template<class T, class U> shared_ptr<T> dynamic_pointer_cast( shared_ptr<U> const & r ) BOOST_NOEXCEPT
  587. {
  588. (void) dynamic_cast< T* >( static_cast< U* >( 0 ) );
  589. typedef typename shared_ptr<T>::element_type E;
  590. E * p = dynamic_cast< E* >( r.get() );
  591. return p? shared_ptr<T>( r, p ): shared_ptr<T>();
  592. }
  593. template<class T, class U> shared_ptr<T> reinterpret_pointer_cast( shared_ptr<U> const & r ) BOOST_NOEXCEPT
  594. {
  595. (void) reinterpret_cast< T* >( static_cast< U* >( 0 ) );
  596. typedef typename shared_ptr<T>::element_type E;
  597. E * p = reinterpret_cast< E* >( r.get() );
  598. return shared_ptr<T>( r, p );
  599. }
  600. // get_pointer() enables boost::mem_fn to recognize shared_ptr
  601. template<class T> inline typename shared_ptr<T>::element_type * get_pointer(shared_ptr<T> const & p) BOOST_NOEXCEPT
  602. {
  603. return p.get();
  604. }
  605. // operator<<
  606. #if !defined(BOOST_NO_IOSTREAM)
  607. #if defined(BOOST_NO_TEMPLATED_IOSTREAMS) || ( defined(__GNUC__) && (__GNUC__ < 3) )
  608. template<class Y> std::ostream & operator<< (std::ostream & os, shared_ptr<Y> const & p)
  609. {
  610. os << p.get();
  611. return os;
  612. }
  613. #else
  614. // in STLport's no-iostreams mode no iostream symbols can be used
  615. #ifndef _STLP_NO_IOSTREAMS
  616. # if defined(BOOST_MSVC) && BOOST_WORKAROUND(BOOST_MSVC, < 1300 && __SGI_STL_PORT)
  617. // MSVC6 has problems finding std::basic_ostream through the using declaration in namespace _STL
  618. using std::basic_ostream;
  619. template<class E, class T, class Y> basic_ostream<E, T> & operator<< (basic_ostream<E, T> & os, shared_ptr<Y> const & p)
  620. # else
  621. template<class E, class T, class Y> std::basic_ostream<E, T> & operator<< (std::basic_ostream<E, T> & os, shared_ptr<Y> const & p)
  622. # endif
  623. {
  624. os << p.get();
  625. return os;
  626. }
  627. #endif // _STLP_NO_IOSTREAMS
  628. #endif // __GNUC__ < 3
  629. #endif // !defined(BOOST_NO_IOSTREAM)
  630. // get_deleter
  631. namespace detail
  632. {
  633. #if ( defined(__GNUC__) && BOOST_WORKAROUND(__GNUC__, < 3) ) || \
  634. ( defined(__EDG_VERSION__) && BOOST_WORKAROUND(__EDG_VERSION__, <= 238) ) || \
  635. ( defined(__HP_aCC) && BOOST_WORKAROUND(__HP_aCC, <= 33500) )
  636. // g++ 2.9x doesn't allow static_cast<X const *>(void *)
  637. // apparently EDG 2.38 and HP aCC A.03.35 also don't accept it
  638. template<class D, class T> D * basic_get_deleter(shared_ptr<T> const & p)
  639. {
  640. void const * q = p._internal_get_deleter(BOOST_SP_TYPEID(D));
  641. return const_cast<D *>(static_cast<D const *>(q));
  642. }
  643. #else
  644. template<class D, class T> D * basic_get_deleter( shared_ptr<T> const & p ) BOOST_NOEXCEPT
  645. {
  646. return static_cast<D *>( p._internal_get_deleter(BOOST_SP_TYPEID(D)) );
  647. }
  648. #endif
  649. class esft2_deleter_wrapper
  650. {
  651. private:
  652. shared_ptr<void> deleter_;
  653. public:
  654. esft2_deleter_wrapper()
  655. {
  656. }
  657. template< class T > void set_deleter( shared_ptr<T> const & deleter )
  658. {
  659. deleter_ = deleter;
  660. }
  661. template<typename D> D* get_deleter() const BOOST_NOEXCEPT
  662. {
  663. return boost::detail::basic_get_deleter<D>( deleter_ );
  664. }
  665. template< class T> void operator()( T* )
  666. {
  667. BOOST_ASSERT( deleter_.use_count() <= 1 );
  668. deleter_.reset();
  669. }
  670. };
  671. } // namespace detail
  672. template<class D, class T> D * get_deleter( shared_ptr<T> const & p ) BOOST_NOEXCEPT
  673. {
  674. D *del = boost::detail::basic_get_deleter<D>(p);
  675. if(del == 0)
  676. {
  677. boost::detail::esft2_deleter_wrapper *del_wrapper = boost::detail::basic_get_deleter<boost::detail::esft2_deleter_wrapper>(p);
  678. // The following get_deleter method call is fully qualified because
  679. // older versions of gcc (2.95, 3.2.3) fail to compile it when written del_wrapper->get_deleter<D>()
  680. if(del_wrapper) del = del_wrapper->::boost::detail::esft2_deleter_wrapper::get_deleter<D>();
  681. }
  682. return del;
  683. }
  684. // atomic access
  685. #if !defined(BOOST_SP_NO_ATOMIC_ACCESS)
  686. template<class T> inline bool atomic_is_lock_free( shared_ptr<T> const * /*p*/ ) BOOST_NOEXCEPT
  687. {
  688. return false;
  689. }
  690. template<class T> shared_ptr<T> atomic_load( shared_ptr<T> const * p )
  691. {
  692. boost::detail::spinlock_pool<2>::scoped_lock lock( p );
  693. return *p;
  694. }
  695. template<class T> inline shared_ptr<T> atomic_load_explicit( shared_ptr<T> const * p, memory_order /*mo*/ )
  696. {
  697. return atomic_load( p );
  698. }
  699. template<class T> void atomic_store( shared_ptr<T> * p, shared_ptr<T> r )
  700. {
  701. boost::detail::spinlock_pool<2>::scoped_lock lock( p );
  702. p->swap( r );
  703. }
  704. template<class T> inline void atomic_store_explicit( shared_ptr<T> * p, shared_ptr<T> r, memory_order /*mo*/ )
  705. {
  706. atomic_store( p, r ); // std::move( r )
  707. }
  708. template<class T> shared_ptr<T> atomic_exchange( shared_ptr<T> * p, shared_ptr<T> r )
  709. {
  710. boost::detail::spinlock & sp = boost::detail::spinlock_pool<2>::spinlock_for( p );
  711. sp.lock();
  712. p->swap( r );
  713. sp.unlock();
  714. return r; // return std::move( r )
  715. }
  716. template<class T> shared_ptr<T> atomic_exchange_explicit( shared_ptr<T> * p, shared_ptr<T> r, memory_order /*mo*/ )
  717. {
  718. return atomic_exchange( p, r ); // std::move( r )
  719. }
  720. template<class T> bool atomic_compare_exchange( shared_ptr<T> * p, shared_ptr<T> * v, shared_ptr<T> w )
  721. {
  722. boost::detail::spinlock & sp = boost::detail::spinlock_pool<2>::spinlock_for( p );
  723. sp.lock();
  724. if( p->_internal_equiv( *v ) )
  725. {
  726. p->swap( w );
  727. sp.unlock();
  728. return true;
  729. }
  730. else
  731. {
  732. shared_ptr<T> tmp( *p );
  733. sp.unlock();
  734. tmp.swap( *v );
  735. return false;
  736. }
  737. }
  738. template<class T> inline bool atomic_compare_exchange_explicit( shared_ptr<T> * p, shared_ptr<T> * v, shared_ptr<T> w, memory_order /*success*/, memory_order /*failure*/ )
  739. {
  740. return atomic_compare_exchange( p, v, w ); // std::move( w )
  741. }
  742. #endif // !defined(BOOST_SP_NO_ATOMIC_ACCESS)
  743. // hash_value
  744. template< class T > struct hash;
  745. template< class T > std::size_t hash_value( boost::shared_ptr<T> const & p ) BOOST_NOEXCEPT
  746. {
  747. return boost::hash< T* >()( p.get() );
  748. }
  749. } // namespace boost
  750. #endif // #if defined(BOOST_NO_MEMBER_TEMPLATES) && !defined(BOOST_MSVC6_MEMBER_TEMPLATES)
  751. #endif // #ifndef BOOST_SMART_PTR_SHARED_PTR_HPP_INCLUDED