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