]> git.proxmox.com Git - ceph.git/blob - 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
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
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 {
232 template<class T> sp_any_pointer( T* ) {}
233 };
234
235 inline void sp_enable_shared_from_this( sp_any_pointer, sp_any_pointer, sp_any_pointer )
236 {
237 }
238
239 #else // _MANAGED
240
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
840 template<class T> inline void swap(shared_ptr<T> & a, shared_ptr<T> & b) BOOST_NOEXCEPT
841 {
842 a.swap(b);
843 }
844
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
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
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
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
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
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;
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
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
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
1004 template<class T> inline bool atomic_is_lock_free( shared_ptr<T> const * /*p*/ ) BOOST_NOEXCEPT
1005 {
1006 return false;
1007 }
1008
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
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
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
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
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
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
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
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
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