CLHEP VERSION Reference Documentation
   
CLHEP Home Page     CLHEP Documentation     CLHEP Bug Reports

Random/CLHEP/Utility/memory.h
Go to the documentation of this file.
00001 #ifndef CLHEP_MEMORY_H
00002 #define CLHEP_MEMORY_H
00003 
00004 // ======================================================================
00005 //
00006 // memory - memory management utilities
00007 //
00008 // Note:  the following adaptation of the C++0X std::shared_ptr/weak_ptr
00009 // interface and semantics has been customized for the specific internal
00010 // needs of CLHEP/Random; it neither has nor needs the full generality
00011 // of its namesake.
00012 //
00013 // Author:  W. E. Brown, 2010-03-19, adapted from the boost library's
00014 // shared_ptr and related functionality whose internal attributions bear
00015 // the following various notices:
00016 //
00017 //   (C) Copyright Greg Colvin and Beman Dawes 1998, 1999.
00018 //   Copyright (c) 2001, 2002, 2003 Peter Dimov
00019 //   Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd.
00020 //   Copyright (c) 2001-2008 Peter Dimov
00021 //   Copyright (c) 2001-2009 Peter Dimov
00022 //   Copyright 2002, 2009 Peter Dimov
00023 //   Copyright 2004-2005 Peter Dimov
00024 //   Copyright 2004-2008 Peter Dimov
00025 //   Copyright 2005, 2006 Peter Dimov
00026 //   Copyright 2008 Frank Mori Hess
00027 //   Copyright 2008 Peter Dimov
00028 //   Distributed under the Boost Software License, Version 1.0.
00029 //   See http://www.boost.org/LICENSE_1_0.txt
00030 //
00031 // ======================================================================
00032 
00033 
00034 #include "CLHEP/Utility/defs.h"
00035 #include "CLHEP/Utility/noncopyable.h"
00036 #include "CLHEP/Utility/type_traits.h"
00037 
00038 #include <algorithm>  // for swap
00039 #include <cassert>    // for assert macro
00040 #include <cstddef>    // for size_t
00041 #include <exception>  // for exception
00042 #include <functional> // for less
00043 #include <iosfwd>     // for basic_ostream
00044 #include <memory>     // for allocator, auto_ptr
00045 #include <typeinfo>   // for bad_cast, type_info
00046 
00047 
00048 namespace CLHEP {
00049 
00050 
00051 // ----------------------------------------------------------------------
00052 // forward declarations
00053 // ----------------------------------------------------------------------
00054 
00055 template< typename T > class shared_ptr;
00056 template< typename T > class weak_ptr;
00057 template< typename T > class enable_shared_from_this;
00058 template< typename T > class enable_shared_from_this2;
00059 
00060 
00061 // ----------------------------------------------------------------------
00062 // bad_weak_ptr - exception thrown when a stale weak_ptr is encountered
00063 // ----------------------------------------------------------------------
00064 
00065 class bad_weak_ptr
00066   : public std::exception
00067 {
00068 public:
00069   inline  virtual  char const *  what() const throw();
00070 
00071 };  // bad_weak_ptr
00072 
00073 char const *
00074   bad_weak_ptr::what() const throw()
00075 {
00076   return "bad_weak_ptr";
00077 }
00078 
00079 
00080 namespace sp {
00081 
00082 
00083 // ----------------------------------------------------------------------
00084 // abstract_ctrl_block - shared_ptr's counters and type-erased deleter
00085 // ----------------------------------------------------------------------
00086 
00087 class abstract_ctrl_block
00088   : public noncopyable
00089 {
00090 public:
00091   inline  void  class_invariant() const throw();
00092   // class class_invariant
00093 
00094   inline           abstract_ctrl_block();
00095   inline  virtual  ~abstract_ctrl_block() throw();
00096   // constructor and destructor
00097 
00098   inline           void    add_ref();
00099   inline           bool    add_ref_lock();
00100   inline           void    weak_add_ref() throw();
00101           virtual  void *  get_deleter( std::type_info const & ti ) = 0;
00102   inline           void    release() throw();
00103   inline           void    weak_release() throw();
00104           virtual  void    dispose() throw() = 0;
00105   inline  virtual  void    destroy() throw();
00106   // resource management functions
00107 
00108   inline  long use_count() const throw();
00109   // accessor
00110 
00111 private:
00112   int  n_shared_ptrs;
00113   int  n_weak_ptrs;
00114 
00115 };  // abstract_ctrl_block
00116 
00117 void
00118   abstract_ctrl_block::class_invariant() const throw()
00119 {
00120   assert( n_shared_ptrs == 0  || n_weak_ptrs >= 1 );
00121 }
00122 
00123 abstract_ctrl_block::abstract_ctrl_block()
00124   : n_shared_ptrs( 1 )
00125   , n_weak_ptrs  ( 1 )
00126 {
00127   class_invariant();
00128 }
00129 
00130 abstract_ctrl_block::~abstract_ctrl_block() throw()
00131 {
00132   class_invariant();
00133 }
00134 
00135 void
00136   abstract_ctrl_block::add_ref()
00137 {
00138   class_invariant();
00139   ++n_shared_ptrs;
00140 }
00141 
00142 bool
00143   abstract_ctrl_block::add_ref_lock()  // true on success
00144 {
00145   class_invariant();
00146   return n_shared_ptrs ? ++n_shared_ptrs : false;
00147 }
00148 
00149 void
00150   abstract_ctrl_block::weak_add_ref() throw()
00151 {
00152   class_invariant();
00153   ++n_weak_ptrs;
00154 }
00155 
00156 void
00157   abstract_ctrl_block::release() throw()
00158 {
00159   class_invariant();
00160   if( 0 == --n_shared_ptrs )
00161     dispose(), weak_release();
00162 }
00163 
00164 void
00165   abstract_ctrl_block::weak_release() throw()
00166 {
00167   class_invariant();
00168   if( 0 == --n_weak_ptrs )
00169     destroy();
00170 }
00171 
00172 void
00173   abstract_ctrl_block::destroy() throw()
00174 {
00175   assert( n_weak_ptrs == 0 );
00176   delete this;
00177 }
00178 
00179 long
00180   abstract_ctrl_block::use_count() const throw()
00181 {
00182   class_invariant();
00183   return n_shared_ptrs;
00184 }
00185 
00186 
00187 // ----------------------------------------------------------------------
00188 // concrete ctrl_block_* variations:
00189 //   ctrl_block_p  : owned pointer only; no deleter, no allocator
00190 //   ctrl_block_pd : owned pointer and deleter only; no allocator
00191 //   ctrl_block_pda: owned pointer, deleter, and allocator
00192 // ----------------------------------------------------------------------
00193 
00194 template< typename P >  // P is pointee type
00195   class ctrl_block_p
00196     : public abstract_ctrl_block
00197 {
00198   typedef ctrl_block_p<P> this_type;
00199 
00200 public:
00201   inline  explicit ctrl_block_p( P * );
00202   inline           ~ctrl_block_p() throw();
00203   // constructor and destructor
00204 
00205   inline  void *  operator new ( std::size_t );
00206   inline  void    operator delete ( void * );
00207   // allocation functions
00208 
00209   inline  virtual  void *  get_deleter( std::type_info const & );
00210   inline  virtual  void    dispose() throw();
00211   // resource management functions
00212 
00213 private:
00214   P *  owned_ptr;
00215 
00216 };  // ctrl_block_p
00217 
00218 template< typename P >
00219 ctrl_block_p<P>::ctrl_block_p( P * p )
00220   : abstract_ctrl_block( )
00221   , owned_ptr( p )
00222 { }
00223 
00224 template< typename P >
00225 ctrl_block_p<P>::~ctrl_block_p() throw()
00226 { }
00227 
00228 template< typename P >
00229 void
00230   ctrl_block_p<P>::dispose() throw()
00231 {
00232   delete owned_ptr;
00233 }
00234 
00235 template< typename P >
00236 void *
00237   ctrl_block_p<P>::get_deleter( std::type_info const & )
00238 {
00239   return 0;
00240 }
00241 
00242 template< typename P >
00243 void *
00244   ctrl_block_p<P>::operator new ( std::size_t )
00245 {
00246   return std::allocator<this_type>().allocate( 1 );
00247 }
00248 
00249 template< typename P >
00250 void
00251   ctrl_block_p<P>::operator delete ( void * p )
00252 {
00253   std::allocator<this_type>().deallocate( static_cast<this_type*>(p), 1 );
00254 }
00255 
00256 template< typename P  // pointee type
00257         , typename D  // deleter type
00258         >
00259   class ctrl_block_pd
00260     : public abstract_ctrl_block
00261 {
00262   typedef ctrl_block_pd<P,D> this_type;
00263 
00264 public:
00265   inline  ctrl_block_pd( P *, D );
00266   inline  ~ctrl_block_pd() throw();
00267   // constructor and destructor
00268 
00269   inline  void *  operator new ( std::size_t );
00270   inline  void    operator delete ( void * );
00271   // allocation functions
00272 
00273   inline  virtual  void *  get_deleter( std::type_info const & );
00274   inline  virtual  void    dispose() throw();
00275   // resource management functions
00276 
00277 private:
00278   P *  owned_ptr;
00279   D    deleter;   // D's copy constructor must not throw, and
00280                   // call to deleter( owned_ptr ) must not throw
00281 
00282 };  // ctrl_block_pd
00283 
00284 template< typename P, typename D >
00285 ctrl_block_pd<P,D>::ctrl_block_pd( P * p, D d )
00286   : abstract_ctrl_block( )
00287   , owned_ptr( p )
00288   , deleter  ( d )
00289 { }
00290 
00291 template< typename P, typename D >
00292 ctrl_block_pd<P,D>::~ctrl_block_pd() throw()
00293 { }
00294 
00295 template< typename P, typename D >
00296 void
00297   ctrl_block_pd<P,D>::dispose() throw()
00298 {
00299   deleter( owned_ptr );
00300 }
00301 
00302 template< typename P, typename D >
00303 void *
00304   ctrl_block_pd<P,D>::get_deleter( std::type_info const & ti )
00305 {
00306   return ti == typeid(D) ? &reinterpret_cast<char&>( deleter ) : 0;
00307 }
00308 
00309 template< typename P, typename D >
00310 void *
00311   ctrl_block_pd<P,D>::operator new ( std::size_t )
00312 {
00313   return std::allocator<this_type>().allocate( 1 );
00314 }
00315 
00316 template< typename P, typename D >
00317 void
00318   ctrl_block_pd<P,D>::operator delete ( void * p )
00319 {
00320   std::allocator<this_type>().deallocate( static_cast<this_type*>(p), 1 );
00321 }
00322 
00323 template< typename P  // pointee type
00324         , typename D  // deleter type
00325         , typename A  // allocator type
00326         >
00327   class ctrl_block_pda
00328     : public abstract_ctrl_block
00329 {
00330   typedef ctrl_block_pda<P,D,A> this_type;
00331 
00332 public:
00333   inline  ctrl_block_pda( P *, D, A );
00334   inline  ~ctrl_block_pda() throw();
00335   // constructor and destructor
00336 
00337   inline  virtual  void *  get_deleter( std::type_info const & );
00338   inline  virtual  void    dispose() throw();
00339   inline  virtual  void    destroy() throw();
00340   // resource management functions
00341 
00342 private:
00343   P *  owned_ptr;
00344   D    deleter;   // D's copy constructor must not throw, and
00345                   // call to deleter( owned_ptr ) must not throw
00346   A    allocator; // A's copy constructor must not throw
00347 
00348 };  // ctrl_block_pda
00349 
00350 template< typename P, typename D, typename A >
00351 ctrl_block_pda<P,D,A>::ctrl_block_pda( P * p, D d, A a )
00352   : abstract_ctrl_block( )
00353   , owned_ptr( p )
00354   , deleter  ( d )
00355   , allocator( a )
00356 { }
00357 
00358 template< typename P, typename D, typename A >
00359 ctrl_block_pda<P,D,A>::~ctrl_block_pda() throw()
00360 { }
00361 
00362 template< typename P, typename D, typename A >
00363 void
00364   ctrl_block_pda<P,D,A>::dispose() throw()
00365 {
00366   deleter( owned_ptr );
00367 }
00368 
00369 template< typename P, typename D, typename A >
00370 void
00371   ctrl_block_pda<P,D,A>::destroy() throw()
00372 {
00373   typename A::template rebind< this_type >::other  this_allocator( allocator );
00374 
00375   this_allocator.destroy( this );  // this->~this_type();
00376   this_allocator.deallocate( this, 1 );
00377 }
00378 
00379 template< typename P, typename D, typename A >
00380 void *
00381   ctrl_block_pda<P,D,A>::get_deleter( std::type_info const & ti )
00382 {
00383   return ti == typeid( D ) ? &reinterpret_cast<char&>( deleter ) : 0;
00384 }
00385 
00386 
00387 // ----------------------------------------------------------------------
00388 // shared_ctrl_handle, weak_ctrl_handle - ctrl block handles
00389 // ----------------------------------------------------------------------
00390 
00391 class shared_ctrl_handle;
00392 class weak_ctrl_handle;
00393 
00394 struct sp_nothrow_tag { };
00395 
00396 class shared_ctrl_handle
00397 {
00398   friend  class weak_ctrl_handle;
00399 
00400 public:
00401   inline  shared_ctrl_handle() throw();
00402   template< typename P >
00403     inline  explicit
00404     shared_ctrl_handle( P * );
00405   template< typename P, typename D >
00406     inline  shared_ctrl_handle( P *, D );
00407   template< typename P, typename D, typename A >
00408     inline  shared_ctrl_handle( P *, D, A );
00409   template< typename P >
00410     inline  explicit
00411     shared_ctrl_handle( std::auto_ptr<P> & );
00412   inline  ~shared_ctrl_handle() throw();
00413   // constructors and destructor
00414 
00415   inline  void  swap( shared_ctrl_handle & ) throw();
00416   inline  shared_ctrl_handle( shared_ctrl_handle const & ) throw();
00417   inline  shared_ctrl_handle &
00418     operator = ( shared_ctrl_handle const & ) throw();
00419   // copy functions
00420 
00421   inline  explicit
00422     shared_ctrl_handle( weak_ctrl_handle const & );
00423   inline  shared_ctrl_handle( weak_ctrl_handle const &, sp_nothrow_tag );
00424   // copy-like functions
00425 
00426   inline  void *  get_deleter( std::type_info const & ) const;
00427   inline  bool    unique() const throw();
00428   inline  bool    empty() const throw();
00429   inline  long    use_count() const throw();
00430   // accessors
00431 
00432   friend inline
00433   bool
00434     operator == ( shared_ctrl_handle const &, shared_ctrl_handle const & );
00435   friend inline
00436   bool
00437     operator < ( shared_ctrl_handle const &, shared_ctrl_handle const & );
00438   // comparisons
00439 
00440 private:
00441   abstract_ctrl_block *  acb_ptr;
00442 
00443 };  // shared_ctrl_handle
00444 
00445 shared_ctrl_handle::shared_ctrl_handle() throw()
00446   : acb_ptr( 0 )
00447 { }
00448 
00449 template< typename P >
00450   shared_ctrl_handle::shared_ctrl_handle( P * p )
00451   // a fctn-try block would be slightly more efficient here,
00452   // but some older compilers don't understand it
00453   : acb_ptr( 0 )
00454 {
00455   try  {
00456     acb_ptr = new ctrl_block_p<P>(p);
00457   }
00458   catch(...)  {
00459     delete p;
00460     throw;
00461   }
00462 }
00463 
00464 template< typename P, typename D >
00465   shared_ctrl_handle::shared_ctrl_handle( P * p, D d )
00466   // a fctn-try block would be slightly more efficient here,
00467   // but some older compilers don't understand it
00468   : acb_ptr( 0 )
00469 {
00470   try  {
00471     acb_ptr = new ctrl_block_pd<P,D>(p, d);
00472   }
00473   catch(...)  {
00474     d( p );
00475     throw;
00476   }
00477 }
00478 
00479 template< typename P, typename D, typename A >
00480   shared_ctrl_handle::shared_ctrl_handle( P * p, D d, A a )
00481   : acb_ptr( 0 )
00482 {
00483   typedef  ctrl_block_pda<P,D,A>
00484            ctrl_block;
00485   typedef  typename A::template rebind<ctrl_block>::other
00486            ctrl_block_allocator;
00487   ctrl_block_allocator cba( a );
00488 
00489   try
00490   {
00491     acb_ptr = cba.allocate( 1 );
00492     new( static_cast<void*>(acb_ptr) ) ctrl_block(p, d, a);
00493   }
00494   catch(...)
00495   {
00496     d( p );
00497     if( acb_ptr != 0 )
00498       cba.deallocate( static_cast<ctrl_block*>( acb_ptr ), 1 );
00499     throw;
00500   }
00501 }
00502 
00503 template< typename P >
00504   shared_ctrl_handle::shared_ctrl_handle( std::auto_ptr<P> & p )
00505     : acb_ptr( new ctrl_block_p<P>( p.get() ) )
00506 {
00507   p.release();
00508 }
00509 
00510 shared_ctrl_handle::~shared_ctrl_handle() throw()
00511 {
00512   if( acb_ptr != 0 )
00513     acb_ptr->release();
00514 }
00515 
00516 void
00517   shared_ctrl_handle::swap( shared_ctrl_handle & other ) throw()
00518 {
00519   abstract_ctrl_block * tmp = other.acb_ptr;
00520   other.acb_ptr = acb_ptr;
00521   acb_ptr = tmp;
00522 }
00523 
00524 shared_ctrl_handle::shared_ctrl_handle( shared_ctrl_handle const & other ) throw()
00525   : acb_ptr( other.acb_ptr )
00526 {
00527   if( acb_ptr != 0 )
00528     acb_ptr->add_ref();
00529 }
00530 
00531 shared_ctrl_handle &
00532   shared_ctrl_handle::operator = ( shared_ctrl_handle const & other ) throw()
00533 {
00534   abstract_ctrl_block * tmp = other.acb_ptr;
00535 
00536   if( tmp != acb_ptr )
00537   {
00538     if( tmp     != 0 ) tmp->add_ref();
00539     if( acb_ptr != 0 ) acb_ptr->release();
00540     acb_ptr = tmp;
00541   }
00542 
00543   return *this;
00544 }
00545 
00546 void *
00547   shared_ctrl_handle::get_deleter( std::type_info const & ti ) const
00548 {
00549   return acb_ptr ? acb_ptr->get_deleter( ti ) : 0;
00550 }
00551 
00552 bool
00553   shared_ctrl_handle::unique() const throw()
00554 {
00555   return 1L == use_count();
00556 }
00557 
00558 bool
00559   shared_ctrl_handle::empty() const throw()
00560 {
00561   return acb_ptr == 0;
00562 }
00563 
00564 long
00565   shared_ctrl_handle::use_count() const throw()
00566 {
00567   return acb_ptr == 0 ? 0L : acb_ptr->use_count();
00568 }
00569 
00570 bool
00571   operator == ( shared_ctrl_handle const & lhs, shared_ctrl_handle const & rhs )
00572 {
00573   return lhs.acb_ptr == rhs.acb_ptr;
00574 }
00575 
00576 bool
00577   operator < ( shared_ctrl_handle const & lhs, shared_ctrl_handle const & rhs )
00578 {
00579   return std::less<abstract_ctrl_block*>()( lhs.acb_ptr, rhs.acb_ptr );
00580 }
00581 
00582 class weak_ctrl_handle
00583 {
00584   friend  class shared_ctrl_handle;
00585 
00586 public:
00587 
00588   inline  weak_ctrl_handle() throw();
00589   inline  weak_ctrl_handle( shared_ctrl_handle const & ) throw();
00590   inline  ~weak_ctrl_handle() throw();
00591   // constructors and destructor
00592 
00593   inline  void  swap( weak_ctrl_handle & ) throw();
00594   inline  weak_ctrl_handle( weak_ctrl_handle const & ) throw();
00595   inline  weak_ctrl_handle & operator = ( shared_ctrl_handle const & ) throw();
00596   // copy functions
00597 
00598   inline  weak_ctrl_handle & operator = ( weak_ctrl_handle const & ) throw();
00599   // copy-like functions
00600 
00601   inline  bool  empty() const throw();
00602   inline  long  use_count() const throw();
00603   // accessors
00604 
00605   friend inline
00606   bool
00607     operator == ( weak_ctrl_handle const &, weak_ctrl_handle const & );
00608   friend inline
00609   bool
00610     operator < ( weak_ctrl_handle const &, weak_ctrl_handle const & );
00611   // comparisons
00612 
00613 private:
00614   abstract_ctrl_block *  acb_ptr;
00615 
00616 };  // weak_ctrl_handle
00617 
00618 weak_ctrl_handle::weak_ctrl_handle() throw()
00619   : acb_ptr( 0 )
00620 { }
00621 
00622 weak_ctrl_handle::weak_ctrl_handle( shared_ctrl_handle const & other ) throw()
00623   : acb_ptr( other.acb_ptr )
00624 {
00625   if( acb_ptr != 0 )
00626     acb_ptr->weak_add_ref();
00627 }
00628 
00629 weak_ctrl_handle::~weak_ctrl_handle() throw()
00630 {
00631   if( acb_ptr != 0 )
00632     acb_ptr->weak_release();
00633 }
00634 
00635 void
00636   weak_ctrl_handle::swap( weak_ctrl_handle & other ) throw()
00637 {
00638   abstract_ctrl_block *  tmp = other.acb_ptr;
00639   other.acb_ptr = acb_ptr;
00640   acb_ptr = tmp;
00641 }
00642 
00643 weak_ctrl_handle::weak_ctrl_handle( weak_ctrl_handle const & other ) throw()
00644   : acb_ptr( other.acb_ptr )
00645 {
00646   if( acb_ptr != 0 )
00647     acb_ptr->weak_add_ref();
00648 }
00649 
00650 weak_ctrl_handle &
00651   weak_ctrl_handle::operator = ( shared_ctrl_handle const & other ) throw()
00652 {
00653   abstract_ctrl_block *  tmp = other.acb_ptr;
00654 
00655   if( tmp != acb_ptr )
00656   {
00657     if( tmp     != 0 ) tmp->weak_add_ref();
00658     if( acb_ptr != 0 ) acb_ptr->weak_release();
00659     acb_ptr = tmp;
00660 }
00661 
00662   return *this;
00663 }
00664 
00665 weak_ctrl_handle &
00666   weak_ctrl_handle::operator = ( weak_ctrl_handle const & other ) throw()
00667 {
00668   abstract_ctrl_block *  tmp = other.acb_ptr;
00669 
00670   if( tmp != acb_ptr )
00671 {
00672     if( tmp     != 0 ) tmp->weak_add_ref();
00673     if( acb_ptr != 0 ) acb_ptr->weak_release();
00674     acb_ptr = tmp;
00675 }
00676 
00677   return *this;
00678 }
00679 
00680 bool
00681   weak_ctrl_handle::empty() const throw()
00682 {
00683   return acb_ptr == 0;
00684 }
00685 
00686 long
00687   weak_ctrl_handle::use_count() const throw()
00688 {
00689   return acb_ptr == 0 ? 0L : acb_ptr->use_count();
00690 }
00691 
00692 bool
00693   operator == ( weak_ctrl_handle const & lhs, weak_ctrl_handle const & rhs )
00694 {
00695   return lhs.acb_ptr == rhs.acb_ptr;
00696 }
00697 
00698 bool
00699   operator < ( weak_ctrl_handle const & lhs, weak_ctrl_handle const & rhs )
00700 {
00701   return std::less<abstract_ctrl_block*>()( lhs.acb_ptr, rhs.acb_ptr );
00702 }
00703 
00704 shared_ctrl_handle::shared_ctrl_handle( weak_ctrl_handle const & other )
00705   : acb_ptr( other.acb_ptr )
00706 {
00707   if( acb_ptr == 0  ||  ! acb_ptr->add_ref_lock() )
00708     throw bad_weak_ptr();
00709 }
00710 
00711 shared_ctrl_handle::shared_ctrl_handle( weak_ctrl_handle const & other
00712                                       , sp_nothrow_tag )
00713   : acb_ptr( other.acb_ptr )
00714 {
00715   if( acb_ptr != 0  &&  ! acb_ptr->add_ref_lock() )
00716     acb_ptr = 0;
00717 }
00718 
00719 
00720 // ----------------------------------------------------------------------
00721 // cast tags
00722 // ----------------------------------------------------------------------
00723 
00724 struct static_cast_tag      { };
00725 struct const_cast_tag       { };
00726 struct dynamic_cast_tag     { };
00727 struct polymorphic_cast_tag { };
00728 
00729 
00730 // ----------------------------------------------------------------------
00731 // shared_ptr_traits - specify dependent types
00732 // ----------------------------------------------------------------------
00733 
00734 template< typename T >
00735   struct shared_ptr_traits
00736 {
00737   typedef  T &  reference;
00738 };
00739 
00740 template<>
00741   struct shared_ptr_traits<void>
00742 {
00743   typedef  void  reference;
00744 };
00745 
00746 template<>
00747   struct shared_ptr_traits<void const>
00748 {
00749   typedef  void  reference;
00750 };
00751 
00752 template<>
00753   struct shared_ptr_traits<void volatile>
00754 {
00755   typedef  void  reference;
00756 };
00757 
00758 template<>
00759   struct shared_ptr_traits<void const volatile>
00760 {
00761   typedef  void  reference;
00762 };
00763 
00764 
00765 // ----------------------------------------------------------------------
00766 // enable_shared_from_this support
00767 // ----------------------------------------------------------------------
00768 
00769 template< typename X, typename Y, typename T >
00770 inline void
00771   sp_enable_shared_from_this( shared_ptr<X>              const * ppx
00772                             , Y                          const * py
00773                             , enable_shared_from_this<T> const * pe
00774                             )
00775 {
00776   if( pe != 0 )
00777     pe->_internal_accept_owner( ppx, const_cast<Y*>( py ) );
00778 }
00779 
00780 template< typename X, typename Y, typename T >
00781 inline void
00782   sp_enable_shared_from_this( shared_ptr<X>                     * ppx
00783                             , Y                           const * py
00784                             , enable_shared_from_this2<T> const * pe
00785                             )
00786 {
00787   if( pe != 0 )
00788     pe->_internal_accept_owner( ppx, const_cast<Y*>( py ) );
00789 }
00790 
00791 inline void
00792   sp_enable_shared_from_this( ... )
00793 { }
00794 
00795 }  // namespace sp
00796 
00797 
00798 // ----------------------------------------------------------------------
00799 // shared_ptr - "if you are the last person, please turn out the light"
00800 // ----------------------------------------------------------------------
00801 
00802 template< typename P >  // pointee type
00803   class shared_ptr
00804 {
00805   typedef  shared_ptr<P>                                 this_type;
00806   typedef  typename sp::shared_ptr_traits<P>::reference  reference;
00807 
00808   template< typename >  friend  class shared_ptr;
00809   template< typename >  friend  class weak_ptr;
00810 
00811 public:
00812   typedef  P  element_type;
00813   // pointee type
00814 
00815   shared_ptr() throw();
00816   template< typename P2 >
00817     inline  explicit
00818     shared_ptr( P2 * );
00819   template< typename P2, typename D >
00820     inline  shared_ptr( P2 *, D );
00821   template< typename P2, typename D, typename A >
00822     inline  shared_ptr( P2 *, D, A );
00823   // constructors
00824 
00825   inline  void          swap( shared_ptr<P> & ) throw();
00826   inline  shared_ptr &  operator = ( shared_ptr const & ) throw();
00827   // copy functions; generated copy constructor, destructor are fine
00828 
00829   template< typename P2 >
00830     inline  explicit
00831     shared_ptr( weak_ptr<P2> const & );
00832   template< typename P2 >
00833     inline  shared_ptr( weak_ptr<P2> const &, sp::sp_nothrow_tag ) throw();
00834   template< typename P2 >
00835     inline  shared_ptr( shared_ptr<P2> const &, P * ) throw();
00836   template< typename P2 >
00837     inline  shared_ptr( shared_ptr<P2> const &, sp::static_cast_tag );
00838   template< typename P2 >
00839     inline  shared_ptr( shared_ptr<P2> const &, sp::const_cast_tag );
00840   template< typename P2 >
00841     inline  shared_ptr( shared_ptr<P2> const &, sp::dynamic_cast_tag );
00842   template< typename P2 >
00843     inline  shared_ptr( shared_ptr<P2> const &, sp::polymorphic_cast_tag );
00844   template< typename P2 >
00845     inline  explicit
00846     shared_ptr( std::auto_ptr<P2> & );
00847   template< typename AP >
00848     inline  explicit
00849     shared_ptr( AP
00850               , typename enable_if_auto_ptr<AP,void*>::type = 0
00851               );
00852   template< typename P2 >
00853     inline
00854     shared_ptr( shared_ptr<P2> const &
00855               , typename enable_if_ptr_convertible<P2,P,void*>::type = 0
00856               ) throw();
00857   template< typename P2 >
00858     inline  shared_ptr &  operator = ( shared_ptr<P2> const & ) throw();
00859   template< typename P2 >
00860     inline  shared_ptr &  operator = ( std::auto_ptr<P2> & );
00861   template< typename AP >
00862     inline  typename enable_if_auto_ptr< AP, shared_ptr & >::type
00863     operator = ( AP );
00864   // copy-like functions
00865 
00866   inline  void reset() throw();
00867   template< typename P2 >
00868     inline  void  reset( P2 * );
00869   template< typename P2, typename D >
00870     inline  void  reset( P2 *, D );
00871   template< typename P2, typename D, typename A >
00872     inline  void  reset( P2 *, D, A );
00873   template< typename P2 >
00874     inline  void  reset( shared_ptr<P2> const &, P * );
00875   // reset functions
00876 
00877              inline  operator bool () const throw();
00878   inline  reference  operator *    () const throw();
00879   inline  P *        operator ->   () const throw();
00880   // pointer-like behavior
00881 
00882   inline  P *      get() const throw();
00883   inline  bool     unique() const throw();
00884   inline  long     use_count() const throw();
00885   // accessors
00886 
00887   template< typename P2 >
00888     inline  bool _internal_less( shared_ptr<P2> const & ) const;
00889   inline  void *  _internal_get_deleter( std::type_info const & ) const;
00890   inline  bool    _internal_equiv( shared_ptr const & ) const;
00891   // implementation helpers -- do not use
00892 
00893 private:
00894   P *                    px;  // contained pointer
00895   sp::shared_ctrl_handle pn;  // control information
00896 
00897 };  // shared_ptr
00898 
00899 template< typename P, typename P2 >
00900   inline bool  operator == ( shared_ptr<P> const &, shared_ptr<P2> const & );
00901 template< typename P, typename P2 >
00902   inline bool  operator != ( shared_ptr<P> const &, shared_ptr<P2> const & );
00903 template< typename P, typename P2 >
00904   inline bool  operator <  ( shared_ptr<P> const &, shared_ptr<P2> const & );
00905 
00906 template< typename P >
00907   inline void  swap( shared_ptr<P> &, shared_ptr<P> & );
00908 
00909 template< typename P, typename P2 >
00910   inline shared_ptr<P>  static_pointer_cast( shared_ptr<P2> const & );
00911 template< typename P, typename P2 >
00912   inline shared_ptr<P>  const_pointer_cast( shared_ptr<P2> const & );
00913 template< typename P, typename P2 >
00914   inline shared_ptr<P>  dynamic_pointer_cast( shared_ptr<P2> const & );
00915 
00916 template< typename P >
00917   inline P *  get_pointer( shared_ptr<P> const & );
00918 template< typename D, typename P >
00919   inline D *  get_deleter( shared_ptr<P> const & );
00920 
00921 template< typename C, typename T, typename P >
00922   inline std::basic_ostream<C,T> &  operator << ( std::basic_ostream<C,T> &
00923                                                 , shared_ptr<P> const &
00924                                                 );
00925 
00926 template< typename P >
00927   shared_ptr<P>::shared_ptr() throw()
00928   : px( 0 )
00929   , pn(         )
00930 { }
00931 
00932 template< typename P >
00933 template< typename P2 >  // P2 must be a complete type
00934   shared_ptr<P>::shared_ptr( P2 * p )
00935   : px( p )
00936   , pn( p )
00937 {
00938   sp::sp_enable_shared_from_this( this, p, p );
00939 }
00940 
00941 template< typename P >
00942 template< typename P2, typename D >  // D's copy c'tor must not throw
00943   shared_ptr<P>::shared_ptr( P2 * p, D d )
00944   : px( p    )
00945   , pn( p, d )
00946 {
00947   sp::sp_enable_shared_from_this( this, p, p );
00948 }
00949 
00950 template< typename P >
00951 template< typename P2, typename D, typename A >  // D's, A's copy c'tors must not throw
00952   shared_ptr<P>::shared_ptr( P2 * p, D d, A a )
00953   : px( p       )
00954   , pn( p, d, a )
00955 {
00956   sp::sp_enable_shared_from_this( this, p, p );
00957 }
00958 
00959 template< typename P >
00960   void
00961   shared_ptr<P>::swap( shared_ptr<P> & other ) throw()
00962 {
00963   std::swap( px, other.px );
00964   pn.swap( other.pn );
00965 }
00966 
00967 template< typename P >
00968   shared_ptr<P> &
00969   shared_ptr<P>::operator = ( shared_ptr const & other ) throw()
00970 {
00971   this_type( other ).swap( *this );
00972   return *this;
00973 }
00974 
00975 template< typename P >
00976 template< typename P2 >
00977   shared_ptr<P>::shared_ptr( weak_ptr<P2> const & other )
00978   : px( 0  )  // temporarily
00979   , pn( other.pn )  // may throw
00980 {
00981   px = other.px;  // safe to copy other.px, as pn(other.pn) did not throw
00982 }
00983 
00984 template< typename P >
00985 template< typename P2 >
00986   shared_ptr<P>::shared_ptr( weak_ptr<P2> const & other
00987                            , sp::sp_nothrow_tag
00988                            ) throw()
00989   : px( 0                        )  // temporarily
00990   , pn( other.pn, sp::sp_nothrow_tag() )
00991 {
00992   if( ! pn.empty() )
00993     px = other.px;
00994 }
00995 
00996 template< typename P >
00997 template< typename P2 >
00998   shared_ptr<P>::shared_ptr( shared_ptr<P2> const & other
00999                            , P * p
01000                            ) throw()
01001   : px( p        )
01002   , pn( other.pn )
01003 { }
01004 
01005 template< typename P >
01006 template< typename P2 >
01007   shared_ptr<P>::shared_ptr( shared_ptr<P2> const & other
01008                            , sp::static_cast_tag
01009                            )
01010   : px( static_cast<element_type*>( other.px ) )
01011   , pn( other.pn                               )
01012 { }
01013 
01014 template< typename P >
01015 template< typename P2 >
01016   shared_ptr<P>::shared_ptr( shared_ptr<P2> const & other
01017                            , sp::const_cast_tag
01018                            )
01019   : px( const_cast<element_type*>( other.px ) )
01020   , pn( other.pn                              )
01021 { }
01022 
01023 template< typename P >
01024 template< typename P2 >
01025   shared_ptr<P>::shared_ptr( shared_ptr<P2> const & other
01026                            , sp::dynamic_cast_tag
01027                            )
01028   : px( dynamic_cast<element_type*>( other.px ) )
01029   , pn( other.pn                                )
01030 {
01031   if( px == 0 )               // cast failed?
01032     pn = sp::shared_ctrl_handle();  // yes; need our own control information
01033 }
01034 
01035 template< typename P >
01036 template< typename P2 >
01037   shared_ptr<P>::shared_ptr( shared_ptr<P2> const & other
01038                            , sp::polymorphic_cast_tag
01039                            )
01040   : px( dynamic_cast<element_type*>( other.px ) )
01041   , pn( other.pn                                )
01042 {
01043   if( px == 0 )
01044     throw std::bad_cast();
01045 }
01046 
01047 template< typename P >
01048 template< typename P2 >
01049   shared_ptr<P>::shared_ptr( std::auto_ptr<P2> & other )
01050   : px( other.get() )
01051   , pn(             )  // temporarily
01052 {
01053   P2 *  tmp = other.get();
01054   pn = sp::shared_ctrl_handle( other );
01055   sp::sp_enable_shared_from_this( this, tmp, tmp );
01056 }
01057 
01058 template< typename P >
01059 template< typename AP >
01060   shared_ptr<P>::shared_ptr( AP other
01061                            , typename enable_if_auto_ptr<AP,void*>::type
01062                            )
01063   : px( other.get() )
01064   , pn(             )  // temporarily
01065 {
01066   typename AP::element_type *  tmp = other.get();
01067   pn = sp::shared_ctrl_handle( other );
01068   sp::sp_enable_shared_from_this( this, tmp, tmp );
01069 }
01070 
01071 template< typename P >
01072 template< typename P2 >
01073   shared_ptr<P>::shared_ptr( shared_ptr<P2> const & other
01074                            , typename enable_if_ptr_convertible<P2,P,void*>::type
01075                            ) throw()
01076   : px( other.px )
01077   , pn( other.pn )
01078   { }
01079 
01080 template< typename P >
01081 template< typename P2 >
01082   shared_ptr<P> &
01083   shared_ptr<P>::operator = ( shared_ptr<P2> const & other ) throw()
01084 {
01085   this_type( other ).swap( *this );
01086   return *this;
01087 }
01088 
01089 template< typename P >
01090 template< typename P2 >
01091   shared_ptr<P> &
01092   shared_ptr<P>::operator = ( std::auto_ptr<P2> & other )
01093 {
01094   this_type( other ).swap( *this );
01095   return *this;
01096 }
01097 
01098 template< typename P >
01099 template< typename AP >
01100   typename enable_if_auto_ptr< AP, shared_ptr<P> & >::type
01101   shared_ptr<P>::operator = ( AP other )
01102 {
01103   this_type( other ).swap( *this );
01104   return *this;
01105 }
01106 
01107 template< typename P >
01108   void
01109   shared_ptr<P>::reset() throw()
01110 {
01111   this_type().swap( *this );
01112 }
01113 
01114 template< typename P >
01115 template< typename P2 >
01116   void
01117   shared_ptr<P>::reset( P2 * p )  // P2 must be a complete type
01118 {
01119   assert( p == 0 || p != px );  // oughtn't reset oneself
01120   this_type( p ).swap( *this );
01121 }
01122 
01123 template< typename P >
01124 template< typename P2, typename D >
01125   void
01126   shared_ptr<P>::reset( P2 * p, D d )
01127 {
01128   this_type( p, d ).swap( *this );
01129 }
01130 
01131 template< typename P >
01132 template< typename P2, typename D, typename A >
01133   void
01134   shared_ptr<P>::reset( P2 * p, D d, A a )
01135 {
01136   this_type( p, d, a ).swap( *this );
01137 }
01138 
01139 template< typename P >
01140 template< typename P2 >
01141   void
01142   shared_ptr<P>::reset( shared_ptr<P2> const & other, P * p )
01143 {
01144   this_type( other, p ).swap( *this );
01145 }
01146 
01147 template< typename P >
01148   shared_ptr<P>::operator bool () const throw()
01149 {
01150   return px;
01151 }
01152 
01153 template< typename P >
01154   typename sp::shared_ptr_traits<P>::reference
01155   //typename shared_ptr<P>::reference
01156   shared_ptr<P>::operator * () const throw()
01157 {
01158   assert( px != 0 );
01159   return *px;
01160 }
01161 
01162 template< typename P >
01163   P *
01164   shared_ptr<P>::operator -> () const throw()
01165 {
01166   assert( px != 0 );
01167   return px;
01168 }
01169 
01170 template< typename P >
01171   P *
01172   shared_ptr<P>::get() const throw()
01173 {
01174   return px;
01175 }
01176 
01177 template< typename P >
01178   bool
01179   shared_ptr<P>::unique() const throw()
01180 {
01181   return pn.unique();
01182 }
01183 
01184 template< typename P >
01185   long
01186   shared_ptr<P>::use_count() const throw()
01187 {
01188   return pn.use_count();
01189 }
01190 
01191 template< typename P >
01192 template< typename P2 >
01193   bool
01194   shared_ptr<P>::_internal_less( shared_ptr<P2> const & rhs ) const
01195 {
01196   return pn < rhs.pn;
01197 }
01198 
01199 template< typename P >
01200   void *
01201   shared_ptr<P>::_internal_get_deleter( std::type_info const & ti ) const
01202 {
01203   return pn.get_deleter( ti );
01204 }
01205 
01206 template< typename P >
01207   bool
01208   shared_ptr<P>::_internal_equiv( shared_ptr const & other ) const
01209 {
01210   return px == other.px && pn == other.pn;
01211 }
01212 
01213 template< typename P, typename P2 >
01214   bool
01215   operator == ( shared_ptr<P> const & a, shared_ptr<P2> const & b )
01216 {
01217   return a.get() == b.get();
01218 }
01219 
01220 template< typename P, typename P2 >
01221   bool
01222   operator != ( shared_ptr<P> const & a, shared_ptr<P2> const & b )
01223 {
01224   return a.get() != b.get();
01225 }
01226 
01227 template< typename P, typename P2 >
01228   bool
01229   operator < ( shared_ptr<P> const & a, shared_ptr<P2> const & b )
01230 {
01231   return a._internal_less(b);
01232 }
01233 
01234 template< typename P >
01235   void
01236   swap( shared_ptr<P> & a, shared_ptr<P> & b )
01237 {
01238   a.swap( b );
01239 }
01240 
01241 template< typename P, typename P2 >
01242   shared_ptr<P>
01243   static_pointer_cast( shared_ptr<P2> const & other )
01244 {
01245   return shared_ptr<P>( other, sp::static_cast_tag() );
01246 }
01247 
01248 template< typename P, typename P2 >
01249   shared_ptr<P>
01250   const_pointer_cast( shared_ptr<P2> const & other )
01251 {
01252   return shared_ptr<P>( other, sp::const_cast_tag() );
01253 }
01254 
01255 template< typename P, typename P2 >
01256   shared_ptr<P>
01257   dynamic_pointer_cast( shared_ptr<P2> const & other )
01258 {
01259   return shared_ptr<P>( other, sp::dynamic_cast_tag() );
01260 }
01261 
01262 template< typename P >
01263   P *
01264   get_pointer( shared_ptr<P> const & p )
01265 {
01266   return p.get();
01267 }
01268 
01269 template< typename D, typename P >
01270   D *
01271   get_deleter( shared_ptr<P> const & p )
01272 {
01273   return static_cast<D*>( p._internal_get_deleter( typeid(D)) );
01274 }
01275 
01276 template< typename C, typename T, typename P >
01277   std::basic_ostream<C,T> &
01278   operator << ( std::basic_ostream<C,T> & os, shared_ptr<P> const & p )
01279 {
01280   os << p.get();
01281   return os;
01282 }
01283 
01284 
01285 // ----------------------------------------------------------------------
01286 // weak_ptr - non-owning handle from which a shared_ptr can be obtained
01287 // ----------------------------------------------------------------------
01288 
01289 template< typename P >
01290   class weak_ptr
01291 {
01292   typedef  weak_ptr<P>  this_type;
01293 
01294   template< typename >  friend  class shared_ptr;
01295   template< typename >  friend  class weak_ptr;
01296 
01297 public:
01298   typedef  P  element_type;
01299 
01300   inline  weak_ptr() throw();
01301 
01302   //  generated copy constructor, assignment, destructor are fine
01303 
01304   inline  void  swap( this_type & other ) throw();
01305   template< typename P2 >
01306   inline
01307   weak_ptr( weak_ptr<P2> const & r
01308           , typename enable_if_ptr_convertible<P2,P,void*>::type = 0
01309           ) throw();
01310   template< typename P2 >
01311   inline
01312   weak_ptr( shared_ptr<P2> const & r
01313           , typename enable_if_ptr_convertible<P2,P,void*>::type = 0
01314           ) throw();
01315   template< typename P2 >
01316   inline  weak_ptr &  operator = (weak_ptr<P2> const & r) throw();
01317   template< typename P2 >
01318   inline  weak_ptr &  operator = (shared_ptr<P2> const & r) throw();
01319   // copy-like functions
01320 
01321   inline  shared_ptr<P>  lock() const throw();
01322   inline  long           use_count() const throw();
01323   inline  bool           expired() const throw();
01324   inline  bool           _empty() const; // extension, not in std::weak_ptr
01325   inline  void           reset() throw();
01326   // accessors
01327 
01328   inline  void  _internal_assign( P * px2, sp::shared_ctrl_handle const & pn2 );
01329   template< typename P2 >
01330     inline  bool _internal_less( weak_ptr<P2> const & rhs ) const;
01331 
01332 private:
01333   P *                   px;  // contained pointer
01334   sp::weak_ctrl_handle  pn;  // control information
01335 
01336 };  // weak_ptr
01337 
01338 template< typename P, typename P2 >
01339   inline  bool  operator < ( weak_ptr<P> const & a, weak_ptr<P2> const & b );
01340 
01341 template< typename P >
01342   inline  void  swap( weak_ptr<P> & a, weak_ptr<P> & b );
01343 
01344 template< typename P >
01345 weak_ptr<P>::weak_ptr() throw()
01346   : px( 0 )
01347   , pn(         )
01348 { }
01349 
01350 template< typename P >
01351 template< typename P2 >
01352   weak_ptr<P>::weak_ptr( weak_ptr<P2> const & r
01353                        , typename enable_if_ptr_convertible<P2,P,void*>::type
01354                        ) throw()
01355   : px( r.lock().get() )  // same as r.px, but doesn't risk invalidation
01356   , pn( r.pn           )
01357 { }
01358 
01359 template< typename P >
01360 template< typename P2 >
01361   weak_ptr<P>::weak_ptr( shared_ptr<P2> const & r
01362                        , typename enable_if_ptr_convertible<P2,P,void*>::type
01363                        ) throw()
01364   : px( r.px )
01365   , pn( r.pn )
01366 { }
01367 
01368 template< typename P >
01369 template< typename P2 >
01370   weak_ptr<P> &
01371   weak_ptr<P>::operator = (weak_ptr<P2> const & r) throw()
01372 {
01373   px = r.lock().get();
01374   pn = r.pn;
01375   return *this;
01376 }
01377 
01378 template< typename P >
01379 template< typename P2 >
01380   weak_ptr<P> &
01381   weak_ptr<P>::operator = (shared_ptr<P2> const & r) throw()
01382 {
01383   px = r.px;
01384   pn = r.pn;
01385   return *this;
01386 }
01387 
01388 template< typename P >
01389   shared_ptr<P>
01390   weak_ptr<P>::lock() const throw()
01391 {
01392   return shared_ptr<element_type>( *this, sp::sp_nothrow_tag() );
01393 }
01394 
01395 template< typename P >
01396   long
01397   weak_ptr<P>::use_count() const throw()
01398 {
01399   return pn.use_count();
01400 }
01401 
01402 template< typename P >
01403   bool
01404   weak_ptr<P>::expired() const throw()
01405 {
01406   return pn.use_count() == 0;
01407 }
01408 
01409 template< typename P >
01410   bool
01411   weak_ptr<P>::_empty() const // extension, not in std::weak_ptr
01412 {
01413   return pn.empty();
01414 }
01415 
01416 template< typename P >
01417   void
01418   weak_ptr<P>::reset() throw()
01419 {
01420   this_type().swap(*this);
01421 }
01422 
01423 template< typename P >
01424   void
01425   weak_ptr<P>::swap( this_type & other ) throw()
01426 {
01427   std::swap(px, other.px);
01428   pn.swap(other.pn);
01429 }
01430 
01431 template< typename P >
01432   void
01433   weak_ptr<P>::_internal_assign( P * px2, sp::shared_ctrl_handle const & pn2 )
01434 {
01435   px = px2;
01436   pn = pn2;
01437 }
01438 
01439 template< typename P >
01440 template< typename P2 >
01441   bool
01442   weak_ptr<P>::_internal_less( weak_ptr<P2> const & rhs ) const
01443 {
01444   return pn < rhs.pn;
01445 }
01446 
01447 template< typename P, typename P2 >
01448   bool
01449   operator < ( weak_ptr<P> const & a, weak_ptr<P2> const & b )
01450 {
01451   return a._internal_less(b);
01452 }
01453 
01454 template< typename P >
01455   void
01456   swap( weak_ptr<P> & a, weak_ptr<P> & b )
01457 {
01458   a.swap(b);
01459 }
01460 
01461 
01462 // ----------------------------------------------------------------------
01463 // do_nothing_deleter - for shared_ptrs not taking ownership
01464 // ----------------------------------------------------------------------
01465 
01466 struct do_nothing_deleter {
01467   inline  void  operator () ( void const * ) const;
01468 };
01469 
01470 void
01471 do_nothing_deleter::operator () ( void const * ) const
01472 { }
01473 
01474 
01475 }  // namespace CLHEP
01476 
01477 
01478 
01479 
01480 #endif  // CLHEP_MEMORY_H
01481 //
01482 // ======================================================================
01483 
01484 
01485 #if 0
01486 
01487 //  enable_shared_from_this.hpp
01488 
01489 template< typename T >
01490   class enable_shared_from_this
01491 {
01492 protected:
01493   enable_shared_from_this()
01494   { }
01495 
01496   ~enable_shared_from_this()
01497   { }
01498 
01499   enable_shared_from_this( enable_shared_from_this const & )
01500   { }
01501 
01502   enable_shared_from_this &
01503   operator = ( enable_shared_from_this const & )
01504   {
01505     return *this;
01506   }
01507 
01508 public:
01509   shared_ptr<T>
01510     shared_from_this()
01511   {
01512     shared_ptr<T>  p( weak_this_ );
01513     assert( p.get() == this );
01514     return p;
01515   }
01516 
01517   shared_ptr<T const>
01518     shared_from_this() const
01519   {
01520     shared_ptr<T const>  p( weak_this_ );
01521     assert( p.get() == this );
01522     return p;
01523   }
01524 
01525 public: // actually private, but avoids compiler template friendship issues
01526 
01527   // Note: invoked automatically by shared_ptr; do not call
01528   template< typename X, typename Y >
01529     void
01530     _internal_accept_owner( shared_ptr<X> const * ppx, Y * py ) const
01531   {
01532     if( weak_this_.expired() )
01533         weak_this_ = shared_ptr<T>( *ppx, py );
01534   }
01535 
01536 private:
01537     mutable weak_ptr<T>  weak_this_;
01538 };  // enable_shared_from_this<>
01539 
01540 
01541 //  enable_shared_from_this2.hpp
01542 
01543 namespace detail
01544 {
01545 
01546 class esft2_deleter_wrapper
01547 {
01548 private:
01549   shared_ptr<void>  deleter_;
01550 
01551 public:
01552   esft2_deleter_wrapper()
01553   { }
01554 
01555   template< typename T >
01556     void
01557     set_deleter( shared_ptr<T> const & deleter )
01558   {
01559     deleter_ = deleter;
01560   }
01561 
01562   template< typename T >
01563     void
01564     operator () ( T* )
01565   {
01566     assert( deleter_.use_count() <= 1 );
01567     deleter_.reset();
01568   }
01569 };
01570 
01571 } // namespace detail
01572 
01573 template< typename T >
01574   class enable_shared_from_this2
01575 {
01576 protected:
01577 
01578   enable_shared_from_this2()
01579   { }
01580 
01581   enable_shared_from_this2( enable_shared_from_this2 const & )
01582   { }
01583 
01584   enable_shared_from_this2 & operator = ( enable_shared_from_this2 const & )
01585   {
01586     return *this;
01587   }
01588 
01589   ~enable_shared_from_this2()
01590   {
01591     assert( shared_this_.use_count() <= 1 ); // ensure no dangling shared_ptrs
01592   }
01593 
01594 private:
01595   mutable  weak_ptr<T>    weak_this_;
01596   mutable  shared_ptr<T>  shared_this_;
01597 
01598 public:
01599 
01600   shared_ptr<T>
01601   shared_from_this()
01602   {
01603     init_weak_once();
01604     return shared_ptr<T>( weak_this_ );
01605   }
01606 
01607   shared_ptr<T const>
01608   shared_from_this() const
01609   {
01610     init_weak_once();
01611     return shared_ptr<T>( weak_this_ );
01612   }
01613 
01614 private:
01615 
01616   void init_weak_once() const
01617   {
01618     if( weak_this_._empty() )
01619     {
01620       shared_this_.reset( static_cast< T* >( 0 )
01621                         , detail::esft2_deleter_wrapper()
01622                         );
01623       weak_this_ = shared_this_;
01624     }
01625   }
01626 
01627 public:  // actually private, but avoids compiler template friendship issues
01628 
01629   // Note: invoked automatically by shared_ptr; do not call
01630   template< typename X, typename Y >
01631     void
01632     _internal_accept_owner( shared_ptr<X> * ppx, Y * py ) const
01633   {
01634     assert( ppx != 0 );
01635 
01636     if( weak_this_.use_count() == 0 )
01637       weak_this_ = shared_ptr<T>( *ppx, py );
01638     else if( shared_this_.use_count() != 0 )
01639     {
01640       assert( ppx->unique() ); // no weak_ptrs should exist either, but there's no way to check that
01641 
01642       detail::esft2_deleter_wrapper *  pd
01643         = boost::get_deleter<detail::esft2_deleter_wrapper>( shared_this_ );
01644       assert( pd != 0 );
01645 
01646       pd->set_deleter( *ppx );
01647 
01648       ppx->reset( shared_this_, ppx->get() );
01649       shared_this_.reset();
01650     }
01651   }
01652 };  // enable_shared_from_this2<>
01653 
01654 #endif  // 0