Ticket #1696: enable_shared_from_this_v3.patch
File enable_shared_from_this_v3.patch, 7.7 KB (added by , 15 years ago) |
---|
-
boost/enable_shared_from_this.hpp
23 23 24 24 template<class T> class enable_shared_from_this 25 25 { 26 // dynamic cast to template type doesn't work in constructor, so we have 27 // to use lazy initialization 28 void init_internal_shared_once() const 29 { 30 if(_owned == false && _internal_shared_this == 0) 31 { 32 _internal_shared_this = shared_ptr<T>(dynamic_cast<T *>(const_cast<enable_shared_from_this*>(this)), 33 detail::deleter_wrapper(), detail::ignore_enable_shared_from_this_tag()); 34 BOOST_ASSERT(_internal_shared_this.get() == this); 35 _internal_weak_this = _internal_shared_this; 36 } 37 } 38 39 typedef T _internal_element_type; // for bcc 5.5.1 40 mutable shared_ptr<_internal_element_type> _internal_shared_this; 41 mutable weak_ptr<_internal_element_type> _internal_weak_this; 42 mutable bool _owned; 26 43 protected: 27 44 28 enable_shared_from_this() 45 enable_shared_from_this(): 46 _owned(false) 29 47 { 30 48 } 31 49 … … 38 56 return *this; 39 57 } 40 58 41 ~enable_shared_from_this() 59 // virtual destructor because we need a vtable for dynamic_cast from base to derived to work 60 virtual ~enable_shared_from_this() 42 61 { 62 // make sure no dangling shared_ptr objects were created by the 63 // user calling shared_from_this() but never passing ownership of the object 64 // to a shared_ptr. 65 BOOST_ASSERT(owned() || _internal_shared_this.unique() || _internal_shared_this == 0); 43 66 } 44 67 45 68 public: 46 69 47 70 shared_ptr<T> shared_from_this() 48 71 { 72 init_internal_shared_once(); 49 73 shared_ptr<T> p(_internal_weak_this); 50 74 BOOST_ASSERT(p.get() == this); 51 75 return p; … … 53 77 54 78 shared_ptr<T const> shared_from_this() const 55 79 { 80 init_internal_shared_once(); 56 81 shared_ptr<T const> p(_internal_weak_this); 57 82 BOOST_ASSERT(p.get() == this); 58 83 return p; 59 84 } 60 85 61 // Note: No, you don't need to initialize _internal_weak_this 62 // 63 // Please read the documentation, not the code 64 // 65 // http://www.boost.org/libs/smart_ptr/enable_shared_from_this.html 86 bool owned() const 87 { 88 return _owned; 89 } 66 90 67 typedef T _internal_element_type; // for bcc 5.5.1 68 mutable weak_ptr<_internal_element_type> _internal_weak_this; 91 template<typename U> 92 void _internal_accept_owner(shared_ptr<U> &owner) const 93 { 94 init_internal_shared_once(); 95 get_deleter<detail::deleter_wrapper>(_internal_shared_this)->set_deleter(owner); 96 owner = _internal_shared_this; 97 _internal_shared_this.reset(); 98 _owned = true; 99 } 69 100 }; 70 101 71 102 } // namespace boost -
boost/shared_ptr.hpp
48 48 namespace boost 49 49 { 50 50 51 template<class T> class shared_ptr; 51 52 template<class T> class weak_ptr; 52 53 template<class T> class enable_shared_from_this; 53 54 … … 90 91 91 92 // enable_shared_from_this support 92 93 93 template<class T, class Y> void sp_enable_shared_from_this( shared_count const & pn, boost::enable_shared_from_this<T> const * pe, Y const * px ) 94 struct ignore_enable_shared_from_this_tag {}; 95 96 template<class T, class Y> void sp_enable_shared_from_this( boost::shared_ptr<Y> * ptr, boost::enable_shared_from_this<T> const * pe ) 94 97 { 95 if(pe != 0) pe->_internal_weak_this._internal_assign(const_cast<Y*>(px), pn); 98 if(pe != 0) 99 { 100 pe->_internal_accept_owner(*ptr); 96 101 } 102 } 97 103 98 104 #ifdef _MANAGED 99 105 … … 104 110 template<class T> sp_any_pointer( T* ) {} 105 111 }; 106 112 107 inline void sp_enable_shared_from_this( s hared_count const & /*pn*/, sp_any_pointer, sp_any_pointer )113 inline void sp_enable_shared_from_this( sp_any_pointer, sp_any_pointer ) 108 114 { 109 115 } 110 116 … … 115 121 # pragma set woff 3506 116 122 #endif 117 123 118 inline void sp_enable_shared_from_this( shared_count const & /*pn*/,... )124 inline void sp_enable_shared_from_this( ... ) 119 125 { 120 126 } 121 127 … … 172 178 template<class Y> 173 179 explicit shared_ptr( Y * p ): px( p ), pn( p ) // Y must be complete 174 180 { 175 boost::detail::sp_enable_shared_from_this( pn, p, p );181 boost::detail::sp_enable_shared_from_this( this, p ); 176 182 } 177 183 178 184 // … … 183 189 184 190 template<class Y, class D> shared_ptr(Y * p, D d): px(p), pn(p, d) 185 191 { 186 boost::detail::sp_enable_shared_from_this( pn, p, p );192 boost::detail::sp_enable_shared_from_this( this, p ); 187 193 } 188 194 189 195 // As above, but with allocator. A's copy constructor shall not throw. 190 196 191 197 template<class Y, class D, class A> shared_ptr( Y * p, D d, A a ): px( p ), pn( p, d, a ) 192 198 { 193 boost::detail::sp_enable_shared_from_this( pn, p, p );199 boost::detail::sp_enable_shared_from_this( this, p ); 194 200 } 195 201 196 202 // generated copy constructor, assignment, destructor are fine... … … 253 259 } 254 260 } 255 261 262 // constructor that doesn't trigger enable_shared_from_this code, needed 263 // for enable_shared_from_this internal implementation 264 template<class Y, class D> shared_ptr(Y * p, D d, detail::ignore_enable_shared_from_this_tag tag): 265 px(p), pn(p, d) 266 {} 267 256 268 #ifndef BOOST_NO_AUTO_PTR 257 269 258 270 template<class Y> … … 260 272 { 261 273 Y * tmp = r.get(); 262 274 pn = boost::detail::shared_count(r); 263 boost::detail::sp_enable_shared_from_this( pn, tmp, tmp );275 boost::detail::sp_enable_shared_from_this( this, tmp ); 264 276 } 265 277 266 278 #if !defined( BOOST_NO_SFINAE ) && !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION ) … … 270 282 { 271 283 typename Ap::element_type * tmp = r.get(); 272 284 pn = boost::detail::shared_count( r ); 273 boost::detail::sp_enable_shared_from_this( pn, tmp, tmp );285 boost::detail::sp_enable_shared_from_this( this, tmp ); 274 286 } 275 287 276 288 … … 597 609 598 610 // get_deleter 599 611 612 namespace detail 613 { 600 614 #if ( defined(__GNUC__) && BOOST_WORKAROUND(__GNUC__, < 3) ) || \ 601 615 ( defined(__EDG_VERSION__) && BOOST_WORKAROUND(__EDG_VERSION__, <= 238) ) || \ 602 616 ( defined(__HP_aCC) && BOOST_WORKAROUND(__HP_aCC, <= 33500) ) … … 604 618 // g++ 2.9x doesn't allow static_cast<X const *>(void *) 605 619 // apparently EDG 2.38 and HP aCC A.03.35 also don't accept it 606 620 607 template<class D, class T> D * get_deleter(shared_ptr<T> const & p)621 template<class D, class T> D * basic_get_deleter(shared_ptr<T> const & p) 608 622 { 609 623 void const * q = p._internal_get_deleter(BOOST_SP_TYPEID(D)); 610 624 return const_cast<D *>(static_cast<D const *>(q)); … … 612 626 613 627 #else 614 628 615 template<class D, class T> D * get_deleter(shared_ptr<T> const & p)629 template<class D, class T> D * basic_get_deleter(shared_ptr<T> const & p) 616 630 { 617 631 return static_cast<D *>(p._internal_get_deleter(BOOST_SP_TYPEID(D))); 618 632 } 619 633 620 634 #endif 621 635 636 class deleter_wrapper 637 { 638 shared_ptr<const void> _deleter; 639 public: 640 deleter_wrapper() 641 {} 642 void set_deleter(const shared_ptr<const void> &deleter) 643 { 644 _deleter = deleter; 645 } 646 void operator()(const void *) 647 { 648 BOOST_ASSERT(_deleter.unique()); 649 _deleter.reset(); 650 } 651 template<typename D> 652 D* get_deleter() const 653 { 654 return boost::detail::basic_get_deleter<D>(_deleter); 655 } 656 }; 657 658 } // namespace detail 659 660 template<class D, class T> D * get_deleter(shared_ptr<T> const & p) 661 { 662 D *del = detail::basic_get_deleter<D>(p); 663 if(del == 0) 664 { 665 detail::deleter_wrapper *del_wrapper = detail::basic_get_deleter<detail::deleter_wrapper>(p); 666 if(del_wrapper) del = del_wrapper->get_deleter<D>(); 667 } 668 return del; 669 } 670 622 671 } // namespace boost 623 672 624 673 #ifdef BOOST_MSVC