Ticket #1696: enable_shared_from_this_v3.patch

File enable_shared_from_this_v3.patch, 7.7 KB (added by fhess, 15 years ago)

new patch, passes esft_regtest test program

  • boost/enable_shared_from_this.hpp

     
    2323
    2424template<class T> class enable_shared_from_this
    2525{
     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;
    2643protected:
    2744
    28     enable_shared_from_this()
     45    enable_shared_from_this():
     46      _owned(false)
    2947    {
    3048    }
    3149
     
    3856        return *this;
    3957    }
    4058
    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()
    4261    {
     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);
    4366    }
    4467
    4568public:
    4669
    4770    shared_ptr<T> shared_from_this()
    4871    {
     72        init_internal_shared_once();
    4973        shared_ptr<T> p(_internal_weak_this);
    5074        BOOST_ASSERT(p.get() == this);
    5175        return p;
     
    5377
    5478    shared_ptr<T const> shared_from_this() const
    5579    {
     80        init_internal_shared_once();
    5681        shared_ptr<T const> p(_internal_weak_this);
    5782        BOOST_ASSERT(p.get() == this);
    5883        return p;
    5984    }
    6085
    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    }
    6690
    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    }
    69100};
    70101
    71102} // namespace boost
  • boost/shared_ptr.hpp

     
    4848namespace boost
    4949{
    5050
     51template<class T> class shared_ptr;
    5152template<class T> class weak_ptr;
    5253template<class T> class enable_shared_from_this;
    5354
     
    9091
    9192// enable_shared_from_this support
    9293
    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 )
     94struct ignore_enable_shared_from_this_tag {};
     95
     96template<class T, class Y> void sp_enable_shared_from_this( boost::shared_ptr<Y> * ptr, boost::enable_shared_from_this<T> const * pe )
    9497{
    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);
    96101}
     102}
    97103
    98104#ifdef _MANAGED
    99105
     
    104110    template<class T> sp_any_pointer( T* ) {}
    105111};
    106112
    107 inline void sp_enable_shared_from_this( shared_count const & /*pn*/, sp_any_pointer, sp_any_pointer )
     113inline void sp_enable_shared_from_this( sp_any_pointer, sp_any_pointer )
    108114{
    109115}
    110116
     
    115121# pragma set woff 3506
    116122#endif
    117123
    118 inline void sp_enable_shared_from_this( shared_count const & /*pn*/, ... )
     124inline void sp_enable_shared_from_this( ... )
    119125{
    120126}
    121127
     
    172178    template<class Y>
    173179    explicit shared_ptr( Y * p ): px( p ), pn( p ) // Y must be complete
    174180    {
    175         boost::detail::sp_enable_shared_from_this( pn, p, p );
     181        boost::detail::sp_enable_shared_from_this( this, p );
    176182    }
    177183
    178184    //
     
    183189
    184190    template<class Y, class D> shared_ptr(Y * p, D d): px(p), pn(p, d)
    185191    {
    186         boost::detail::sp_enable_shared_from_this( pn, p, p );
     192        boost::detail::sp_enable_shared_from_this( this, p );
    187193    }
    188194
    189195    // As above, but with allocator. A's copy constructor shall not throw.
    190196
    191197    template<class Y, class D, class A> shared_ptr( Y * p, D d, A a ): px( p ), pn( p, d, a )
    192198    {
    193         boost::detail::sp_enable_shared_from_this( pn, p, p );
     199        boost::detail::sp_enable_shared_from_this( this, p );
    194200    }
    195201
    196202//  generated copy constructor, assignment, destructor are fine...
     
    253259        }
    254260    }
    255261
     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
    256268#ifndef BOOST_NO_AUTO_PTR
    257269
    258270    template<class Y>
     
    260272    {
    261273        Y * tmp = r.get();
    262274        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 );
    264276    }
    265277
    266278#if !defined( BOOST_NO_SFINAE ) && !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
     
    270282    {
    271283        typename Ap::element_type * tmp = r.get();
    272284        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 );
    274286    }
    275287
    276288
     
    597609
    598610// get_deleter
    599611
     612namespace detail
     613{
    600614#if ( defined(__GNUC__) && BOOST_WORKAROUND(__GNUC__, < 3) ) || \
    601615    ( defined(__EDG_VERSION__) && BOOST_WORKAROUND(__EDG_VERSION__, <= 238) ) || \
    602616    ( defined(__HP_aCC) && BOOST_WORKAROUND(__HP_aCC, <= 33500) )
     
    604618// g++ 2.9x doesn't allow static_cast<X const *>(void *)
    605619// apparently EDG 2.38 and HP aCC A.03.35 also don't accept it
    606620
    607 template<class D, class T> D * get_deleter(shared_ptr<T> const & p)
     621template<class D, class T> D * basic_get_deleter(shared_ptr<T> const & p)
    608622{
    609623    void const * q = p._internal_get_deleter(BOOST_SP_TYPEID(D));
    610624    return const_cast<D *>(static_cast<D const *>(q));
     
    612626
    613627#else
    614628
    615 template<class D, class T> D * get_deleter(shared_ptr<T> const & p)
     629template<class D, class T> D * basic_get_deleter(shared_ptr<T> const & p)
    616630{
    617631    return static_cast<D *>(p._internal_get_deleter(BOOST_SP_TYPEID(D)));
    618632}
    619633
    620634#endif
    621635
     636class deleter_wrapper
     637{
     638    shared_ptr<const void> _deleter;
     639public:
     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
     660template<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
    622671} // namespace boost
    623672
    624673#ifdef BOOST_MSVC