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/ for documentation.
15//
16
17#include <boost/smart_ptr/detail/requires_cxx11.hpp>
18#include <boost/smart_ptr/detail/shared_count.hpp>
19#include <boost/smart_ptr/detail/sp_convertible.hpp>
20#include <boost/smart_ptr/detail/sp_nullptr_t.hpp>
21#include <boost/smart_ptr/detail/sp_disable_deprecated.hpp>
22#include <boost/smart_ptr/detail/sp_noexcept.hpp>
23#include <boost/core/checked_delete.hpp>
24#include <boost/throw_exception.hpp>
25#include <boost/assert.hpp>
26#include <boost/config.hpp>
27#include <boost/config/workaround.hpp>
28
29#if !defined(BOOST_SP_NO_ATOMIC_ACCESS)
30#include <boost/smart_ptr/detail/spinlock_pool.hpp>
31#endif
32
33#include <algorithm> // for std::swap
34#include <functional> // for std::less
35#include <typeinfo> // for std::bad_cast
36#include <cstddef> // for std::size_t
37#include <memory> // for std::auto_ptr
38
39#if !defined(BOOST_NO_IOSTREAM)
40#if !defined(BOOST_NO_IOSFWD)
41#include <iosfwd> // for std::basic_ostream
42#else
43#include <ostream>
44#endif
45#endif
46
47#if defined( BOOST_SP_DISABLE_DEPRECATED )
48#pragma GCC diagnostic push
49#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
50#endif
51
52namespace boost
53{
54
55template<class T> class shared_ptr;
56template<class T> class weak_ptr;
57template<class T> class enable_shared_from_this;
58class enable_shared_from_raw;
59
60namespace movelib
61{
62
63 template< class T, class D > class unique_ptr;
64
65} // namespace movelib
66
67namespace detail
68{
69
70// sp_element, element_type
71
72template< class T > struct sp_element
73{
74 typedef T type;
75};
76
77#if !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
78
79template< class T > struct sp_element< T[] >
80{
81 typedef T type;
82};
83
84#if !defined( BOOST_BORLANDC ) || !BOOST_WORKAROUND( BOOST_BORLANDC, < 0x600 )
85
86template< class T, std::size_t N > struct sp_element< T[N] >
87{
88 typedef T type;
89};
90
91#endif
92
93#endif // !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
94
95// sp_dereference, return type of operator*
96
97template< class T > struct sp_dereference
98{
99 typedef T & type;
100};
101
102template<> struct sp_dereference< void >
103{
104 typedef void type;
105};
106
107#if !defined(BOOST_NO_CV_VOID_SPECIALIZATIONS)
108
109template<> struct sp_dereference< void const >
110{
111 typedef void type;
112};
113
114template<> struct sp_dereference< void volatile >
115{
116 typedef void type;
117};
118
119template<> struct sp_dereference< void const volatile >
120{
121 typedef void type;
122};
123
124#endif // !defined(BOOST_NO_CV_VOID_SPECIALIZATIONS)
125
126#if !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
127
128template< class T > struct sp_dereference< T[] >
129{
130 typedef void type;
131};
132
133#if !defined( BOOST_BORLANDC ) || !BOOST_WORKAROUND( BOOST_BORLANDC, < 0x600 )
134
135template< class T, std::size_t N > struct sp_dereference< T[N] >
136{
137 typedef void type;
138};
139
140#endif
141
142#endif // !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
143
144// sp_member_access, return type of operator->
145
146template< class T > struct sp_member_access
147{
148 typedef T * type;
149};
150
151#if !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
152
153template< class T > struct sp_member_access< T[] >
154{
155 typedef void type;
156};
157
158#if !defined( BOOST_BORLANDC ) || !BOOST_WORKAROUND( BOOST_BORLANDC, < 0x600 )
159
160template< class T, std::size_t N > struct sp_member_access< T[N] >
161{
162 typedef void type;
163};
164
165#endif
166
167#endif // !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
168
169// sp_array_access, return type of operator[]
170
171template< class T > struct sp_array_access
172{
173 typedef void type;
174};
175
176#if !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
177
178template< class T > struct sp_array_access< T[] >
179{
180 typedef T & type;
181};
182
183#if !defined( BOOST_BORLANDC ) || !BOOST_WORKAROUND( BOOST_BORLANDC, < 0x600 )
184
185template< class T, std::size_t N > struct sp_array_access< T[N] >
186{
187 typedef T & type;
188};
189
190#endif
191
192#endif // !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
193
194// sp_extent, for operator[] index check
195
196template< class T > struct sp_extent
197{
198 enum _vt { value = 0 };
199};
200
201#if !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
202
203template< class T, std::size_t N > struct sp_extent< T[N] >
204{
205 enum _vt { value = N };
206};
207
208#endif // !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
209
210// enable_shared_from_this support
211
212template< 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 )
213{
214 if( pe != 0 )
215 {
216 pe->_internal_accept_owner( ppx, const_cast< Y* >( py ) );
217 }
218}
219
220template< 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 );
221
222#ifdef _MANAGED
223
224// Avoid C4793, ... causes native code generation
225
226struct sp_any_pointer
227{
228 template<class T> sp_any_pointer( T* ) {}
229};
230
231inline void sp_enable_shared_from_this( sp_any_pointer, sp_any_pointer, sp_any_pointer )
232{
233}
234
235#else // _MANAGED
236
237inline void sp_enable_shared_from_this( ... )
238{
239}
240
241#endif // _MANAGED
242
243#if !defined( BOOST_NO_SFINAE ) && !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION ) && !defined( BOOST_NO_AUTO_PTR )
244
245// rvalue auto_ptr support based on a technique by Dave Abrahams
246
247template< class T, class R > struct sp_enable_if_auto_ptr
248{
249};
250
251template< class T, class R > struct sp_enable_if_auto_ptr< std::auto_ptr< T >, R >
252{
253 typedef R type;
254};
255
256#endif
257
258// sp_assert_convertible
259
260template< class Y, class T > inline void sp_assert_convertible() BOOST_SP_NOEXCEPT
261{
262#if !defined( BOOST_SP_NO_SP_CONVERTIBLE )
263
264 // static_assert( sp_convertible< Y, T >::value );
265 typedef char tmp[ sp_convertible< Y, T >::value? 1: -1 ];
266 (void)sizeof( tmp );
267
268#else
269
270 T* p = static_cast< Y* >( 0 );
271 (void)p;
272
273#endif
274}
275
276// pointer constructor helper
277
278template< class T, class Y > inline void sp_pointer_construct( boost::shared_ptr< T > * ppx, Y * p, boost::detail::shared_count & pn )
279{
280 boost::detail::shared_count( p ).swap( r&: pn );
281 boost::detail::sp_enable_shared_from_this( ppx, p, p );
282}
283
284#if !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
285
286template< class T, class Y > inline void sp_pointer_construct( boost::shared_ptr< T[] > * /*ppx*/, Y * p, boost::detail::shared_count & pn )
287{
288 sp_assert_convertible< Y[], T[] >();
289 boost::detail::shared_count( p, boost::checked_array_deleter< T >() ).swap( r&: pn );
290}
291
292template< 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 )
293{
294 sp_assert_convertible< Y[N], T[N] >();
295 boost::detail::shared_count( p, boost::checked_array_deleter< T >() ).swap( r&: pn );
296}
297
298#endif // !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
299
300// deleter constructor helper
301
302template< class T, class Y > inline void sp_deleter_construct( boost::shared_ptr< T > * ppx, Y * p )
303{
304 boost::detail::sp_enable_shared_from_this( ppx, p, p );
305}
306
307#if !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
308
309template< class T, class Y > inline void sp_deleter_construct( boost::shared_ptr< T[] > * /*ppx*/, Y * /*p*/ )
310{
311 sp_assert_convertible< Y[], T[] >();
312}
313
314template< class T, std::size_t N, class Y > inline void sp_deleter_construct( boost::shared_ptr< T[N] > * /*ppx*/, Y * /*p*/ )
315{
316 sp_assert_convertible< Y[N], T[N] >();
317}
318
319#endif // !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
320
321struct sp_internal_constructor_tag
322{
323};
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 BOOST_CONSTEXPR shared_ptr() BOOST_SP_NOEXCEPT : px( 0 ), pn()
348 {
349 }
350
351#if !defined( BOOST_NO_CXX11_NULLPTR )
352
353 BOOST_CONSTEXPR shared_ptr( boost::detail::sp_nullptr_t ) BOOST_SP_NOEXCEPT : px( 0 ), pn()
354 {
355 }
356
357#endif
358
359 BOOST_CONSTEXPR shared_ptr( boost::detail::sp_internal_constructor_tag, element_type * px_, boost::detail::shared_count const & pn_ ) BOOST_SP_NOEXCEPT : px( px_ ), pn( pn_ )
360 {
361 }
362
363#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
364
365 BOOST_CONSTEXPR shared_ptr( boost::detail::sp_internal_constructor_tag, element_type * px_, boost::detail::shared_count && pn_ ) BOOST_SP_NOEXCEPT : px( px_ ), pn( std::move( pn_ ) )
366 {
367 }
368
369#endif
370
371 template<class Y>
372 explicit shared_ptr( Y * p ): px( p ), pn() // Y must be complete
373 {
374 boost::detail::sp_pointer_construct( this, p, pn );
375 }
376
377 //
378 // Requirements: D's copy/move constructors must not throw
379 //
380 // shared_ptr will release p by calling d(p)
381 //
382
383#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
384
385 template<class Y, class D> shared_ptr( Y * p, D d ): px( p ), pn( p, static_cast< D&& >( d ) )
386 {
387 boost::detail::sp_deleter_construct( this, p );
388 }
389
390#else
391
392 template<class Y, class D> shared_ptr( Y * p, D d ): px( p ), pn( p, d )
393 {
394 boost::detail::sp_deleter_construct( this, p );
395 }
396
397#endif
398
399#if !defined( BOOST_NO_CXX11_NULLPTR )
400
401#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
402
403 template<class D> shared_ptr( boost::detail::sp_nullptr_t p, D d ): px( p ), pn( p, static_cast< D&& >( d ) )
404 {
405 }
406
407#else
408
409 template<class D> shared_ptr( boost::detail::sp_nullptr_t p, D d ): px( p ), pn( p, d )
410 {
411 }
412
413#endif
414
415#endif
416
417 // As above, but with allocator. A's copy constructor shall not throw.
418
419#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
420
421 template<class Y, class D, class A> shared_ptr( Y * p, D d, A a ): px( p ), pn( p, static_cast< D&& >( d ), a )
422 {
423 boost::detail::sp_deleter_construct( this, p );
424 }
425
426#else
427
428 template<class Y, class D, class A> shared_ptr( Y * p, D d, A a ): px( p ), pn( p, d, a )
429 {
430 boost::detail::sp_deleter_construct( this, p );
431 }
432
433#endif
434
435#if !defined( BOOST_NO_CXX11_NULLPTR )
436
437#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
438
439 template<class D, class A> shared_ptr( boost::detail::sp_nullptr_t p, D d, A a ): px( p ), pn( p, static_cast< D&& >( d ), a )
440 {
441 }
442
443#else
444
445 template<class D, class A> shared_ptr( boost::detail::sp_nullptr_t p, D d, A a ): px( p ), pn( p, d, a )
446 {
447 }
448
449#endif
450
451#endif
452
453// generated copy constructor, destructor are fine...
454
455#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
456
457// ... except in C++0x, move disables the implicit copy
458
459 shared_ptr( shared_ptr const & r ) BOOST_SP_NOEXCEPT : px( r.px ), pn( r.pn )
460 {
461 }
462
463#endif
464
465 template<class Y>
466 explicit shared_ptr( weak_ptr<Y> const & r ): pn( r.pn ) // may throw
467 {
468 boost::detail::sp_assert_convertible< Y, T >();
469
470 // it is now safe to copy r.px, as pn(r.pn) did not throw
471 px = r.px;
472 }
473
474 template<class Y>
475 shared_ptr( weak_ptr<Y> const & r, boost::detail::sp_nothrow_tag )
476 BOOST_SP_NOEXCEPT : px( 0 ), pn( r.pn, boost::detail::sp_nothrow_tag() )
477 {
478 if( !pn.empty() )
479 {
480 px = r.px;
481 }
482 }
483
484 template<class Y>
485#if !defined( BOOST_SP_NO_SP_CONVERTIBLE )
486
487 shared_ptr( shared_ptr<Y> const & r, typename boost::detail::sp_enable_if_convertible<Y,T>::type = boost::detail::sp_empty() )
488
489#else
490
491 shared_ptr( shared_ptr<Y> const & r )
492
493#endif
494 BOOST_SP_NOEXCEPT : px( r.px ), pn( r.pn )
495 {
496 boost::detail::sp_assert_convertible< Y, T >();
497 }
498
499 // aliasing
500 template< class Y >
501 shared_ptr( shared_ptr<Y> const & r, element_type * p ) BOOST_SP_NOEXCEPT : px( p ), pn( r.pn )
502 {
503 }
504
505#ifndef BOOST_NO_AUTO_PTR
506
507 template<class Y>
508 explicit shared_ptr( std::auto_ptr<Y> & r ): px(r.get()), pn()
509 {
510 boost::detail::sp_assert_convertible< Y, T >();
511
512 Y * tmp = r.get();
513 pn = boost::detail::shared_count( r );
514
515 boost::detail::sp_deleter_construct( this, tmp );
516 }
517
518#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
519
520 template<class Y>
521 shared_ptr( std::auto_ptr<Y> && r ): px(r.get()), pn()
522 {
523 boost::detail::sp_assert_convertible< Y, T >();
524
525 Y * tmp = r.get();
526 pn = boost::detail::shared_count( r );
527
528 boost::detail::sp_deleter_construct( this, tmp );
529 }
530
531#elif !defined( BOOST_NO_SFINAE ) && !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
532
533 template<class Ap>
534 explicit shared_ptr( Ap r, typename boost::detail::sp_enable_if_auto_ptr<Ap, int>::type = 0 ): px( r.get() ), pn()
535 {
536 typedef typename Ap::element_type Y;
537
538 boost::detail::sp_assert_convertible< Y, T >();
539
540 Y * tmp = r.get();
541 pn = boost::detail::shared_count( r );
542
543 boost::detail::sp_deleter_construct( this, tmp );
544 }
545
546#endif // BOOST_NO_SFINAE, BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
547
548#endif // BOOST_NO_AUTO_PTR
549
550#if !defined( BOOST_NO_CXX11_SMART_PTR ) && !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
551
552 template< class Y, class D >
553 shared_ptr( std::unique_ptr< Y, D > && r ): px( r.get() ), pn()
554 {
555 boost::detail::sp_assert_convertible< Y, T >();
556
557 typename std::unique_ptr< Y, D >::pointer tmp = r.get();
558
559 if( tmp != 0 )
560 {
561 pn = boost::detail::shared_count( r );
562 boost::detail::sp_deleter_construct( this, tmp );
563 }
564 }
565
566#endif
567
568 template< class Y, class D >
569 shared_ptr( boost::movelib::unique_ptr< Y, D > r ): px( r.get() ), pn()
570 {
571 boost::detail::sp_assert_convertible< Y, T >();
572
573 typename boost::movelib::unique_ptr< Y, D >::pointer tmp = r.get();
574
575 if( tmp != 0 )
576 {
577 pn = boost::detail::shared_count( r );
578 boost::detail::sp_deleter_construct( this, tmp );
579 }
580 }
581
582 // assignment
583
584 shared_ptr & operator=( shared_ptr const & r ) BOOST_SP_NOEXCEPT
585 {
586 this_type(r).swap(*this);
587 return *this;
588 }
589
590#if !defined(BOOST_MSVC) || (BOOST_MSVC >= 1400)
591
592 template<class Y>
593 shared_ptr & operator=(shared_ptr<Y> const & r) BOOST_SP_NOEXCEPT
594 {
595 this_type(r).swap(*this);
596 return *this;
597 }
598
599#endif
600
601#ifndef BOOST_NO_AUTO_PTR
602
603 template<class Y>
604 shared_ptr & operator=( std::auto_ptr<Y> & r )
605 {
606 this_type( r ).swap( *this );
607 return *this;
608 }
609
610#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
611
612 template<class Y>
613 shared_ptr & operator=( std::auto_ptr<Y> && r )
614 {
615 this_type( static_cast< std::auto_ptr<Y> && >( r ) ).swap( *this );
616 return *this;
617 }
618
619#elif !defined( BOOST_NO_SFINAE ) && !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
620
621 template<class Ap>
622 typename boost::detail::sp_enable_if_auto_ptr< Ap, shared_ptr & >::type operator=( Ap r )
623 {
624 this_type( r ).swap( *this );
625 return *this;
626 }
627
628#endif // BOOST_NO_SFINAE, BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
629
630#endif // BOOST_NO_AUTO_PTR
631
632#if !defined( BOOST_NO_CXX11_SMART_PTR ) && !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
633
634 template<class Y, class D>
635 shared_ptr & operator=( std::unique_ptr<Y, D> && r )
636 {
637 this_type( static_cast< std::unique_ptr<Y, D> && >( r ) ).swap(*this);
638 return *this;
639 }
640
641#endif
642
643 template<class Y, class D>
644 shared_ptr & operator=( boost::movelib::unique_ptr<Y, D> r )
645 {
646 // this_type( static_cast< unique_ptr<Y, D> && >( r ) ).swap( *this );
647
648 boost::detail::sp_assert_convertible< Y, T >();
649
650 typename boost::movelib::unique_ptr< Y, D >::pointer p = r.get();
651
652 shared_ptr tmp;
653
654 if( p != 0 )
655 {
656 tmp.px = p;
657 tmp.pn = boost::detail::shared_count( r );
658
659 boost::detail::sp_deleter_construct( &tmp, p );
660 }
661
662 tmp.swap( *this );
663
664 return *this;
665 }
666
667// Move support
668
669#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
670
671 shared_ptr( shared_ptr && r ) BOOST_SP_NOEXCEPT : px( r.px ), pn( static_cast< boost::detail::shared_count && >( r.pn ) )
672 {
673 r.px = 0;
674 }
675
676 template<class Y>
677#if !defined( BOOST_SP_NO_SP_CONVERTIBLE )
678
679 shared_ptr( shared_ptr<Y> && r, typename boost::detail::sp_enable_if_convertible<Y,T>::type = boost::detail::sp_empty() )
680
681#else
682
683 shared_ptr( shared_ptr<Y> && r )
684
685#endif
686 BOOST_SP_NOEXCEPT : px( r.px ), pn( static_cast< boost::detail::shared_count && >( r.pn ) )
687 {
688 boost::detail::sp_assert_convertible< Y, T >();
689 r.px = 0;
690 }
691
692 shared_ptr & operator=( shared_ptr && r ) BOOST_SP_NOEXCEPT
693 {
694 this_type( static_cast< shared_ptr && >( r ) ).swap( *this );
695 return *this;
696 }
697
698 template<class Y>
699 shared_ptr & operator=( shared_ptr<Y> && r ) BOOST_SP_NOEXCEPT
700 {
701 this_type( static_cast< shared_ptr<Y> && >( r ) ).swap( *this );
702 return *this;
703 }
704
705 // aliasing move
706 template<class Y>
707 shared_ptr( shared_ptr<Y> && r, element_type * p ) BOOST_SP_NOEXCEPT : px( p ), pn()
708 {
709 pn.swap( r&: r.pn );
710 r.px = 0;
711 }
712
713#endif
714
715#if !defined( BOOST_NO_CXX11_NULLPTR )
716
717 shared_ptr & operator=( boost::detail::sp_nullptr_t ) BOOST_SP_NOEXCEPT
718 {
719 this_type().swap(*this);
720 return *this;
721 }
722
723#endif
724
725 void reset() BOOST_SP_NOEXCEPT
726 {
727 this_type().swap(*this);
728 }
729
730 template<class Y> void reset( Y * p ) // Y must be complete
731 {
732 BOOST_ASSERT( p == 0 || p != px ); // catch self-reset errors
733 this_type( p ).swap( *this );
734 }
735
736#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
737
738 template<class Y, class D> void reset( Y * p, D d )
739 {
740 this_type( p, static_cast< D&& >( d ) ).swap( *this );
741 }
742
743 template<class Y, class D, class A> void reset( Y * p, D d, A a )
744 {
745 this_type( p, static_cast< D&& >( d ), a ).swap( *this );
746 }
747
748#else
749
750 template<class Y, class D> void reset( Y * p, D d )
751 {
752 this_type( p, d ).swap( *this );
753 }
754
755 template<class Y, class D, class A> void reset( Y * p, D d, A a )
756 {
757 this_type( p, d, a ).swap( *this );
758 }
759
760#endif
761
762 template<class Y> void reset( shared_ptr<Y> const & r, element_type * p ) BOOST_SP_NOEXCEPT
763 {
764 this_type( r, p ).swap( *this );
765 }
766
767#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
768
769 template<class Y> void reset( shared_ptr<Y> && r, element_type * p ) BOOST_SP_NOEXCEPT
770 {
771 this_type( static_cast< shared_ptr<Y> && >( r ), p ).swap( *this );
772 }
773
774#endif
775
776 typename boost::detail::sp_dereference< T >::type operator* () const BOOST_SP_NOEXCEPT_WITH_ASSERT
777 {
778 BOOST_ASSERT( px != 0 );
779 return *px;
780 }
781
782 typename boost::detail::sp_member_access< T >::type operator-> () const BOOST_SP_NOEXCEPT_WITH_ASSERT
783 {
784 BOOST_ASSERT( px != 0 );
785 return px;
786 }
787
788 typename boost::detail::sp_array_access< T >::type operator[] ( std::ptrdiff_t i ) const BOOST_SP_NOEXCEPT_WITH_ASSERT
789 {
790 BOOST_ASSERT( px != 0 );
791 BOOST_ASSERT( i >= 0 && ( i < boost::detail::sp_extent< T >::value || boost::detail::sp_extent< T >::value == 0 ) );
792
793 return static_cast< typename boost::detail::sp_array_access< T >::type >( px[ i ] );
794 }
795
796 element_type * get() const BOOST_SP_NOEXCEPT
797 {
798 return px;
799 }
800
801// implicit conversion to "bool"
802#include <boost/smart_ptr/detail/operator_bool.hpp>
803
804 bool unique() const BOOST_SP_NOEXCEPT
805 {
806 return pn.unique();
807 }
808
809 long use_count() const BOOST_SP_NOEXCEPT
810 {
811 return pn.use_count();
812 }
813
814 void swap( shared_ptr & other ) BOOST_SP_NOEXCEPT
815 {
816 std::swap(px, other.px);
817 pn.swap(r&: other.pn);
818 }
819
820 template<class Y> bool owner_before( shared_ptr<Y> const & rhs ) const BOOST_SP_NOEXCEPT
821 {
822 return pn < rhs.pn;
823 }
824
825 template<class Y> bool owner_before( weak_ptr<Y> const & rhs ) const BOOST_SP_NOEXCEPT
826 {
827 return pn < rhs.pn;
828 }
829
830 template<class Y> bool owner_equals( shared_ptr<Y> const & rhs ) const BOOST_SP_NOEXCEPT
831 {
832 return pn == rhs.pn;
833 }
834
835 template<class Y> bool owner_equals( weak_ptr<Y> const & rhs ) const BOOST_SP_NOEXCEPT
836 {
837 return pn == rhs.pn;
838 }
839
840 std::size_t owner_hash_value() const BOOST_SP_NOEXCEPT
841 {
842 return pn.hash_value();
843 }
844
845 void * _internal_get_deleter( boost::detail::sp_typeinfo_ const & ti ) const BOOST_SP_NOEXCEPT
846 {
847 return pn.get_deleter( ti );
848 }
849
850 void * _internal_get_local_deleter( boost::detail::sp_typeinfo_ const & ti ) const BOOST_SP_NOEXCEPT
851 {
852 return pn.get_local_deleter( ti );
853 }
854
855 void * _internal_get_untyped_deleter() const BOOST_SP_NOEXCEPT
856 {
857 return pn.get_untyped_deleter();
858 }
859
860 bool _internal_equiv( shared_ptr const & r ) const BOOST_SP_NOEXCEPT
861 {
862 return px == r.px && pn == r.pn;
863 }
864
865 boost::detail::shared_count _internal_count() const BOOST_SP_NOEXCEPT
866 {
867 return pn;
868 }
869
870// Tasteless as this may seem, making all members public allows member templates
871// to work in the absence of member template friends. (Matthew Langston)
872
873#ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS
874
875private:
876
877 template<class Y> friend class shared_ptr;
878 template<class Y> friend class weak_ptr;
879
880
881#endif
882
883 element_type * px; // contained pointer
884 boost::detail::shared_count pn; // reference counter
885
886}; // shared_ptr
887
888template<class T, class U> inline bool operator==(shared_ptr<T> const & a, shared_ptr<U> const & b) BOOST_SP_NOEXCEPT
889{
890 return a.get() == b.get();
891}
892
893template<class T, class U> inline bool operator!=(shared_ptr<T> const & a, shared_ptr<U> const & b) BOOST_SP_NOEXCEPT
894{
895 return a.get() != b.get();
896}
897
898#if !defined( BOOST_NO_CXX11_NULLPTR )
899
900template<class T> inline bool operator==( shared_ptr<T> const & p, boost::detail::sp_nullptr_t ) BOOST_SP_NOEXCEPT
901{
902 return p.get() == 0;
903}
904
905template<class T> inline bool operator==( boost::detail::sp_nullptr_t, shared_ptr<T> const & p ) BOOST_SP_NOEXCEPT
906{
907 return p.get() == 0;
908}
909
910template<class T> inline bool operator!=( shared_ptr<T> const & p, boost::detail::sp_nullptr_t ) BOOST_SP_NOEXCEPT
911{
912 return p.get() != 0;
913}
914
915template<class T> inline bool operator!=( boost::detail::sp_nullptr_t, shared_ptr<T> const & p ) BOOST_SP_NOEXCEPT
916{
917 return p.get() != 0;
918}
919
920#endif
921
922template<class T, class U> inline bool operator<(shared_ptr<T> const & a, shared_ptr<U> const & b) BOOST_SP_NOEXCEPT
923{
924 return a.owner_before( b );
925}
926
927template<class T> inline void swap(shared_ptr<T> & a, shared_ptr<T> & b) BOOST_SP_NOEXCEPT
928{
929 a.swap(b);
930}
931
932template<class T, class U> shared_ptr<T> static_pointer_cast( shared_ptr<U> const & r ) BOOST_SP_NOEXCEPT
933{
934 (void) static_cast< T* >( static_cast< U* >( 0 ) );
935
936 typedef typename shared_ptr<T>::element_type E;
937
938 E * p = static_cast< E* >( r.get() );
939 return shared_ptr<T>( r, p );
940}
941
942template<class T, class U> shared_ptr<T> const_pointer_cast( shared_ptr<U> const & r ) BOOST_SP_NOEXCEPT
943{
944 (void) const_cast< T* >( static_cast< U* >( 0 ) );
945
946 typedef typename shared_ptr<T>::element_type E;
947
948 E * p = const_cast< E* >( r.get() );
949 return shared_ptr<T>( r, p );
950}
951
952template<class T, class U> shared_ptr<T> dynamic_pointer_cast( shared_ptr<U> const & r ) BOOST_SP_NOEXCEPT
953{
954 (void) dynamic_cast< T* >( static_cast< U* >( 0 ) );
955
956 typedef typename shared_ptr<T>::element_type E;
957
958 E * p = dynamic_cast< E* >( r.get() );
959 return p? shared_ptr<T>( r, p ): shared_ptr<T>();
960}
961
962template<class T, class U> shared_ptr<T> reinterpret_pointer_cast( shared_ptr<U> const & r ) BOOST_SP_NOEXCEPT
963{
964 (void) reinterpret_cast< T* >( static_cast< U* >( 0 ) );
965
966 typedef typename shared_ptr<T>::element_type E;
967
968 E * p = reinterpret_cast< E* >( r.get() );
969 return shared_ptr<T>( r, p );
970}
971
972#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
973
974template<class T, class U> shared_ptr<T> static_pointer_cast( shared_ptr<U> && r ) BOOST_SP_NOEXCEPT
975{
976 (void) static_cast< T* >( static_cast< U* >( 0 ) );
977
978 typedef typename shared_ptr<T>::element_type E;
979
980 E * p = static_cast< E* >( r.get() );
981 return shared_ptr<T>( std::move(r), p );
982}
983
984template<class T, class U> shared_ptr<T> const_pointer_cast( shared_ptr<U> && r ) BOOST_SP_NOEXCEPT
985{
986 (void) const_cast< T* >( static_cast< U* >( 0 ) );
987
988 typedef typename shared_ptr<T>::element_type E;
989
990 E * p = const_cast< E* >( r.get() );
991 return shared_ptr<T>( std::move(r), p );
992}
993
994template<class T, class U> shared_ptr<T> dynamic_pointer_cast( shared_ptr<U> && r ) BOOST_SP_NOEXCEPT
995{
996 (void) dynamic_cast< T* >( static_cast< U* >( 0 ) );
997
998 typedef typename shared_ptr<T>::element_type E;
999
1000 E * p = dynamic_cast< E* >( r.get() );
1001 return p? shared_ptr<T>( std::move(r), p ): shared_ptr<T>();
1002}
1003
1004template<class T, class U> shared_ptr<T> reinterpret_pointer_cast( shared_ptr<U> && r ) BOOST_SP_NOEXCEPT
1005{
1006 (void) reinterpret_cast< T* >( static_cast< U* >( 0 ) );
1007
1008 typedef typename shared_ptr<T>::element_type E;
1009
1010 E * p = reinterpret_cast< E* >( r.get() );
1011 return shared_ptr<T>( std::move(r), p );
1012}
1013
1014#endif // !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
1015
1016// get_pointer() enables boost::mem_fn to recognize shared_ptr
1017
1018template<class T> inline typename shared_ptr<T>::element_type * get_pointer(shared_ptr<T> const & p) BOOST_SP_NOEXCEPT
1019{
1020 return p.get();
1021}
1022
1023// operator<<
1024
1025#if !defined(BOOST_NO_IOSTREAM)
1026
1027#if defined(BOOST_NO_TEMPLATED_IOSTREAMS) || ( defined(__GNUC__) && (__GNUC__ < 3) )
1028
1029template<class Y> std::ostream & operator<< (std::ostream & os, shared_ptr<Y> const & p)
1030{
1031 os << p.get();
1032 return os;
1033}
1034
1035#else
1036
1037// in STLport's no-iostreams mode no iostream symbols can be used
1038#ifndef _STLP_NO_IOSTREAMS
1039
1040# if defined(BOOST_MSVC) && BOOST_WORKAROUND(BOOST_MSVC, < 1300 && __SGI_STL_PORT)
1041// MSVC6 has problems finding std::basic_ostream through the using declaration in namespace _STL
1042using std::basic_ostream;
1043template<class E, class T, class Y> basic_ostream<E, T> & operator<< (basic_ostream<E, T> & os, shared_ptr<Y> const & p)
1044# else
1045template<class E, class T, class Y> std::basic_ostream<E, T> & operator<< (std::basic_ostream<E, T> & os, shared_ptr<Y> const & p)
1046# endif
1047{
1048 os << p.get();
1049 return os;
1050}
1051
1052#endif // _STLP_NO_IOSTREAMS
1053
1054#endif // __GNUC__ < 3
1055
1056#endif // !defined(BOOST_NO_IOSTREAM)
1057
1058// get_deleter
1059
1060namespace detail
1061{
1062
1063template<class D, class T> D * basic_get_deleter( shared_ptr<T> const & p ) BOOST_SP_NOEXCEPT
1064{
1065 return static_cast<D *>( p._internal_get_deleter(BOOST_SP_TYPEID_(D)) );
1066}
1067
1068template<class D, class T> D * basic_get_local_deleter( D *, shared_ptr<T> const & p ) BOOST_SP_NOEXCEPT;
1069template<class D, class T> D const * basic_get_local_deleter( D const *, shared_ptr<T> const & p ) BOOST_SP_NOEXCEPT;
1070
1071class esft2_deleter_wrapper
1072{
1073private:
1074
1075 shared_ptr<void const volatile> deleter_;
1076
1077public:
1078
1079 esft2_deleter_wrapper() BOOST_SP_NOEXCEPT
1080 {
1081 }
1082
1083 template< class T > void set_deleter( shared_ptr<T> const & deleter ) BOOST_SP_NOEXCEPT
1084 {
1085 deleter_ = deleter;
1086 }
1087
1088 template<typename D> D* get_deleter() const BOOST_SP_NOEXCEPT
1089 {
1090 return boost::detail::basic_get_deleter<D>( deleter_ );
1091 }
1092
1093 template< class T> void operator()( T* ) BOOST_SP_NOEXCEPT_WITH_ASSERT
1094 {
1095 BOOST_ASSERT( deleter_.use_count() <= 1 );
1096 deleter_.reset();
1097 }
1098};
1099
1100} // namespace detail
1101
1102template<class D, class T> D * get_deleter( shared_ptr<T> const & p ) BOOST_SP_NOEXCEPT
1103{
1104 D * d = boost::detail::basic_get_deleter<D>( p );
1105
1106 if( d == 0 )
1107 {
1108 d = boost::detail::basic_get_local_deleter( d, p );
1109 }
1110
1111 if( d == 0 )
1112 {
1113 boost::detail::esft2_deleter_wrapper *del_wrapper = boost::detail::basic_get_deleter<boost::detail::esft2_deleter_wrapper>(p);
1114// The following get_deleter method call is fully qualified because
1115// older versions of gcc (2.95, 3.2.3) fail to compile it when written del_wrapper->get_deleter<D>()
1116 if(del_wrapper) d = del_wrapper->::boost::detail::esft2_deleter_wrapper::get_deleter<D>();
1117 }
1118
1119 return d;
1120}
1121
1122// atomic access
1123
1124#if !defined(BOOST_SP_NO_ATOMIC_ACCESS)
1125
1126template<class T> inline bool atomic_is_lock_free( shared_ptr<T> const * /*p*/ ) BOOST_SP_NOEXCEPT
1127{
1128 return false;
1129}
1130
1131template<class T> shared_ptr<T> atomic_load( shared_ptr<T> const * p ) BOOST_SP_NOEXCEPT
1132{
1133 boost::detail::spinlock_pool<2>::scoped_lock lock( p );
1134 return *p;
1135}
1136
1137template<class T, class M> inline shared_ptr<T> atomic_load_explicit( shared_ptr<T> const * p, /*memory_order mo*/ M ) BOOST_SP_NOEXCEPT
1138{
1139 return atomic_load( p );
1140}
1141
1142template<class T> void atomic_store( shared_ptr<T> * p, shared_ptr<T> r ) BOOST_SP_NOEXCEPT
1143{
1144 boost::detail::spinlock_pool<2>::scoped_lock lock( p );
1145 p->swap( r );
1146}
1147
1148template<class T, class M> inline void atomic_store_explicit( shared_ptr<T> * p, shared_ptr<T> r, /*memory_order mo*/ M ) BOOST_SP_NOEXCEPT
1149{
1150 atomic_store( p, r ); // std::move( r )
1151}
1152
1153template<class T> shared_ptr<T> atomic_exchange( shared_ptr<T> * p, shared_ptr<T> r ) BOOST_SP_NOEXCEPT
1154{
1155 boost::detail::spinlock & sp = boost::detail::spinlock_pool<2>::spinlock_for( pv: p );
1156
1157 sp.lock();
1158 p->swap( r );
1159 sp.unlock();
1160
1161 return r; // return std::move( r )
1162}
1163
1164template<class T, class M> shared_ptr<T> inline atomic_exchange_explicit( shared_ptr<T> * p, shared_ptr<T> r, /*memory_order mo*/ M ) BOOST_SP_NOEXCEPT
1165{
1166 return atomic_exchange( p, r ); // std::move( r )
1167}
1168
1169template<class T> bool atomic_compare_exchange( shared_ptr<T> * p, shared_ptr<T> * v, shared_ptr<T> w ) BOOST_SP_NOEXCEPT
1170{
1171 boost::detail::spinlock & sp = boost::detail::spinlock_pool<2>::spinlock_for( pv: p );
1172
1173 sp.lock();
1174
1175 if( p->_internal_equiv( *v ) )
1176 {
1177 p->swap( w );
1178
1179 sp.unlock();
1180
1181 return true;
1182 }
1183 else
1184 {
1185 shared_ptr<T> tmp( *p );
1186
1187 sp.unlock();
1188
1189 tmp.swap( *v );
1190 return false;
1191 }
1192}
1193
1194template<class T, class M> inline bool atomic_compare_exchange_explicit( shared_ptr<T> * p, shared_ptr<T> * v, shared_ptr<T> w, /*memory_order success*/ M, /*memory_order failure*/ M ) BOOST_SP_NOEXCEPT
1195{
1196 return atomic_compare_exchange( p, v, w ); // std::move( w )
1197}
1198
1199#endif // !defined(BOOST_SP_NO_ATOMIC_ACCESS)
1200
1201// hash_value
1202
1203template< class T > struct hash;
1204
1205template< class T > std::size_t hash_value( boost::shared_ptr<T> const & p ) BOOST_SP_NOEXCEPT
1206{
1207 return boost::hash< typename boost::shared_ptr<T>::element_type* >()( p.get() );
1208}
1209
1210} // namespace boost
1211
1212// std::hash
1213
1214#if !defined(BOOST_NO_CXX11_HDR_FUNCTIONAL)
1215
1216namespace std
1217{
1218
1219template<class T> struct hash< ::boost::shared_ptr<T> >
1220{
1221 std::size_t operator()( ::boost::shared_ptr<T> const & p ) const BOOST_SP_NOEXCEPT
1222 {
1223 return std::hash< typename ::boost::shared_ptr<T>::element_type* >()( p.get() );
1224 }
1225};
1226
1227} // namespace std
1228
1229#endif // #if !defined(BOOST_NO_CXX11_HDR_FUNCTIONAL)
1230
1231#include <boost/smart_ptr/detail/local_sp_deleter.hpp>
1232
1233namespace boost
1234{
1235
1236namespace detail
1237{
1238
1239template<class D, class T> D * basic_get_local_deleter( D *, shared_ptr<T> const & p ) BOOST_SP_NOEXCEPT
1240{
1241 return static_cast<D *>( p._internal_get_local_deleter( BOOST_SP_TYPEID_(local_sp_deleter<D>) ) );
1242}
1243
1244template<class D, class T> D const * basic_get_local_deleter( D const *, shared_ptr<T> const & p ) BOOST_SP_NOEXCEPT
1245{
1246 return static_cast<D *>( p._internal_get_local_deleter( BOOST_SP_TYPEID_(local_sp_deleter<D>) ) );
1247}
1248
1249} // namespace detail
1250
1251#if defined(__cpp_deduction_guides)
1252
1253template<class T> shared_ptr( weak_ptr<T> ) -> shared_ptr<T>;
1254template<class T, class D> shared_ptr( std::unique_ptr<T, D> ) -> shared_ptr<T>;
1255
1256#endif
1257
1258} // namespace boost
1259
1260#if defined( BOOST_SP_DISABLE_DEPRECATED )
1261#pragma GCC diagnostic pop
1262#endif
1263
1264#endif // #ifndef BOOST_SMART_PTR_SHARED_PTR_HPP_INCLUDED
1265

source code of boost/libs/smart_ptr/include/boost/smart_ptr/shared_ptr.hpp