]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/libs/smart_ptr/include/boost/smart_ptr/shared_ptr.hpp
bump version to 12.2.2-pve1
[ceph.git] / ceph / src / boost / libs / smart_ptr / include / boost / smart_ptr / shared_ptr.hpp
CommitLineData
7c673cae
FG
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 // aliasing move
646 template<class Y>
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
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
665 void reset() BOOST_NOEXCEPT // never throws in 1.30+
666 {
667 this_type().swap(*this);
668 }
669
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
676 template<class Y, class D> void reset( Y * p, D d )
677 {
678 this_type( p, d ).swap( *this );
679 }
680
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
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
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)
701 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)
708 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)
715 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
723 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
731 bool unique() const BOOST_NOEXCEPT
732 {
733 return pn.unique();
734 }
735
736 long use_count() const BOOST_NOEXCEPT
737 {
738 return pn.use_count();
739 }
740
741 void swap( shared_ptr & other ) BOOST_NOEXCEPT
742 {
743 std::swap(px, other.px);
744 pn.swap(other.pn);
745 }
746
747 template<class Y> bool owner_before( shared_ptr<Y> const & rhs ) const BOOST_NOEXCEPT
748 {
749 return pn < rhs.pn;
750 }
751
752 template<class Y> bool owner_before( weak_ptr<Y> const & rhs ) const BOOST_NOEXCEPT
753 {
754 return pn < rhs.pn;
755 }
756
757 void * _internal_get_deleter( boost::detail::sp_typeinfo const & ti ) const BOOST_NOEXCEPT
758 {
759 return pn.get_deleter( ti );
760 }
761
762 void * _internal_get_untyped_deleter() const BOOST_NOEXCEPT
763 {
764 return pn.get_untyped_deleter();
765 }
766
767 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
777private:
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
790template<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
795template<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
804template<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
813template<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
818template<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
823template<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
828template<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
835template<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
840template<class T> inline void swap(shared_ptr<T> & a, shared_ptr<T> & b) BOOST_NOEXCEPT
841{
842 a.swap(b);
843}
844
845template<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
855template<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
865template<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
875template<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
887template<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
898template<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
911using std::basic_ostream;
912template<class E, class T, class Y> basic_ostream<E, T> & operator<< (basic_ostream<E, T> & os, shared_ptr<Y> const & p)
913# else
914template<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
929namespace 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
939template<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
947template<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
954class esft2_deleter_wrapper
955{
956private:
957
958 shared_ptr<void const volatile> deleter_;
959
960public:
961
962 esft2_deleter_wrapper()
963 {
964 }
965
966 template< class T > void set_deleter( shared_ptr<T> const & deleter )
967 {
968 deleter_ = deleter;
969 }
970
971 template<typename D> D* get_deleter() const BOOST_NOEXCEPT
972 {
973 return boost::detail::basic_get_deleter<D>( deleter_ );
974 }
975
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
985template<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
1004template<class T> inline bool atomic_is_lock_free( shared_ptr<T> const * /*p*/ ) BOOST_NOEXCEPT
1005{
1006 return false;
1007}
1008
1009template<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
1015template<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
1020template<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
1026template<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
1031template<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
1042template<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
1047template<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
1072template<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
1081template< class T > struct hash;
1082
1083template< 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