]> git.donarmstrong.com Git - rsem.git/blob - boost/smart_ptr/shared_ptr.hpp
609cce903221ab5687ccbabc9d651348e883dc76
[rsem.git] / 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 #if defined(BOOST_NO_MEMBER_TEMPLATES) && !defined(BOOST_MSVC6_MEMBER_TEMPLATES)
20 #include <boost/smart_ptr/detail/shared_ptr_nmt.hpp>
21 #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:
27 #include <boost/config/no_tr1/memory.hpp>  // std::auto_ptr
28
29 #include <boost/assert.hpp>
30 #include <boost/checked_delete.hpp>
31 #include <boost/throw_exception.hpp>
32 #include <boost/smart_ptr/detail/shared_count.hpp>
33 #include <boost/detail/workaround.hpp>
34 #include <boost/smart_ptr/detail/sp_convertible.hpp>
35
36 #if !defined(BOOST_SP_NO_ATOMIC_ACCESS)
37 #include <boost/smart_ptr/detail/spinlock_pool.hpp>
38 #include <boost/memory_order.hpp>
39 #endif
40
41 #include <algorithm>            // for std::swap
42 #include <functional>           // for std::less
43 #include <typeinfo>             // for std::bad_cast
44
45 #if !defined(BOOST_NO_IOSTREAM)
46 #if !defined(BOOST_NO_IOSFWD)
47 #include <iosfwd>               // for std::basic_ostream
48 #else
49 #include <ostream>
50 #endif
51 #endif
52
53 #ifdef BOOST_MSVC  // moved here to work around VC++ compiler crash
54 # pragma warning(push)
55 # pragma warning(disable:4284) // odd return type for operator->
56 #endif
57
58 namespace boost
59 {
60
61 template<class T> class shared_ptr;
62 template<class T> class weak_ptr;
63 template<class T> class enable_shared_from_this;
64 template<class T> class enable_shared_from_this2;
65
66 namespace detail
67 {
68
69 struct static_cast_tag {};
70 struct const_cast_tag {};
71 struct dynamic_cast_tag {};
72 struct polymorphic_cast_tag {};
73
74 template<class T> struct shared_ptr_traits
75 {
76     typedef T & reference;
77 };
78
79 template<> struct shared_ptr_traits<void>
80 {
81     typedef void reference;
82 };
83
84 #if !defined(BOOST_NO_CV_VOID_SPECIALIZATIONS)
85
86 template<> struct shared_ptr_traits<void const>
87 {
88     typedef void reference;
89 };
90
91 template<> struct shared_ptr_traits<void volatile>
92 {
93     typedef void reference;
94 };
95
96 template<> struct shared_ptr_traits<void const volatile>
97 {
98     typedef void reference;
99 };
100
101 #endif
102
103 // enable_shared_from_this support
104
105 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 )
106 {
107     if( pe != 0 )
108     {
109         pe->_internal_accept_owner( ppx, const_cast< Y* >( py ) );
110     }
111 }
112
113 template< class X, class Y, class T > inline void sp_enable_shared_from_this( boost::shared_ptr<X> * ppx, Y const * py, boost::enable_shared_from_this2< T > const * pe )
114 {
115     if( pe != 0 )
116     {
117         pe->_internal_accept_owner( ppx, const_cast< Y* >( py ) );
118     }
119 }
120
121 #ifdef _MANAGED
122
123 // Avoid C4793, ... causes native code generation
124
125 struct sp_any_pointer
126 {
127     template<class T> sp_any_pointer( T* ) {}
128 };
129
130 inline void sp_enable_shared_from_this( sp_any_pointer, sp_any_pointer, sp_any_pointer )
131 {
132 }
133
134 #else // _MANAGED
135
136 inline void sp_enable_shared_from_this( ... )
137 {
138 }
139
140 #endif // _MANAGED
141
142 #if !defined( BOOST_NO_SFINAE ) && !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION ) && !defined( BOOST_NO_AUTO_PTR )
143
144 // rvalue auto_ptr support based on a technique by Dave Abrahams
145
146 template< class T, class R > struct sp_enable_if_auto_ptr
147 {
148 };
149
150 template< class T, class R > struct sp_enable_if_auto_ptr< std::auto_ptr< T >, R >
151 {
152     typedef R type;
153 }; 
154
155 #endif
156
157 } // namespace detail
158
159
160 //
161 //  shared_ptr
162 //
163 //  An enhanced relative of scoped_ptr with reference counted copy semantics.
164 //  The object pointed to is deleted when the last shared_ptr pointing to it
165 //  is destroyed or reset.
166 //
167
168 template<class T> class shared_ptr
169 {
170 private:
171
172     // Borland 5.5.1 specific workaround
173     typedef shared_ptr<T> this_type;
174
175 public:
176
177     typedef T element_type;
178     typedef T value_type;
179     typedef T * pointer;
180     typedef typename boost::detail::shared_ptr_traits<T>::reference reference;
181
182     shared_ptr(): px(0), pn() // never throws in 1.30+
183     {
184     }
185
186     template<class Y>
187     explicit shared_ptr( Y * p ): px( p ), pn( p ) // Y must be complete
188     {
189         boost::detail::sp_enable_shared_from_this( this, p, p );
190     }
191
192     //
193     // Requirements: D's copy constructor must not throw
194     //
195     // shared_ptr will release p by calling d(p)
196     //
197
198     template<class Y, class D> shared_ptr(Y * p, D d): px(p), pn(p, d)
199     {
200         boost::detail::sp_enable_shared_from_this( this, p, p );
201     }
202
203     // As above, but with allocator. A's copy constructor shall not throw.
204
205     template<class Y, class D, class A> shared_ptr( Y * p, D d, A a ): px( p ), pn( p, d, a )
206     {
207         boost::detail::sp_enable_shared_from_this( this, p, p );
208     }
209
210 //  generated copy constructor, destructor are fine
211
212     template<class Y>
213     explicit shared_ptr(weak_ptr<Y> const & r): pn(r.pn) // may throw
214     {
215         // it is now safe to copy r.px, as pn(r.pn) did not throw
216         px = r.px;
217     }
218
219     template<class Y>
220     shared_ptr( weak_ptr<Y> const & r, boost::detail::sp_nothrow_tag ): px( 0 ), pn( r.pn, boost::detail::sp_nothrow_tag() ) // never throws
221     {
222         if( !pn.empty() )
223         {
224             px = r.px;
225         }
226     }
227
228     template<class Y>
229 #if !defined( BOOST_SP_NO_SP_CONVERTIBLE )
230
231     shared_ptr( shared_ptr<Y> const & r, typename boost::detail::sp_enable_if_convertible<Y,T>::type = boost::detail::sp_empty() )
232
233 #else
234
235     shared_ptr( shared_ptr<Y> const & r )
236
237 #endif
238     : px( r.px ), pn( r.pn ) // never throws
239     {
240     }
241
242     // aliasing
243     template< class Y >
244     shared_ptr( shared_ptr<Y> const & r, T * p ): px( p ), pn( r.pn ) // never throws
245     {
246     }
247
248     template<class Y>
249     shared_ptr(shared_ptr<Y> const & r, boost::detail::static_cast_tag): px(static_cast<element_type *>(r.px)), pn(r.pn)
250     {
251     }
252
253     template<class Y>
254     shared_ptr(shared_ptr<Y> const & r, boost::detail::const_cast_tag): px(const_cast<element_type *>(r.px)), pn(r.pn)
255     {
256     }
257
258     template<class Y>
259     shared_ptr(shared_ptr<Y> const & r, boost::detail::dynamic_cast_tag): px(dynamic_cast<element_type *>(r.px)), pn(r.pn)
260     {
261         if(px == 0) // need to allocate new counter -- the cast failed
262         {
263             pn = boost::detail::shared_count();
264         }
265     }
266
267     template<class Y>
268     shared_ptr(shared_ptr<Y> const & r, boost::detail::polymorphic_cast_tag): px(dynamic_cast<element_type *>(r.px)), pn(r.pn)
269     {
270         if(px == 0)
271         {
272             boost::throw_exception(std::bad_cast());
273         }
274     }
275
276 #ifndef BOOST_NO_AUTO_PTR
277
278     template<class Y>
279     explicit shared_ptr(std::auto_ptr<Y> & r): px(r.get()), pn()
280     {
281         Y * tmp = r.get();
282         pn = boost::detail::shared_count(r);
283         boost::detail::sp_enable_shared_from_this( this, tmp, tmp );
284     }
285
286 #if !defined( BOOST_NO_SFINAE ) && !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
287
288     template<class Ap>
289     explicit shared_ptr( Ap r, typename boost::detail::sp_enable_if_auto_ptr<Ap, int>::type = 0 ): px( r.get() ), pn()
290     {
291         typename Ap::element_type * tmp = r.get();
292         pn = boost::detail::shared_count( r );
293         boost::detail::sp_enable_shared_from_this( this, tmp, tmp );
294     }
295
296
297 #endif // BOOST_NO_SFINAE, BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
298
299 #endif // BOOST_NO_AUTO_PTR
300
301     // assignment
302
303     shared_ptr & operator=( shared_ptr const & r ) // never throws
304     {
305         this_type(r).swap(*this);
306         return *this;
307     }
308
309 #if !defined(BOOST_MSVC) || (BOOST_MSVC >= 1400)
310
311     template<class Y>
312     shared_ptr & operator=(shared_ptr<Y> const & r) // never throws
313     {
314         this_type(r).swap(*this);
315         return *this;
316     }
317
318 #endif
319
320 #ifndef BOOST_NO_AUTO_PTR
321
322     template<class Y>
323     shared_ptr & operator=( std::auto_ptr<Y> & r )
324     {
325         this_type(r).swap(*this);
326         return *this;
327     }
328
329 #if !defined( BOOST_NO_SFINAE ) && !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
330
331     template<class Ap>
332     typename boost::detail::sp_enable_if_auto_ptr< Ap, shared_ptr & >::type operator=( Ap r )
333     {
334         this_type( r ).swap( *this );
335         return *this;
336     }
337
338
339 #endif // BOOST_NO_SFINAE, BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
340
341 #endif // BOOST_NO_AUTO_PTR
342
343 // Move support
344
345 #if defined( BOOST_HAS_RVALUE_REFS )
346
347     shared_ptr( shared_ptr && r ): px( r.px ), pn() // never throws
348     {
349         pn.swap( r.pn );
350         r.px = 0;
351     }
352
353     template<class Y>
354 #if !defined( BOOST_SP_NO_SP_CONVERTIBLE )
355
356     shared_ptr( shared_ptr<Y> && r, typename boost::detail::sp_enable_if_convertible<Y,T>::type = boost::detail::sp_empty() )
357
358 #else
359
360     shared_ptr( shared_ptr<Y> && r )
361
362 #endif
363     : px( r.px ), pn() // never throws
364     {
365         pn.swap( r.pn );
366         r.px = 0;
367     }
368
369     shared_ptr & operator=( shared_ptr && r ) // never throws
370     {
371         this_type( static_cast< shared_ptr && >( r ) ).swap( *this );
372         return *this;
373     }
374
375     template<class Y>
376     shared_ptr & operator=( shared_ptr<Y> && r ) // never throws
377     {
378         this_type( static_cast< shared_ptr<Y> && >( r ) ).swap( *this );
379         return *this;
380     }
381
382 #endif
383
384     void reset() // never throws in 1.30+
385     {
386         this_type().swap(*this);
387     }
388
389     template<class Y> void reset(Y * p) // Y must be complete
390     {
391         BOOST_ASSERT(p == 0 || p != px); // catch self-reset errors
392         this_type(p).swap(*this);
393     }
394
395     template<class Y, class D> void reset( Y * p, D d )
396     {
397         this_type( p, d ).swap( *this );
398     }
399
400     template<class Y, class D, class A> void reset( Y * p, D d, A a )
401     {
402         this_type( p, d, a ).swap( *this );
403     }
404
405     template<class Y> void reset( shared_ptr<Y> const & r, T * p )
406     {
407         this_type( r, p ).swap( *this );
408     }
409
410     reference operator* () const // never throws
411     {
412         BOOST_ASSERT(px != 0);
413         return *px;
414     }
415
416     T * operator-> () const // never throws
417     {
418         BOOST_ASSERT(px != 0);
419         return px;
420     }
421
422     T * get() const // never throws
423     {
424         return px;
425     }
426
427 // implicit conversion to "bool"
428 #include <boost/smart_ptr/detail/operator_bool.hpp>
429
430     bool unique() const // never throws
431     {
432         return pn.unique();
433     }
434
435     long use_count() const // never throws
436     {
437         return pn.use_count();
438     }
439
440     void swap(shared_ptr<T> & other) // never throws
441     {
442         std::swap(px, other.px);
443         pn.swap(other.pn);
444     }
445
446     template<class Y> bool _internal_less(shared_ptr<Y> const & rhs) const
447     {
448         return pn < rhs.pn;
449     }
450
451     void * _internal_get_deleter( boost::detail::sp_typeinfo const & ti ) const
452     {
453         return pn.get_deleter( ti );
454     }
455
456     bool _internal_equiv( shared_ptr const & r ) const
457     {
458         return px == r.px && pn == r.pn;
459     }
460
461 // Tasteless as this may seem, making all members public allows member templates
462 // to work in the absence of member template friends. (Matthew Langston)
463
464 #ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS
465
466 private:
467
468     template<class Y> friend class shared_ptr;
469     template<class Y> friend class weak_ptr;
470
471
472 #endif
473
474     T * px;                     // contained pointer
475     boost::detail::shared_count pn;    // reference counter
476
477 };  // shared_ptr
478
479 template<class T, class U> inline bool operator==(shared_ptr<T> const & a, shared_ptr<U> const & b)
480 {
481     return a.get() == b.get();
482 }
483
484 template<class T, class U> inline bool operator!=(shared_ptr<T> const & a, shared_ptr<U> const & b)
485 {
486     return a.get() != b.get();
487 }
488
489 #if __GNUC__ == 2 && __GNUC_MINOR__ <= 96
490
491 // Resolve the ambiguity between our op!= and the one in rel_ops
492
493 template<class T> inline bool operator!=(shared_ptr<T> const & a, shared_ptr<T> const & b)
494 {
495     return a.get() != b.get();
496 }
497
498 #endif
499
500 template<class T, class U> inline bool operator<(shared_ptr<T> const & a, shared_ptr<U> const & b)
501 {
502     return a._internal_less(b);
503 }
504
505 template<class T> inline void swap(shared_ptr<T> & a, shared_ptr<T> & b)
506 {
507     a.swap(b);
508 }
509
510 template<class T, class U> shared_ptr<T> static_pointer_cast(shared_ptr<U> const & r)
511 {
512     return shared_ptr<T>(r, boost::detail::static_cast_tag());
513 }
514
515 template<class T, class U> shared_ptr<T> const_pointer_cast(shared_ptr<U> const & r)
516 {
517     return shared_ptr<T>(r, boost::detail::const_cast_tag());
518 }
519
520 template<class T, class U> shared_ptr<T> dynamic_pointer_cast(shared_ptr<U> const & r)
521 {
522     return shared_ptr<T>(r, boost::detail::dynamic_cast_tag());
523 }
524
525 // shared_*_cast names are deprecated. Use *_pointer_cast instead.
526
527 template<class T, class U> shared_ptr<T> shared_static_cast(shared_ptr<U> const & r)
528 {
529     return shared_ptr<T>(r, boost::detail::static_cast_tag());
530 }
531
532 template<class T, class U> shared_ptr<T> shared_dynamic_cast(shared_ptr<U> const & r)
533 {
534     return shared_ptr<T>(r, boost::detail::dynamic_cast_tag());
535 }
536
537 template<class T, class U> shared_ptr<T> shared_polymorphic_cast(shared_ptr<U> const & r)
538 {
539     return shared_ptr<T>(r, boost::detail::polymorphic_cast_tag());
540 }
541
542 template<class T, class U> shared_ptr<T> shared_polymorphic_downcast(shared_ptr<U> const & r)
543 {
544     BOOST_ASSERT(dynamic_cast<T *>(r.get()) == r.get());
545     return shared_static_cast<T>(r);
546 }
547
548 // get_pointer() enables boost::mem_fn to recognize shared_ptr
549
550 template<class T> inline T * get_pointer(shared_ptr<T> const & p)
551 {
552     return p.get();
553 }
554
555 // operator<<
556
557 #if !defined(BOOST_NO_IOSTREAM)
558
559 #if defined(BOOST_NO_TEMPLATED_IOSTREAMS) || ( defined(__GNUC__) &&  (__GNUC__ < 3) )
560
561 template<class Y> std::ostream & operator<< (std::ostream & os, shared_ptr<Y> const & p)
562 {
563     os << p.get();
564     return os;
565 }
566
567 #else
568
569 // in STLport's no-iostreams mode no iostream symbols can be used
570 #ifndef _STLP_NO_IOSTREAMS
571
572 # if defined(BOOST_MSVC) && BOOST_WORKAROUND(BOOST_MSVC, < 1300 && __SGI_STL_PORT)
573 // MSVC6 has problems finding std::basic_ostream through the using declaration in namespace _STL
574 using std::basic_ostream;
575 template<class E, class T, class Y> basic_ostream<E, T> & operator<< (basic_ostream<E, T> & os, shared_ptr<Y> const & p)
576 # else
577 template<class E, class T, class Y> std::basic_ostream<E, T> & operator<< (std::basic_ostream<E, T> & os, shared_ptr<Y> const & p)
578 # endif
579 {
580     os << p.get();
581     return os;
582 }
583
584 #endif // _STLP_NO_IOSTREAMS
585
586 #endif // __GNUC__ < 3
587
588 #endif // !defined(BOOST_NO_IOSTREAM)
589
590 // get_deleter
591
592 #if ( defined(__GNUC__) && BOOST_WORKAROUND(__GNUC__, < 3) ) || \
593     ( defined(__EDG_VERSION__) && BOOST_WORKAROUND(__EDG_VERSION__, <= 238) ) || \
594     ( defined(__HP_aCC) && BOOST_WORKAROUND(__HP_aCC, <= 33500) )
595
596 // g++ 2.9x doesn't allow static_cast<X const *>(void *)
597 // apparently EDG 2.38 and HP aCC A.03.35 also don't accept it
598
599 template<class D, class T> D * get_deleter(shared_ptr<T> const & p)
600 {
601     void const * q = p._internal_get_deleter(BOOST_SP_TYPEID(D));
602     return const_cast<D *>(static_cast<D const *>(q));
603 }
604
605 #else
606
607 template<class D, class T> D * get_deleter(shared_ptr<T> const & p)
608 {
609     return static_cast<D *>(p._internal_get_deleter(BOOST_SP_TYPEID(D)));
610 }
611
612 #endif
613
614 // atomic access
615
616 #if !defined(BOOST_SP_NO_ATOMIC_ACCESS)
617
618 template<class T> inline bool atomic_is_lock_free( shared_ptr<T> const * /*p*/ )
619 {
620     return false;
621 }
622
623 template<class T> shared_ptr<T> atomic_load( shared_ptr<T> const * p )
624 {
625     boost::detail::spinlock_pool<2>::scoped_lock lock( p );
626     return *p;
627 }
628
629 template<class T> inline shared_ptr<T> atomic_load_explicit( shared_ptr<T> const * p, memory_order /*mo*/ )
630 {
631     return atomic_load( p );
632 }
633
634 template<class T> void atomic_store( shared_ptr<T> * p, shared_ptr<T> r )
635 {
636     boost::detail::spinlock_pool<2>::scoped_lock lock( p );
637     p->swap( r );
638 }
639
640 template<class T> inline void atomic_store_explicit( shared_ptr<T> * p, shared_ptr<T> r, memory_order /*mo*/ )
641 {
642     atomic_store( p, r ); // std::move( r )
643 }
644
645 template<class T> shared_ptr<T> atomic_exchange( shared_ptr<T> * p, shared_ptr<T> r )
646 {
647     boost::detail::spinlock & sp = boost::detail::spinlock_pool<2>::spinlock_for( p );
648
649     sp.lock();
650     p->swap( r );
651     sp.unlock();
652
653     return r; // return std::move( r )
654 }
655
656 template<class T> shared_ptr<T> atomic_exchange_explicit( shared_ptr<T> * p, shared_ptr<T> r, memory_order /*mo*/ )
657 {
658     return atomic_exchange( p, r ); // std::move( r )
659 }
660
661 template<class T> bool atomic_compare_exchange( shared_ptr<T> * p, shared_ptr<T> * v, shared_ptr<T> w )
662 {
663     boost::detail::spinlock & sp = boost::detail::spinlock_pool<2>::spinlock_for( p );
664
665     sp.lock();
666
667     if( p->_internal_equiv( *v ) )
668     {
669         p->swap( w );
670
671         sp.unlock();
672
673         return true;
674     }
675     else
676     {
677         shared_ptr<T> tmp( *p );
678
679         sp.unlock();
680
681         tmp.swap( *v );
682         return false;
683     }
684 }
685
686 template<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*/ )
687 {
688     return atomic_compare_exchange( p, v, w ); // std::move( w )
689 }
690
691 #endif
692
693 } // namespace boost
694
695 #ifdef BOOST_MSVC
696 # pragma warning(pop)
697 #endif
698
699 #endif  // #if defined(BOOST_NO_MEMBER_TEMPLATES) && !defined(BOOST_MSVC6_MEMBER_TEMPLATES)
700
701 #endif  // #ifndef BOOST_SMART_PTR_SHARED_PTR_HPP_INCLUDED