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
56namespace boost
57{
58
59template<class T> class shared_ptr;
60template<class T> class weak_ptr;
61template<class T> class enable_shared_from_this;
62class enable_shared_from_raw;
63
64namespace movelib
65{
66
67 template< class T, class D > class unique_ptr;
68
69} // namespace movelib
70
71namespace detail
72{
73
74// sp_element, element_type
75
76template< class T > struct sp_element
77{
78 typedef T type;
79};
80
81#if !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
82
83template< class T > struct sp_element< T[] >
84{
85 typedef T type;
86};
87
88#if !defined( __BORLANDC__ ) || !BOOST_WORKAROUND( __BORLANDC__, < 0x600 )
89
90template< 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
101template< class T > struct sp_dereference
102{
103 typedef T & type;
104};
105
106template<> struct sp_dereference< void >
107{
108 typedef void type;
109};
110
111#if !defined(BOOST_NO_CV_VOID_SPECIALIZATIONS)
112
113template<> struct sp_dereference< void const >
114{
115 typedef void type;
116};
117
118template<> struct sp_dereference< void volatile >
119{
120 typedef void type;
121};
122
123template<> 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
132template< class T > struct sp_dereference< T[] >
133{
134 typedef void type;
135};
136
137#if !defined( __BORLANDC__ ) || !BOOST_WORKAROUND( __BORLANDC__, < 0x600 )
138
139template< 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
150template< class T > struct sp_member_access
151{
152 typedef T * type;
153};
154
155#if !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
156
157template< class T > struct sp_member_access< T[] >
158{
159 typedef void type;
160};
161
162#if !defined( __BORLANDC__ ) || !BOOST_WORKAROUND( __BORLANDC__, < 0x600 )
163
164template< 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
175template< class T > struct sp_array_access
176{
177 typedef void type;
178};
179
180#if !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
181
182template< class T > struct sp_array_access< T[] >
183{
184 typedef T & type;
185};
186
187#if !defined( __BORLANDC__ ) || !BOOST_WORKAROUND( __BORLANDC__, < 0x600 )
188
189template< 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
200template< class T > struct sp_extent
201{
202 enum _vt { value = 0 };
203};
204
205#if !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
206
207template< 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
216template< 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
224template< 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
230struct sp_any_pointer
231{
232 template<class T> sp_any_pointer( T* ) {}
233};
234
235inline void sp_enable_shared_from_this( sp_any_pointer, sp_any_pointer, sp_any_pointer )
236{
237}
238
239#else // _MANAGED
240
241inline 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
251template< class T, class R > struct sp_enable_if_auto_ptr
252{
253};
254
255template< 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
264template< 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
282template< 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
290template< 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
296template< 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
306template< 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
313template< 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
318template< 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
336template<class T> class shared_ptr
337{
338private:
339
340 // Borland 5.5.1 specific workaround
341 typedef shared_ptr<T> this_type;
342
343public:
344
345 typedef typename boost::detail::sp_element< T >::type element_type;
346
347 shared_ptr() BOOST_NOEXCEPT : px( 0 ), pn() // never throws in 1.30+
348 {
349 }
350
351#if !defined( BOOST_NO_CXX11_NULLPTR )
352
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>
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
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
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
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
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
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>
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>
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
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 >
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>
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>
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>
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 >
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 >
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
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>
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>
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>
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>
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>
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>
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
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
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
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>
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#endif
646
647#if !defined( BOOST_NO_CXX11_NULLPTR )
648
649 shared_ptr & operator=( boost::detail::sp_nullptr_t ) BOOST_NOEXCEPT // never throws
650 {
651 this_type().swap(*this);
652 return *this;
653 }
654
655#endif
656
657 void reset() BOOST_NOEXCEPT // never throws in 1.30+
658 {
659 this_type().swap(*this);
660 }
661
662 template<class Y> void reset( Y * p ) // Y must be complete
663 {
664 BOOST_ASSERT( p == 0 || p != px ); // catch self-reset errors
665 this_type( p ).swap( *this );
666 }
667
668 template<class Y, class D> void reset( Y * p, D d )
669 {
670 this_type( p, d ).swap( *this );
671 }
672
673 template<class Y, class D, class A> void reset( Y * p, D d, A a )
674 {
675 this_type( p, d, a ).swap( *this );
676 }
677
678 template<class Y> void reset( shared_ptr<Y> const & r, element_type * p )
679 {
680 this_type( r, p ).swap( *this );
681 }
682
683 // never throws (but has a BOOST_ASSERT in it, so not marked with BOOST_NOEXCEPT)
684 typename boost::detail::sp_dereference< T >::type operator* () const
685 {
686 BOOST_ASSERT( px != 0 );
687 return *px;
688 }
689
690 // never throws (but has a BOOST_ASSERT in it, so not marked with BOOST_NOEXCEPT)
691 typename boost::detail::sp_member_access< T >::type operator-> () const
692 {
693 BOOST_ASSERT( px != 0 );
694 return px;
695 }
696
697 // never throws (but has a BOOST_ASSERT in it, so not marked with BOOST_NOEXCEPT)
698 typename boost::detail::sp_array_access< T >::type operator[] ( std::ptrdiff_t i ) const
699 {
700 BOOST_ASSERT( px != 0 );
701 BOOST_ASSERT( i >= 0 && ( i < boost::detail::sp_extent< T >::value || boost::detail::sp_extent< T >::value == 0 ) );
702
703 return static_cast< typename boost::detail::sp_array_access< T >::type >( px[ i ] );
704 }
705
706 element_type * get() const BOOST_NOEXCEPT
707 {
708 return px;
709 }
710
711// implicit conversion to "bool"
712#include <boost/smart_ptr/detail/operator_bool.hpp>
713
714 bool unique() const BOOST_NOEXCEPT
715 {
716 return pn.unique();
717 }
718
719 long use_count() const BOOST_NOEXCEPT
720 {
721 return pn.use_count();
722 }
723
724 void swap( shared_ptr & other ) BOOST_NOEXCEPT
725 {
726 std::swap(px, other.px);
727 pn.swap(other.pn);
728 }
729
730 template<class Y> bool owner_before( shared_ptr<Y> const & rhs ) const BOOST_NOEXCEPT
731 {
732 return pn < rhs.pn;
733 }
734
735 template<class Y> bool owner_before( weak_ptr<Y> const & rhs ) const BOOST_NOEXCEPT
736 {
737 return pn < rhs.pn;
738 }
739
740 void * _internal_get_deleter( boost::detail::sp_typeinfo const & ti ) const BOOST_NOEXCEPT
741 {
742 return pn.get_deleter( ti );
743 }
744
745 void * _internal_get_untyped_deleter() const BOOST_NOEXCEPT
746 {
747 return pn.get_untyped_deleter();
748 }
749
750 bool _internal_equiv( shared_ptr const & r ) const BOOST_NOEXCEPT
751 {
752 return px == r.px && pn == r.pn;
753 }
754
755// Tasteless as this may seem, making all members public allows member templates
756// to work in the absence of member template friends. (Matthew Langston)
757
758#ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS
759
760private:
761
762 template<class Y> friend class shared_ptr;
763 template<class Y> friend class weak_ptr;
764
765
766#endif
767
768 element_type * px; // contained pointer
769 boost::detail::shared_count pn; // reference counter
770
771}; // shared_ptr
772
773template<class T, class U> inline bool operator==(shared_ptr<T> const & a, shared_ptr<U> const & b) BOOST_NOEXCEPT
774{
775 return a.get() == b.get();
776}
777
778template<class T, class U> inline bool operator!=(shared_ptr<T> const & a, shared_ptr<U> const & b) BOOST_NOEXCEPT
779{
780 return a.get() != b.get();
781}
782
783#if __GNUC__ == 2 && __GNUC_MINOR__ <= 96
784
785// Resolve the ambiguity between our op!= and the one in rel_ops
786
787template<class T> inline bool operator!=(shared_ptr<T> const & a, shared_ptr<T> const & b) BOOST_NOEXCEPT
788{
789 return a.get() != b.get();
790}
791
792#endif
793
794#if !defined( BOOST_NO_CXX11_NULLPTR )
795
796template<class T> inline bool operator==( shared_ptr<T> const & p, boost::detail::sp_nullptr_t ) BOOST_NOEXCEPT
797{
798 return p.get() == 0;
799}
800
801template<class T> inline bool operator==( boost::detail::sp_nullptr_t, shared_ptr<T> const & p ) BOOST_NOEXCEPT
802{
803 return p.get() == 0;
804}
805
806template<class T> inline bool operator!=( shared_ptr<T> const & p, boost::detail::sp_nullptr_t ) BOOST_NOEXCEPT
807{
808 return p.get() != 0;
809}
810
811template<class T> inline bool operator!=( boost::detail::sp_nullptr_t, shared_ptr<T> const & p ) BOOST_NOEXCEPT
812{
813 return p.get() != 0;
814}
815
816#endif
817
818template<class T, class U> inline bool operator<(shared_ptr<T> const & a, shared_ptr<U> const & b) BOOST_NOEXCEPT
819{
820 return a.owner_before( b );
821}
822
823template<class T> inline void swap(shared_ptr<T> & a, shared_ptr<T> & b) BOOST_NOEXCEPT
824{
825 a.swap(b);
826}
827
828template<class T, class U> shared_ptr<T> static_pointer_cast( shared_ptr<U> const & r ) BOOST_NOEXCEPT
829{
830 (void) static_cast< T* >( static_cast< U* >( 0 ) );
831
832 typedef typename shared_ptr<T>::element_type E;
833
834 E * p = static_cast< E* >( r.get() );
835 return shared_ptr<T>( r, p );
836}
837
838template<class T, class U> shared_ptr<T> const_pointer_cast( shared_ptr<U> const & r ) BOOST_NOEXCEPT
839{
840 (void) const_cast< T* >( static_cast< U* >( 0 ) );
841
842 typedef typename shared_ptr<T>::element_type E;
843
844 E * p = const_cast< E* >( r.get() );
845 return shared_ptr<T>( r, p );
846}
847
848template<class T, class U> shared_ptr<T> dynamic_pointer_cast( shared_ptr<U> const & r ) BOOST_NOEXCEPT
849{
850 (void) dynamic_cast< T* >( static_cast< U* >( 0 ) );
851
852 typedef typename shared_ptr<T>::element_type E;
853
854 E * p = dynamic_cast< E* >( r.get() );
855 return p? shared_ptr<T>( r, p ): shared_ptr<T>();
856}
857
858template<class T, class U> shared_ptr<T> reinterpret_pointer_cast( shared_ptr<U> const & r ) BOOST_NOEXCEPT
859{
860 (void) reinterpret_cast< T* >( static_cast< U* >( 0 ) );
861
862 typedef typename shared_ptr<T>::element_type E;
863
864 E * p = reinterpret_cast< E* >( r.get() );
865 return shared_ptr<T>( r, p );
866}
867
868// get_pointer() enables boost::mem_fn to recognize shared_ptr
869
870template<class T> inline typename shared_ptr<T>::element_type * get_pointer(shared_ptr<T> const & p) BOOST_NOEXCEPT
871{
872 return p.get();
873}
874
875// operator<<
876
877#if !defined(BOOST_NO_IOSTREAM)
878
879#if defined(BOOST_NO_TEMPLATED_IOSTREAMS) || ( defined(__GNUC__) && (__GNUC__ < 3) )
880
881template<class Y> std::ostream & operator<< (std::ostream & os, shared_ptr<Y> const & p)
882{
883 os << p.get();
884 return os;
885}
886
887#else
888
889// in STLport's no-iostreams mode no iostream symbols can be used
890#ifndef _STLP_NO_IOSTREAMS
891
892# if defined(BOOST_MSVC) && BOOST_WORKAROUND(BOOST_MSVC, < 1300 && __SGI_STL_PORT)
893// MSVC6 has problems finding std::basic_ostream through the using declaration in namespace _STL
894using std::basic_ostream;
895template<class E, class T, class Y> basic_ostream<E, T> & operator<< (basic_ostream<E, T> & os, shared_ptr<Y> const & p)
896# else
897template<class E, class T, class Y> std::basic_ostream<E, T> & operator<< (std::basic_ostream<E, T> & os, shared_ptr<Y> const & p)
898# endif
899{
900 os << p.get();
901 return os;
902}
903
904#endif // _STLP_NO_IOSTREAMS
905
906#endif // __GNUC__ < 3
907
908#endif // !defined(BOOST_NO_IOSTREAM)
909
910// get_deleter
911
912namespace detail
913{
914
915#if ( defined(__GNUC__) && BOOST_WORKAROUND(__GNUC__, < 3) ) || \
916 ( defined(__EDG_VERSION__) && BOOST_WORKAROUND(__EDG_VERSION__, <= 238) ) || \
917 ( defined(__HP_aCC) && BOOST_WORKAROUND(__HP_aCC, <= 33500) )
918
919// g++ 2.9x doesn't allow static_cast<X const *>(void *)
920// apparently EDG 2.38 and HP aCC A.03.35 also don't accept it
921
922template<class D, class T> D * basic_get_deleter(shared_ptr<T> const & p)
923{
924 void const * q = p._internal_get_deleter(BOOST_SP_TYPEID(D));
925 return const_cast<D *>(static_cast<D const *>(q));
926}
927
928#else
929
930template<class D, class T> D * basic_get_deleter( shared_ptr<T> const & p ) BOOST_NOEXCEPT
931{
932 return static_cast<D *>( p._internal_get_deleter(BOOST_SP_TYPEID(D)) );
933}
934
935#endif
936
937class esft2_deleter_wrapper
938{
939private:
940
941 shared_ptr<void const volatile> deleter_;
942
943public:
944
945 esft2_deleter_wrapper()
946 {
947 }
948
949 template< class T > void set_deleter( shared_ptr<T> const & deleter )
950 {
951 deleter_ = deleter;
952 }
953
954 template<typename D> D* get_deleter() const BOOST_NOEXCEPT
955 {
956 return boost::detail::basic_get_deleter<D>( deleter_ );
957 }
958
959 template< class T> void operator()( T* )
960 {
961 BOOST_ASSERT( deleter_.use_count() <= 1 );
962 deleter_.reset();
963 }
964};
965
966} // namespace detail
967
968template<class D, class T> D * get_deleter( shared_ptr<T> const & p ) BOOST_NOEXCEPT
969{
970 D *del = boost::detail::basic_get_deleter<D>(p);
971
972 if(del == 0)
973 {
974 boost::detail::esft2_deleter_wrapper *del_wrapper = boost::detail::basic_get_deleter<boost::detail::esft2_deleter_wrapper>(p);
975// The following get_deleter method call is fully qualified because
976// older versions of gcc (2.95, 3.2.3) fail to compile it when written del_wrapper->get_deleter<D>()
977 if(del_wrapper) del = del_wrapper->::boost::detail::esft2_deleter_wrapper::get_deleter<D>();
978 }
979
980 return del;
981}
982
983// atomic access
984
985#if !defined(BOOST_SP_NO_ATOMIC_ACCESS)
986
987template<class T> inline bool atomic_is_lock_free( shared_ptr<T> const * /*p*/ ) BOOST_NOEXCEPT
988{
989 return false;
990}
991
992template<class T> shared_ptr<T> atomic_load( shared_ptr<T> const * p )
993{
994 boost::detail::spinlock_pool<2>::scoped_lock lock( p );
995 return *p;
996}
997
998template<class T> inline shared_ptr<T> atomic_load_explicit( shared_ptr<T> const * p, /*memory_order mo*/ int )
999{
1000 return atomic_load( p );
1001}
1002
1003template<class T> void atomic_store( shared_ptr<T> * p, shared_ptr<T> r )
1004{
1005 boost::detail::spinlock_pool<2>::scoped_lock lock( p );
1006 p->swap( r );
1007}
1008
1009template<class T> inline void atomic_store_explicit( shared_ptr<T> * p, shared_ptr<T> r, /*memory_order mo*/ int )
1010{
1011 atomic_store( p, r ); // std::move( r )
1012}
1013
1014template<class T> shared_ptr<T> atomic_exchange( shared_ptr<T> * p, shared_ptr<T> r )
1015{
1016 boost::detail::spinlock & sp = boost::detail::spinlock_pool<2>::spinlock_for( p );
1017
1018 sp.lock();
1019 p->swap( r );
1020 sp.unlock();
1021
1022 return r; // return std::move( r )
1023}
1024
1025template<class T> shared_ptr<T> atomic_exchange_explicit( shared_ptr<T> * p, shared_ptr<T> r, /*memory_order mo*/ int )
1026{
1027 return atomic_exchange( p, r ); // std::move( r )
1028}
1029
1030template<class T> bool atomic_compare_exchange( shared_ptr<T> * p, shared_ptr<T> * v, shared_ptr<T> w )
1031{
1032 boost::detail::spinlock & sp = boost::detail::spinlock_pool<2>::spinlock_for( p );
1033
1034 sp.lock();
1035
1036 if( p->_internal_equiv( *v ) )
1037 {
1038 p->swap( w );
1039
1040 sp.unlock();
1041
1042 return true;
1043 }
1044 else
1045 {
1046 shared_ptr<T> tmp( *p );
1047
1048 sp.unlock();
1049
1050 tmp.swap( *v );
1051 return false;
1052 }
1053}
1054
1055template<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 )
1056{
1057 return atomic_compare_exchange( p, v, w ); // std::move( w )
1058}
1059
1060#endif // !defined(BOOST_SP_NO_ATOMIC_ACCESS)
1061
1062// hash_value
1063
1064template< class T > struct hash;
1065
1066template< class T > std::size_t hash_value( boost::shared_ptr<T> const & p ) BOOST_NOEXCEPT
1067{
1068 return boost::hash< T* >()( p.get() );
1069}
1070
1071} // namespace boost
1072
1073#if defined( BOOST_SP_DISABLE_DEPRECATED )
1074#pragma GCC diagnostic pop
1075#endif
1076
1077#endif // #ifndef BOOST_SMART_PTR_SHARED_PTR_HPP_INCLUDED
1078