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