1 #ifndef BOOST_SMART_PTR_SHARED_PTR_HPP_INCLUDED
2 #define BOOST_SMART_PTR_SHARED_PTR_HPP_INCLUDED
3 
4 //
5 //  shared_ptr.hpp
6 //
7 //  (C) Copyright Greg Colvin and Beman Dawes 1998, 1999.
8 //  Copyright (c) 2001-2008 Peter Dimov
9 //
10 //  Distributed under the Boost Software License, Version 1.0. (See
11 //  accompanying file LICENSE_1_0.txt or copy at
12 //  http://www.boost.org/LICENSE_1_0.txt)
13 //
14 //  See http://www.boost.org/libs/smart_ptr/shared_ptr.htm for documentation.
15 //
16 
17 #include <boost/config.hpp>   // for broken compiler workarounds
18 
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 
25 #include <boost/assert.hpp>
26 #include <boost/checked_delete.hpp>
27 #include <boost/throw_exception.hpp>
28 #include <boost/smart_ptr/detail/shared_count.hpp>
29 #include <boost/detail/workaround.hpp>
30 #include <boost/smart_ptr/detail/sp_convertible.hpp>
31 #include <boost/smart_ptr/detail/sp_nullptr_t.hpp>
32 #include <boost/smart_ptr/detail/sp_disable_deprecated.hpp>
33 
34 #if !defined(BOOST_SP_NO_ATOMIC_ACCESS)
35 #include <boost/smart_ptr/detail/spinlock_pool.hpp>
36 #endif
37 
38 #include <algorithm>            // for std::swap
39 #include <functional>           // for std::less
40 #include <typeinfo>             // for std::bad_cast
41 #include <cstddef>              // for std::size_t
42 
43 #if !defined(BOOST_NO_IOSTREAM)
44 #if !defined(BOOST_NO_IOSFWD)
45 #include <iosfwd>               // for std::basic_ostream
46 #else
47 #include <ostream>
48 #endif
49 #endif
50 
51 #if defined( BOOST_SP_DISABLE_DEPRECATED )
52 #pragma GCC diagnostic push
53 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
54 #endif
55 
56 namespace boost
57 {
58 
59 template<class T> class shared_ptr;
60 template<class T> class weak_ptr;
61 template<class T> class enable_shared_from_this;
62 class enable_shared_from_raw;
63 
64 namespace movelib
65 {
66 
67     template< class T, class D > class unique_ptr;
68 
69 } // namespace movelib
70 
71 namespace detail
72 {
73 
74 // sp_element, element_type
75 
76 template< class T > struct sp_element
77 {
78     typedef T type;
79 };
80 
81 #if !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
82 
83 template< class T > struct sp_element< T[] >
84 {
85     typedef T type;
86 };
87 
88 #if !defined( __BORLANDC__ ) || !BOOST_WORKAROUND( __BORLANDC__, < 0x600 )
89 
90 template< class T, std::size_t N > struct sp_element< T[N] >
91 {
92     typedef T type;
93 };
94 
95 #endif
96 
97 #endif // !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
98 
99 // sp_dereference, return type of operator*
100 
101 template< class T > struct sp_dereference
102 {
103     typedef T & type;
104 };
105 
106 template<> struct sp_dereference< void >
107 {
108     typedef void type;
109 };
110 
111 #if !defined(BOOST_NO_CV_VOID_SPECIALIZATIONS)
112 
113 template<> struct sp_dereference< void const >
114 {
115     typedef void type;
116 };
117 
118 template<> struct sp_dereference< void volatile >
119 {
120     typedef void type;
121 };
122 
123 template<> struct sp_dereference< void const volatile >
124 {
125     typedef void type;
126 };
127 
128 #endif // !defined(BOOST_NO_CV_VOID_SPECIALIZATIONS)
129 
130 #if !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
131 
132 template< class T > struct sp_dereference< T[] >
133 {
134     typedef void type;
135 };
136 
137 #if !defined( __BORLANDC__ ) || !BOOST_WORKAROUND( __BORLANDC__, < 0x600 )
138 
139 template< class T, std::size_t N > struct sp_dereference< T[N] >
140 {
141     typedef void type;
142 };
143 
144 #endif
145 
146 #endif // !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
147 
148 // sp_member_access, return type of operator->
149 
150 template< class T > struct sp_member_access
151 {
152     typedef T * type;
153 };
154 
155 #if !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
156 
157 template< class T > struct sp_member_access< T[] >
158 {
159     typedef void type;
160 };
161 
162 #if !defined( __BORLANDC__ ) || !BOOST_WORKAROUND( __BORLANDC__, < 0x600 )
163 
164 template< class T, std::size_t N > struct sp_member_access< T[N] >
165 {
166     typedef void type;
167 };
168 
169 #endif
170 
171 #endif // !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
172 
173 // sp_array_access, return type of operator[]
174 
175 template< class T > struct sp_array_access
176 {
177     typedef void type;
178 };
179 
180 #if !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
181 
182 template< class T > struct sp_array_access< T[] >
183 {
184     typedef T & type;
185 };
186 
187 #if !defined( __BORLANDC__ ) || !BOOST_WORKAROUND( __BORLANDC__, < 0x600 )
188 
189 template< class T, std::size_t N > struct sp_array_access< T[N] >
190 {
191     typedef T & type;
192 };
193 
194 #endif
195 
196 #endif // !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
197 
198 // sp_extent, for operator[] index check
199 
200 template< class T > struct sp_extent
201 {
202     enum _vt { value = 0 };
203 };
204 
205 #if !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
206 
207 template< class T, std::size_t N > struct sp_extent< T[N] >
208 {
209     enum _vt { value = N };
210 };
211 
212 #endif // !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
213 
214 // enable_shared_from_this support
215 
sp_enable_shared_from_this(boost::shared_ptr<X> const * ppx,Y const * py,boost::enable_shared_from_this<T> const * pe)216 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 )
217 {
218     if( pe != 0 )
219     {
220         pe->_internal_accept_owner( ppx, const_cast< Y* >( py ) );
221     }
222 }
223 
224 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 );
225 
226 #ifdef _MANAGED
227 
228 // Avoid C4793, ... causes native code generation
229 
230 struct sp_any_pointer
231 {
sp_any_pointerboost::detail::sp_any_pointer232     template<class T> sp_any_pointer( T* ) {}
233 };
234 
sp_enable_shared_from_this(sp_any_pointer,sp_any_pointer,sp_any_pointer)235 inline void sp_enable_shared_from_this( sp_any_pointer, sp_any_pointer, sp_any_pointer )
236 {
237 }
238 
239 #else // _MANAGED
240 
sp_enable_shared_from_this(...)241 inline void sp_enable_shared_from_this( ... )
242 {
243 }
244 
245 #endif // _MANAGED
246 
247 #if !defined( BOOST_NO_SFINAE ) && !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION ) && !defined( BOOST_NO_AUTO_PTR )
248 
249 // rvalue auto_ptr support based on a technique by Dave Abrahams
250 
251 template< class T, class R > struct sp_enable_if_auto_ptr
252 {
253 };
254 
255 template< class T, class R > struct sp_enable_if_auto_ptr< std::auto_ptr< T >, R >
256 {
257     typedef R type;
258 };
259 
260 #endif
261 
262 // sp_assert_convertible
263 
sp_assert_convertible()264 template< class Y, class T > inline void sp_assert_convertible()
265 {
266 #if !defined( BOOST_SP_NO_SP_CONVERTIBLE )
267 
268     // static_assert( sp_convertible< Y, T >::value );
269     typedef char tmp[ sp_convertible< Y, T >::value? 1: -1 ];
270     (void)sizeof( tmp );
271 
272 #else
273 
274     T* p = static_cast< Y* >( 0 );
275     (void)p;
276 
277 #endif
278 }
279 
280 // pointer constructor helper
281 
sp_pointer_construct(boost::shared_ptr<T> * ppx,Y * p,boost::detail::shared_count & pn)282 template< class T, class Y > inline void sp_pointer_construct( boost::shared_ptr< T > * ppx, Y * p, boost::detail::shared_count & pn )
283 {
284     boost::detail::shared_count( p ).swap( pn );
285     boost::detail::sp_enable_shared_from_this( ppx, p, p );
286 }
287 
288 #if !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
289 
sp_pointer_construct(boost::shared_ptr<T[]> *,Y * p,boost::detail::shared_count & pn)290 template< class T, class Y > inline void sp_pointer_construct( boost::shared_ptr< T[] > * /*ppx*/, Y * p, boost::detail::shared_count & pn )
291 {
292     sp_assert_convertible< Y[], T[] >();
293     boost::detail::shared_count( p, boost::checked_array_deleter< T >() ).swap( pn );
294 }
295 
sp_pointer_construct(boost::shared_ptr<T[N]> *,Y * p,boost::detail::shared_count & pn)296 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 )
297 {
298     sp_assert_convertible< Y[N], T[N] >();
299     boost::detail::shared_count( p, boost::checked_array_deleter< T >() ).swap( pn );
300 }
301 
302 #endif // !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
303 
304 // deleter constructor helper
305 
sp_deleter_construct(boost::shared_ptr<T> * ppx,Y * p)306 template< class T, class Y > inline void sp_deleter_construct( boost::shared_ptr< T > * ppx, Y * p )
307 {
308     boost::detail::sp_enable_shared_from_this( ppx, p, p );
309 }
310 
311 #if !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
312 
sp_deleter_construct(boost::shared_ptr<T[]> *,Y *)313 template< class T, class Y > inline void sp_deleter_construct( boost::shared_ptr< T[] > * /*ppx*/, Y * /*p*/ )
314 {
315     sp_assert_convertible< Y[], T[] >();
316 }
317 
sp_deleter_construct(boost::shared_ptr<T[N]> *,Y *)318 template< class T, std::size_t N, class Y > inline void sp_deleter_construct( boost::shared_ptr< T[N] > * /*ppx*/, Y * /*p*/ )
319 {
320     sp_assert_convertible< Y[N], T[N] >();
321 }
322 
323 #endif // !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
324 
325 } // namespace detail
326 
327 
328 //
329 //  shared_ptr
330 //
331 //  An enhanced relative of scoped_ptr with reference counted copy semantics.
332 //  The object pointed to is deleted when the last shared_ptr pointing to it
333 //  is destroyed or reset.
334 //
335 
336 template<class T> class shared_ptr
337 {
338 private:
339 
340     // Borland 5.5.1 specific workaround
341     typedef shared_ptr<T> this_type;
342 
343 public:
344 
345     typedef typename boost::detail::sp_element< T >::type element_type;
346 
shared_ptr()347     shared_ptr() BOOST_NOEXCEPT : px( 0 ), pn() // never throws in 1.30+
348     {
349     }
350 
351 #if !defined( BOOST_NO_CXX11_NULLPTR )
352 
shared_ptr(boost::detail::sp_nullptr_t)353     shared_ptr( boost::detail::sp_nullptr_t ) BOOST_NOEXCEPT : px( 0 ), pn() // never throws
354     {
355     }
356 
357 #endif
358 
359     template<class Y>
shared_ptr(Y * p)360     explicit shared_ptr( Y * p ): px( p ), pn() // Y must be complete
361     {
362         boost::detail::sp_pointer_construct( this, p, pn );
363     }
364 
365     //
366     // Requirements: D's copy constructor must not throw
367     //
368     // shared_ptr will release p by calling d(p)
369     //
370 
shared_ptr(Y * p,D d)371     template<class Y, class D> shared_ptr( Y * p, D d ): px( p ), pn( p, d )
372     {
373         boost::detail::sp_deleter_construct( this, p );
374     }
375 
376 #if !defined( BOOST_NO_CXX11_NULLPTR )
377 
shared_ptr(boost::detail::sp_nullptr_t p,D d)378     template<class D> shared_ptr( boost::detail::sp_nullptr_t p, D d ): px( p ), pn( p, d )
379     {
380     }
381 
382 #endif
383 
384     // As above, but with allocator. A's copy constructor shall not throw.
385 
shared_ptr(Y * p,D d,A a)386     template<class Y, class D, class A> shared_ptr( Y * p, D d, A a ): px( p ), pn( p, d, a )
387     {
388         boost::detail::sp_deleter_construct( this, p );
389     }
390 
391 #if !defined( BOOST_NO_CXX11_NULLPTR )
392 
shared_ptr(boost::detail::sp_nullptr_t p,D d,A a)393     template<class D, class A> shared_ptr( boost::detail::sp_nullptr_t p, D d, A a ): px( p ), pn( p, d, a )
394     {
395     }
396 
397 #endif
398 
399 //  generated copy constructor, destructor are fine...
400 
401 #if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
402 
403 // ... except in C++0x, move disables the implicit copy
404 
shared_ptr(shared_ptr const & r)405     shared_ptr( shared_ptr const & r ) BOOST_NOEXCEPT : px( r.px ), pn( r.pn )
406     {
407     }
408 
409 #endif
410 
411     template<class Y>
shared_ptr(weak_ptr<Y> const & r)412     explicit shared_ptr( weak_ptr<Y> const & r ): pn( r.pn ) // may throw
413     {
414         boost::detail::sp_assert_convertible< Y, T >();
415 
416         // it is now safe to copy r.px, as pn(r.pn) did not throw
417         px = r.px;
418     }
419 
420     template<class Y>
shared_ptr(weak_ptr<Y> const & r,boost::detail::sp_nothrow_tag)421     shared_ptr( weak_ptr<Y> const & r, boost::detail::sp_nothrow_tag )
422     BOOST_NOEXCEPT : px( 0 ), pn( r.pn, boost::detail::sp_nothrow_tag() )
423     {
424         if( !pn.empty() )
425         {
426             px = r.px;
427         }
428     }
429 
430     template<class Y>
431 #if !defined( BOOST_SP_NO_SP_CONVERTIBLE )
432 
shared_ptr(shared_ptr<Y> const & r,typename boost::detail::sp_enable_if_convertible<Y,T>::type=boost::detail::sp_empty ())433     shared_ptr( shared_ptr<Y> const & r, typename boost::detail::sp_enable_if_convertible<Y,T>::type = boost::detail::sp_empty() )
434 
435 #else
436 
437     shared_ptr( shared_ptr<Y> const & r )
438 
439 #endif
440     BOOST_NOEXCEPT : px( r.px ), pn( r.pn )
441     {
442         boost::detail::sp_assert_convertible< Y, T >();
443     }
444 
445     // aliasing
446     template< class Y >
shared_ptr(shared_ptr<Y> const & r,element_type * p)447     shared_ptr( shared_ptr<Y> const & r, element_type * p ) BOOST_NOEXCEPT : px( p ), pn( r.pn )
448     {
449     }
450 
451 #ifndef BOOST_NO_AUTO_PTR
452 
453     template<class Y>
shared_ptr(std::auto_ptr<Y> & r)454     explicit shared_ptr( std::auto_ptr<Y> & r ): px(r.get()), pn()
455     {
456         boost::detail::sp_assert_convertible< Y, T >();
457 
458         Y * tmp = r.get();
459         pn = boost::detail::shared_count( r );
460 
461         boost::detail::sp_deleter_construct( this, tmp );
462     }
463 
464 #if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
465 
466     template<class Y>
shared_ptr(std::auto_ptr<Y> && r)467     shared_ptr( std::auto_ptr<Y> && r ): px(r.get()), pn()
468     {
469         boost::detail::sp_assert_convertible< Y, T >();
470 
471         Y * tmp = r.get();
472         pn = boost::detail::shared_count( r );
473 
474         boost::detail::sp_deleter_construct( this, tmp );
475     }
476 
477 #elif !defined( BOOST_NO_SFINAE ) && !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
478 
479     template<class Ap>
shared_ptr(Ap r,typename boost::detail::sp_enable_if_auto_ptr<Ap,int>::type=0)480     explicit shared_ptr( Ap r, typename boost::detail::sp_enable_if_auto_ptr<Ap, int>::type = 0 ): px( r.get() ), pn()
481     {
482         typedef typename Ap::element_type Y;
483 
484         boost::detail::sp_assert_convertible< Y, T >();
485 
486         Y * tmp = r.get();
487         pn = boost::detail::shared_count( r );
488 
489         boost::detail::sp_deleter_construct( this, tmp );
490     }
491 
492 #endif // BOOST_NO_SFINAE, BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
493 
494 #endif // BOOST_NO_AUTO_PTR
495 
496 #if !defined( BOOST_NO_CXX11_SMART_PTR ) && !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
497 
498     template< class Y, class D >
shared_ptr(std::unique_ptr<Y,D> && r)499     shared_ptr( std::unique_ptr< Y, D > && r ): px( r.get() ), pn()
500     {
501         boost::detail::sp_assert_convertible< Y, T >();
502 
503         typename std::unique_ptr< Y, D >::pointer tmp = r.get();
504         pn = boost::detail::shared_count( r );
505 
506         boost::detail::sp_deleter_construct( this, tmp );
507     }
508 
509 #endif
510 
511     template< class Y, class D >
shared_ptr(boost::movelib::unique_ptr<Y,D> r)512     shared_ptr( boost::movelib::unique_ptr< Y, D > r ): px( r.get() ), pn()
513     {
514         boost::detail::sp_assert_convertible< Y, T >();
515 
516         typename boost::movelib::unique_ptr< Y, D >::pointer tmp = r.get();
517         pn = boost::detail::shared_count( r );
518 
519         boost::detail::sp_deleter_construct( this, tmp );
520     }
521 
522     // assignment
523 
operator =(shared_ptr const & r)524     shared_ptr & operator=( shared_ptr const & r ) BOOST_NOEXCEPT
525     {
526         this_type(r).swap(*this);
527         return *this;
528     }
529 
530 #if !defined(BOOST_MSVC) || (BOOST_MSVC >= 1400)
531 
532     template<class Y>
operator =(shared_ptr<Y> const & r)533     shared_ptr & operator=(shared_ptr<Y> const & r) BOOST_NOEXCEPT
534     {
535         this_type(r).swap(*this);
536         return *this;
537     }
538 
539 #endif
540 
541 #ifndef BOOST_NO_AUTO_PTR
542 
543     template<class Y>
operator =(std::auto_ptr<Y> & r)544     shared_ptr & operator=( std::auto_ptr<Y> & r )
545     {
546         this_type( r ).swap( *this );
547         return *this;
548     }
549 
550 #if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
551 
552     template<class Y>
operator =(std::auto_ptr<Y> && r)553     shared_ptr & operator=( std::auto_ptr<Y> && r )
554     {
555         this_type( static_cast< std::auto_ptr<Y> && >( r ) ).swap( *this );
556         return *this;
557     }
558 
559 #elif !defined( BOOST_NO_SFINAE ) && !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
560 
561     template<class Ap>
operator =(Ap r)562     typename boost::detail::sp_enable_if_auto_ptr< Ap, shared_ptr & >::type operator=( Ap r )
563     {
564         this_type( r ).swap( *this );
565         return *this;
566     }
567 
568 #endif // BOOST_NO_SFINAE, BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
569 
570 #endif // BOOST_NO_AUTO_PTR
571 
572 #if !defined( BOOST_NO_CXX11_SMART_PTR ) && !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
573 
574     template<class Y, class D>
operator =(std::unique_ptr<Y,D> && r)575     shared_ptr & operator=( std::unique_ptr<Y, D> && r )
576     {
577         this_type( static_cast< std::unique_ptr<Y, D> && >( r ) ).swap(*this);
578         return *this;
579     }
580 
581 #endif
582 
583     template<class Y, class D>
operator =(boost::movelib::unique_ptr<Y,D> r)584     shared_ptr & operator=( boost::movelib::unique_ptr<Y, D> r )
585     {
586         // this_type( static_cast< unique_ptr<Y, D> && >( r ) ).swap( *this );
587 
588         boost::detail::sp_assert_convertible< Y, T >();
589 
590         typename boost::movelib::unique_ptr< Y, D >::pointer p = r.get();
591 
592         shared_ptr tmp;
593 
594         tmp.px = p;
595         tmp.pn = boost::detail::shared_count( r );
596 
597         boost::detail::sp_deleter_construct( &tmp, p );
598 
599         tmp.swap( *this );
600 
601         return *this;
602     }
603 
604 // Move support
605 
606 #if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
607 
shared_ptr(shared_ptr && r)608     shared_ptr( shared_ptr && r ) BOOST_NOEXCEPT : px( r.px ), pn()
609     {
610         pn.swap( r.pn );
611         r.px = 0;
612     }
613 
614     template<class Y>
615 #if !defined( BOOST_SP_NO_SP_CONVERTIBLE )
616 
shared_ptr(shared_ptr<Y> && r,typename boost::detail::sp_enable_if_convertible<Y,T>::type=boost::detail::sp_empty ())617     shared_ptr( shared_ptr<Y> && r, typename boost::detail::sp_enable_if_convertible<Y,T>::type = boost::detail::sp_empty() )
618 
619 #else
620 
621     shared_ptr( shared_ptr<Y> && r )
622 
623 #endif
624     BOOST_NOEXCEPT : px( r.px ), pn()
625     {
626         boost::detail::sp_assert_convertible< Y, T >();
627 
628         pn.swap( r.pn );
629         r.px = 0;
630     }
631 
operator =(shared_ptr && r)632     shared_ptr & operator=( shared_ptr && r ) BOOST_NOEXCEPT
633     {
634         this_type( static_cast< shared_ptr && >( r ) ).swap( *this );
635         return *this;
636     }
637 
638     template<class Y>
operator =(shared_ptr<Y> && r)639     shared_ptr & operator=( shared_ptr<Y> && r ) BOOST_NOEXCEPT
640     {
641         this_type( static_cast< shared_ptr<Y> && >( r ) ).swap( *this );
642         return *this;
643     }
644 
645     // aliasing move
646     template<class Y>
shared_ptr(shared_ptr<Y> && r,element_type * p)647     shared_ptr( shared_ptr<Y> && r, element_type * p ) BOOST_NOEXCEPT : px( p ), pn()
648     {
649         pn.swap( r.pn );
650         r.px = 0;
651     }
652 
653 #endif
654 
655 #if !defined( BOOST_NO_CXX11_NULLPTR )
656 
operator =(boost::detail::sp_nullptr_t)657     shared_ptr & operator=( boost::detail::sp_nullptr_t ) BOOST_NOEXCEPT // never throws
658     {
659         this_type().swap(*this);
660         return *this;
661     }
662 
663 #endif
664 
reset()665     void reset() BOOST_NOEXCEPT // never throws in 1.30+
666     {
667         this_type().swap(*this);
668     }
669 
reset(Y * p)670     template<class Y> void reset( Y * p ) // Y must be complete
671     {
672         BOOST_ASSERT( p == 0 || p != px ); // catch self-reset errors
673         this_type( p ).swap( *this );
674     }
675 
reset(Y * p,D d)676     template<class Y, class D> void reset( Y * p, D d )
677     {
678         this_type( p, d ).swap( *this );
679     }
680 
reset(Y * p,D d,A a)681     template<class Y, class D, class A> void reset( Y * p, D d, A a )
682     {
683         this_type( p, d, a ).swap( *this );
684     }
685 
reset(shared_ptr<Y> const & r,element_type * p)686     template<class Y> void reset( shared_ptr<Y> const & r, element_type * p )
687     {
688         this_type( r, p ).swap( *this );
689     }
690 
691 #if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
692 
reset(shared_ptr<Y> && r,element_type * p)693     template<class Y> void reset( shared_ptr<Y> && r, element_type * p )
694     {
695         this_type( static_cast< shared_ptr<Y> && >( r ), p ).swap( *this );
696     }
697 
698 #endif
699 
700     // never throws (but has a BOOST_ASSERT in it, so not marked with BOOST_NOEXCEPT)
operator *() const701     typename boost::detail::sp_dereference< T >::type operator* () const
702     {
703         BOOST_ASSERT( px != 0 );
704         return *px;
705     }
706 
707     // never throws (but has a BOOST_ASSERT in it, so not marked with BOOST_NOEXCEPT)
operator ->() const708     typename boost::detail::sp_member_access< T >::type operator-> () const
709     {
710         BOOST_ASSERT( px != 0 );
711         return px;
712     }
713 
714     // never throws (but has a BOOST_ASSERT in it, so not marked with BOOST_NOEXCEPT)
operator [](std::ptrdiff_t i) const715     typename boost::detail::sp_array_access< T >::type operator[] ( std::ptrdiff_t i ) const
716     {
717         BOOST_ASSERT( px != 0 );
718         BOOST_ASSERT( i >= 0 && ( i < boost::detail::sp_extent< T >::value || boost::detail::sp_extent< T >::value == 0 ) );
719 
720         return static_cast< typename boost::detail::sp_array_access< T >::type >( px[ i ] );
721     }
722 
get() const723     element_type * get() const BOOST_NOEXCEPT
724     {
725         return px;
726     }
727 
728 // implicit conversion to "bool"
729 #include <boost/smart_ptr/detail/operator_bool.hpp>
730 
unique() const731     bool unique() const BOOST_NOEXCEPT
732     {
733         return pn.unique();
734     }
735 
use_count() const736     long use_count() const BOOST_NOEXCEPT
737     {
738         return pn.use_count();
739     }
740 
swap(shared_ptr & other)741     void swap( shared_ptr & other ) BOOST_NOEXCEPT
742     {
743         std::swap(px, other.px);
744         pn.swap(other.pn);
745     }
746 
owner_before(shared_ptr<Y> const & rhs) const747     template<class Y> bool owner_before( shared_ptr<Y> const & rhs ) const BOOST_NOEXCEPT
748     {
749         return pn < rhs.pn;
750     }
751 
owner_before(weak_ptr<Y> const & rhs) const752     template<class Y> bool owner_before( weak_ptr<Y> const & rhs ) const BOOST_NOEXCEPT
753     {
754         return pn < rhs.pn;
755     }
756 
_internal_get_deleter(boost::detail::sp_typeinfo const & ti) const757     void * _internal_get_deleter( boost::detail::sp_typeinfo const & ti ) const BOOST_NOEXCEPT
758     {
759         return pn.get_deleter( ti );
760     }
761 
_internal_get_untyped_deleter() const762     void * _internal_get_untyped_deleter() const BOOST_NOEXCEPT
763     {
764         return pn.get_untyped_deleter();
765     }
766 
_internal_equiv(shared_ptr const & r) const767     bool _internal_equiv( shared_ptr const & r ) const BOOST_NOEXCEPT
768     {
769         return px == r.px && pn == r.pn;
770     }
771 
772 // Tasteless as this may seem, making all members public allows member templates
773 // to work in the absence of member template friends. (Matthew Langston)
774 
775 #ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS
776 
777 private:
778 
779     template<class Y> friend class shared_ptr;
780     template<class Y> friend class weak_ptr;
781 
782 
783 #endif
784 
785     element_type * px;                 // contained pointer
786     boost::detail::shared_count pn;    // reference counter
787 
788 };  // shared_ptr
789 
operator ==(shared_ptr<T> const & a,shared_ptr<U> const & b)790 template<class T, class U> inline bool operator==(shared_ptr<T> const & a, shared_ptr<U> const & b) BOOST_NOEXCEPT
791 {
792     return a.get() == b.get();
793 }
794 
operator !=(shared_ptr<T> const & a,shared_ptr<U> const & b)795 template<class T, class U> inline bool operator!=(shared_ptr<T> const & a, shared_ptr<U> const & b) BOOST_NOEXCEPT
796 {
797     return a.get() != b.get();
798 }
799 
800 #if __GNUC__ == 2 && __GNUC_MINOR__ <= 96
801 
802 // Resolve the ambiguity between our op!= and the one in rel_ops
803 
operator !=(shared_ptr<T> const & a,shared_ptr<T> const & b)804 template<class T> inline bool operator!=(shared_ptr<T> const & a, shared_ptr<T> const & b) BOOST_NOEXCEPT
805 {
806     return a.get() != b.get();
807 }
808 
809 #endif
810 
811 #if !defined( BOOST_NO_CXX11_NULLPTR )
812 
operator ==(shared_ptr<T> const & p,boost::detail::sp_nullptr_t)813 template<class T> inline bool operator==( shared_ptr<T> const & p, boost::detail::sp_nullptr_t ) BOOST_NOEXCEPT
814 {
815     return p.get() == 0;
816 }
817 
operator ==(boost::detail::sp_nullptr_t,shared_ptr<T> const & p)818 template<class T> inline bool operator==( boost::detail::sp_nullptr_t, shared_ptr<T> const & p ) BOOST_NOEXCEPT
819 {
820     return p.get() == 0;
821 }
822 
operator !=(shared_ptr<T> const & p,boost::detail::sp_nullptr_t)823 template<class T> inline bool operator!=( shared_ptr<T> const & p, boost::detail::sp_nullptr_t ) BOOST_NOEXCEPT
824 {
825     return p.get() != 0;
826 }
827 
operator !=(boost::detail::sp_nullptr_t,shared_ptr<T> const & p)828 template<class T> inline bool operator!=( boost::detail::sp_nullptr_t, shared_ptr<T> const & p ) BOOST_NOEXCEPT
829 {
830     return p.get() != 0;
831 }
832 
833 #endif
834 
operator <(shared_ptr<T> const & a,shared_ptr<U> const & b)835 template<class T, class U> inline bool operator<(shared_ptr<T> const & a, shared_ptr<U> const & b) BOOST_NOEXCEPT
836 {
837     return a.owner_before( b );
838 }
839 
swap(shared_ptr<T> & a,shared_ptr<T> & b)840 template<class T> inline void swap(shared_ptr<T> & a, shared_ptr<T> & b) BOOST_NOEXCEPT
841 {
842     a.swap(b);
843 }
844 
static_pointer_cast(shared_ptr<U> const & r)845 template<class T, class U> shared_ptr<T> static_pointer_cast( shared_ptr<U> const & r ) BOOST_NOEXCEPT
846 {
847     (void) static_cast< T* >( static_cast< U* >( 0 ) );
848 
849     typedef typename shared_ptr<T>::element_type E;
850 
851     E * p = static_cast< E* >( r.get() );
852     return shared_ptr<T>( r, p );
853 }
854 
const_pointer_cast(shared_ptr<U> const & r)855 template<class T, class U> shared_ptr<T> const_pointer_cast( shared_ptr<U> const & r ) BOOST_NOEXCEPT
856 {
857     (void) const_cast< T* >( static_cast< U* >( 0 ) );
858 
859     typedef typename shared_ptr<T>::element_type E;
860 
861     E * p = const_cast< E* >( r.get() );
862     return shared_ptr<T>( r, p );
863 }
864 
dynamic_pointer_cast(shared_ptr<U> const & r)865 template<class T, class U> shared_ptr<T> dynamic_pointer_cast( shared_ptr<U> const & r ) BOOST_NOEXCEPT
866 {
867     (void) dynamic_cast< T* >( static_cast< U* >( 0 ) );
868 
869     typedef typename shared_ptr<T>::element_type E;
870 
871     E * p = dynamic_cast< E* >( r.get() );
872     return p? shared_ptr<T>( r, p ): shared_ptr<T>();
873 }
874 
reinterpret_pointer_cast(shared_ptr<U> const & r)875 template<class T, class U> shared_ptr<T> reinterpret_pointer_cast( shared_ptr<U> const & r ) BOOST_NOEXCEPT
876 {
877     (void) reinterpret_cast< T* >( static_cast< U* >( 0 ) );
878 
879     typedef typename shared_ptr<T>::element_type E;
880 
881     E * p = reinterpret_cast< E* >( r.get() );
882     return shared_ptr<T>( r, p );
883 }
884 
885 // get_pointer() enables boost::mem_fn to recognize shared_ptr
886 
get_pointer(shared_ptr<T> const & p)887 template<class T> inline typename shared_ptr<T>::element_type * get_pointer(shared_ptr<T> const & p) BOOST_NOEXCEPT
888 {
889     return p.get();
890 }
891 
892 // operator<<
893 
894 #if !defined(BOOST_NO_IOSTREAM)
895 
896 #if defined(BOOST_NO_TEMPLATED_IOSTREAMS) || ( defined(__GNUC__) &&  (__GNUC__ < 3) )
897 
operator <<(std::ostream & os,shared_ptr<Y> const & p)898 template<class Y> std::ostream & operator<< (std::ostream & os, shared_ptr<Y> const & p)
899 {
900     os << p.get();
901     return os;
902 }
903 
904 #else
905 
906 // in STLport's no-iostreams mode no iostream symbols can be used
907 #ifndef _STLP_NO_IOSTREAMS
908 
909 # if defined(BOOST_MSVC) && BOOST_WORKAROUND(BOOST_MSVC, < 1300 && __SGI_STL_PORT)
910 // MSVC6 has problems finding std::basic_ostream through the using declaration in namespace _STL
911 using std::basic_ostream;
operator <<(basic_ostream<E,T> & os,shared_ptr<Y> const & p)912 template<class E, class T, class Y> basic_ostream<E, T> & operator<< (basic_ostream<E, T> & os, shared_ptr<Y> const & p)
913 # else
914 template<class E, class T, class Y> std::basic_ostream<E, T> & operator<< (std::basic_ostream<E, T> & os, shared_ptr<Y> const & p)
915 # endif
916 {
917     os << p.get();
918     return os;
919 }
920 
921 #endif // _STLP_NO_IOSTREAMS
922 
923 #endif // __GNUC__ < 3
924 
925 #endif // !defined(BOOST_NO_IOSTREAM)
926 
927 // get_deleter
928 
929 namespace detail
930 {
931 
932 #if ( defined(__GNUC__) && BOOST_WORKAROUND(__GNUC__, < 3) ) || \
933     ( defined(__EDG_VERSION__) && BOOST_WORKAROUND(__EDG_VERSION__, <= 238) ) || \
934     ( defined(__HP_aCC) && BOOST_WORKAROUND(__HP_aCC, <= 33500) )
935 
936 // g++ 2.9x doesn't allow static_cast<X const *>(void *)
937 // apparently EDG 2.38 and HP aCC A.03.35 also don't accept it
938 
939 template<class D, class T> D * basic_get_deleter(shared_ptr<T> const & p)
940 {
941     void const * q = p._internal_get_deleter(BOOST_SP_TYPEID(D));
942     return const_cast<D *>(static_cast<D const *>(q));
943 }
944 
945 #else
946 
947 template<class D, class T> D * basic_get_deleter( shared_ptr<T> const & p ) BOOST_NOEXCEPT
948 {
949     return static_cast<D *>( p._internal_get_deleter(BOOST_SP_TYPEID(D)) );
950 }
951 
952 #endif
953 
954 class esft2_deleter_wrapper
955 {
956 private:
957 
958     shared_ptr<void const volatile> deleter_;
959 
960 public:
961 
esft2_deleter_wrapper()962     esft2_deleter_wrapper()
963     {
964     }
965 
set_deleter(shared_ptr<T> const & deleter)966     template< class T > void set_deleter( shared_ptr<T> const & deleter )
967     {
968         deleter_ = deleter;
969     }
970 
get_deleter() const971     template<typename D> D* get_deleter() const BOOST_NOEXCEPT
972     {
973         return boost::detail::basic_get_deleter<D>( deleter_ );
974     }
975 
operator ()(T *)976     template< class T> void operator()( T* )
977     {
978         BOOST_ASSERT( deleter_.use_count() <= 1 );
979         deleter_.reset();
980     }
981 };
982 
983 } // namespace detail
984 
985 template<class D, class T> D * get_deleter( shared_ptr<T> const & p ) BOOST_NOEXCEPT
986 {
987     D *del = boost::detail::basic_get_deleter<D>(p);
988 
989     if(del == 0)
990     {
991         boost::detail::esft2_deleter_wrapper *del_wrapper = boost::detail::basic_get_deleter<boost::detail::esft2_deleter_wrapper>(p);
992 // The following get_deleter method call is fully qualified because
993 // older versions of gcc (2.95, 3.2.3) fail to compile it when written del_wrapper->get_deleter<D>()
994         if(del_wrapper) del = del_wrapper->::boost::detail::esft2_deleter_wrapper::get_deleter<D>();
995     }
996 
997     return del;
998 }
999 
1000 // atomic access
1001 
1002 #if !defined(BOOST_SP_NO_ATOMIC_ACCESS)
1003 
atomic_is_lock_free(shared_ptr<T> const *)1004 template<class T> inline bool atomic_is_lock_free( shared_ptr<T> const * /*p*/ ) BOOST_NOEXCEPT
1005 {
1006     return false;
1007 }
1008 
atomic_load(shared_ptr<T> const * p)1009 template<class T> shared_ptr<T> atomic_load( shared_ptr<T> const * p )
1010 {
1011     boost::detail::spinlock_pool<2>::scoped_lock lock( p );
1012     return *p;
1013 }
1014 
atomic_load_explicit(shared_ptr<T> const * p,int)1015 template<class T> inline shared_ptr<T> atomic_load_explicit( shared_ptr<T> const * p, /*memory_order mo*/ int )
1016 {
1017     return atomic_load( p );
1018 }
1019 
atomic_store(shared_ptr<T> * p,shared_ptr<T> r)1020 template<class T> void atomic_store( shared_ptr<T> * p, shared_ptr<T> r )
1021 {
1022     boost::detail::spinlock_pool<2>::scoped_lock lock( p );
1023     p->swap( r );
1024 }
1025 
atomic_store_explicit(shared_ptr<T> * p,shared_ptr<T> r,int)1026 template<class T> inline void atomic_store_explicit( shared_ptr<T> * p, shared_ptr<T> r, /*memory_order mo*/ int )
1027 {
1028     atomic_store( p, r ); // std::move( r )
1029 }
1030 
atomic_exchange(shared_ptr<T> * p,shared_ptr<T> r)1031 template<class T> shared_ptr<T> atomic_exchange( shared_ptr<T> * p, shared_ptr<T> r )
1032 {
1033     boost::detail::spinlock & sp = boost::detail::spinlock_pool<2>::spinlock_for( p );
1034 
1035     sp.lock();
1036     p->swap( r );
1037     sp.unlock();
1038 
1039     return r; // return std::move( r )
1040 }
1041 
atomic_exchange_explicit(shared_ptr<T> * p,shared_ptr<T> r,int)1042 template<class T> shared_ptr<T> atomic_exchange_explicit( shared_ptr<T> * p, shared_ptr<T> r, /*memory_order mo*/ int )
1043 {
1044     return atomic_exchange( p, r ); // std::move( r )
1045 }
1046 
atomic_compare_exchange(shared_ptr<T> * p,shared_ptr<T> * v,shared_ptr<T> w)1047 template<class T> bool atomic_compare_exchange( shared_ptr<T> * p, shared_ptr<T> * v, shared_ptr<T> w )
1048 {
1049     boost::detail::spinlock & sp = boost::detail::spinlock_pool<2>::spinlock_for( p );
1050 
1051     sp.lock();
1052 
1053     if( p->_internal_equiv( *v ) )
1054     {
1055         p->swap( w );
1056 
1057         sp.unlock();
1058 
1059         return true;
1060     }
1061     else
1062     {
1063         shared_ptr<T> tmp( *p );
1064 
1065         sp.unlock();
1066 
1067         tmp.swap( *v );
1068         return false;
1069     }
1070 }
1071 
atomic_compare_exchange_explicit(shared_ptr<T> * p,shared_ptr<T> * v,shared_ptr<T> w,int,int)1072 template<class T> inline bool atomic_compare_exchange_explicit( shared_ptr<T> * p, shared_ptr<T> * v, shared_ptr<T> w, /*memory_order success*/ int, /*memory_order failure*/ int )
1073 {
1074     return atomic_compare_exchange( p, v, w ); // std::move( w )
1075 }
1076 
1077 #endif // !defined(BOOST_SP_NO_ATOMIC_ACCESS)
1078 
1079 // hash_value
1080 
1081 template< class T > struct hash;
1082 
hash_value(boost::shared_ptr<T> const & p)1083 template< class T > std::size_t hash_value( boost::shared_ptr<T> const & p ) BOOST_NOEXCEPT
1084 {
1085     return boost::hash< typename boost::shared_ptr<T>::element_type* >()( p.get() );
1086 }
1087 
1088 } // namespace boost
1089 
1090 #if defined( BOOST_SP_DISABLE_DEPRECATED )
1091 #pragma GCC diagnostic pop
1092 #endif
1093 
1094 #endif  // #ifndef BOOST_SMART_PTR_SHARED_PTR_HPP_INCLUDED
1095