Ticket #1696: enable_shared_from_this_proof_of_concept.patch

File enable_shared_from_this_proof_of_concept.patch, 4.4 KB (added by Frank Mori Hess, 15 years ago)
  • boost/enable_shared_from_this.hpp

     
    2323
    2424template<class T> class enable_shared_from_this
    2525{
     26    void init_internal_shared_once() const
     27    {
     28        if(_owned == false && _internal_shared_this == 0)
     29        {
     30            _internal_shared_this = shared_ptr<T>(dynamic_cast<T *>(const_cast<enable_shared_from_this*>(this)),
     31                &_internal_shared_this_deleter, detail::ignore_shared_from_this_tag());
     32            BOOST_ASSERT(_internal_shared_this.get() == this);
     33            _internal_weak_this = _internal_shared_this;
     34        }
     35    }
     36
    2637protected:
    2738
    28     enable_shared_from_this()
     39    enable_shared_from_this():
     40      _owned(false)
    2941    {
    3042    }
    3143
     
    3850        return *this;
    3951    }
    4052
    41     ~enable_shared_from_this()
     53    virtual ~enable_shared_from_this()
    4254    {
    4355    }
    4456
     
    4658
    4759    shared_ptr<T> shared_from_this()
    4860    {
     61        init_internal_shared_once();
    4962        shared_ptr<T> p(_internal_weak_this);
    5063        BOOST_ASSERT(p.get() == this);
    5164        return p;
     
    5366
    5467    shared_ptr<T const> shared_from_this() const
    5568    {
     69        init_internal_shared_once();
    5670        shared_ptr<T const> p(_internal_weak_this);
    5771        BOOST_ASSERT(p.get() == this);
    5872        return p;
    5973    }
    6074
     75    bool owned() const
     76    {
     77      return _owned;
     78    }
     79
     80    void _internal_set_user_deleter(const detail::shared_count &user_deleter) const
     81    {
     82      init_internal_shared_once();
     83      _user_deleter = user_deleter;
     84    }
     85    static void _internal_shared_this_deleter(const enable_shared_from_this *obj)
     86    {
     87        detail::shared_count().swap(obj->_user_deleter);
     88    }
     89
    6190//  Note: No, you don't need to initialize _internal_weak_this
    6291//
    6392//  Please read the documentation, not the code
     
    6594//  http://www.boost.org/libs/smart_ptr/enable_shared_from_this.html
    6695
    6796    typedef T _internal_element_type; // for bcc 5.5.1
     97    mutable shared_ptr<_internal_element_type> _internal_shared_this;
     98    mutable detail::shared_count _user_deleter;
    6899    mutable weak_ptr<_internal_element_type> _internal_weak_this;
     100    mutable bool _owned;
    69101};
    70102
    71103} // namespace boost
  • boost/shared_ptr.hpp

     
    9090
    9191// enable_shared_from_this support
    9292
    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 )
     93struct ignore_shared_from_this_tag {};
     94
     95template<class T, class Y> void sp_enable_shared_from_this( shared_count & pn, boost::enable_shared_from_this<T> const * pe, Y const * px)
    9496{
    95     if(pe != 0) pe->_internal_weak_this._internal_assign(const_cast<Y*>(px), pn);
     97    if(pe != 0)
     98    {
     99        pe->_internal_set_user_deleter(pn);
     100        pn.swap(pe->_internal_shared_this.pn);
     101        pe->_internal_shared_this.reset();
     102        pe->_owned = true;
    96103}
     104}
    97105
    98106#ifdef _MANAGED
    99107
     
    104112    template<class T> sp_any_pointer( T* ) {}
    105113};
    106114
    107 inline void sp_enable_shared_from_this( shared_count const & /*pn*/, sp_any_pointer, sp_any_pointer )
     115inline void sp_enable_shared_from_this( shared_count & /*pn*/, sp_any_pointer, sp_any_pointer )
    108116{
    109117}
    110118
     
    115123# pragma set woff 3506
    116124#endif
    117125
    118 inline void sp_enable_shared_from_this( shared_count const & /*pn*/, ... )
     126inline void sp_enable_shared_from_this( shared_count & /*pn*/, ... )
    119127{
    120128}
    121129
     
    186194        boost::detail::sp_enable_shared_from_this( pn, p, p );
    187195    }
    188196
     197    // constructor that doesn't trigger enable_shared_from_this code, needed
     198    // for enable_shared_from_this internal implementation
     199    template<class Y, class D> shared_ptr(Y * p, D d, detail::ignore_shared_from_this_tag tag):
     200      px(p), pn(p, d)
     201    {}
     202
     203
    189204    // As above, but with allocator. A's copy constructor shall not throw.
    190205
    191206    template<class Y, class D, class A> shared_ptr( Y * p, D d, A a ): px( p ), pn( p, d, a )
     
    480495#endif
    481496
    482497    T * px;                     // contained pointer
     498/*yikes! made pn public to get this hack working */
     499public:
    483500    boost::detail::shared_count pn;    // reference counter
    484501
    485502};  // shared_ptr