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