CLHEP VERSION Reference Documentation
CLHEP Home Page CLHEP Documentation CLHEP Bug Reports |
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