Boost logo

Boost :

From: Frank Mori Hess (fmhess_at_[hidden])
Date: 2008-04-30 22:00:27


-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

On Wednesday 30 April 2008 17:21, Frank Mori Hess wrote:
> On Wednesday 30 April 2008 13:42 pm, Peter Dimov wrote:
> > In principle, a new esft may avoid this by:
> >
> > 1. Allowing only (expired) weak_ptr instances to be created in the
> > constructor;
> > 2. Bringing the weak_ptr instances back to life once a shared_ptr
> > takes ownership.
> >
> > This however seems to require a relatively major surgery to
> > sp_counted_base and friends; I'm not sure I'm comfortable with that.
>
> It sounds like you're heading in the direction of the "shared_from_that"
> idea I floated earlier:
>
> http://lists.boost.org/Archives/boost/2008/04/135372.php
>
> which would allow client code to distinguish between the cases of
> "shared_ptr not available yet" and "shared_ptr expired".

To be clear what I'm talking about, I've implemented a little proof of
concept of "shared_from_that" and "enable_shared_from_that", and a little
test program.

- --
Frank

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.6 (GNU/Linux)

iD8DBQFIGSRB5vihyNWuA4URAn3QAKDcxbahawcYUr5mAH6KRRPT29zaoQCfTi0e
izDdZ98Cpi5PPr3D1nk0E8k=
=HHfh
-----END PGP SIGNATURE-----

--Boundary-00=_BRSGIXdkcuuiG8S
Content-Type: text/x-c++hdr; charset="iso-8859-1";
        name="enable_shared_from_that.hpp"
Content-Transfer-Encoding: quoted-printable
Content-Disposition: attachment;
        filename="enable_shared_from_that.hpp"

#ifndef BOOST_ENABLE_SHARED_FROM_THAT_HPP_INCLUDED
#define BOOST_ENABLE_SHARED_FROM_THAT_HPP_INCLUDED

//
// enable_shared_from_that.hpp
//
// Copyright (c) 2002 Peter Dimov
// Copyright (c) 2008 Frank Mori Hess
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// http://www.boost.org/libs/smart_ptr/enable_shared_from_this.html
//

#include <boost/shared_ptr.hpp>
#include <boost/weak_ptr.hpp>
#include <boost/assert.hpp>
#include <boost/config.hpp>

namespace boost
{

class enable_shared_from_that;
template< class Y > void sp_accept_owner( shared_ptr<Y> * ptr, enable_share=
d_from_that const * pe );
template< class Y > void sp_accept_owner( shared_ptr<Y> * ptr, enable_share=
d_from_that const * pe, void * /*pd*/ );

template<typename T>
class shared_from_that
{
public:
    shared_from_that(): _that(0)
    {
    }
    explicit shared_from_that(T *that): _that(that), _shared_weak(that->_in=
ternal_shared_weak)
    {}
   =20
    shared_ptr<T> get() const
    {
        if(weak_is_empty()) return shared_ptr<T>();
        shared_ptr<const void> shared(*_shared_weak);
        return shared_ptr<T>(shared, _that);
    }
private:
    bool weak_is_empty() const
    {
        if(!_shared_weak) return true;
        weak_ptr<const void> empty;
        return !(*_shared_weak < empty) && !(empty < *_shared_weak);
    }
   =20
    T *_that;
    shared_ptr<weak_ptr<const void> > _shared_weak;
};

class enable_shared_from_that
{
public:
    shared_ptr<weak_ptr<const void> > _internal_shared_weak;
protected:

    enable_shared_from_that(): _internal_shared_weak(new weak_ptr<const voi=
d>())
    {
    }

    enable_shared_from_that(enable_shared_from_that const &): _internal_sha=
red_weak(new weak_ptr<const void>())
    {
    }

    enable_shared_from_that & operator=3D(enable_shared_from_that const &)
    {
        return *this;
    }

    ~enable_shared_from_that()
    {
    }
private:

    template<typename U>
    void sp_accept_owner( shared_ptr<U> & owner ) const
    {
        if( _internal_shared_weak->use_count() =3D=3D 0 )
        {
            *_internal_shared_weak =3D owner;
        }
    }

    template< class Y > friend void sp_accept_owner( shared_ptr<Y> * ptr, e=
nable_shared_from_that const * pe );
    template< class Y > friend void sp_accept_owner( shared_ptr<Y> * ptr, e=
nable_shared_from_that const * pe, void * /*pd*/ );
};

template< class Y > inline void sp_accept_owner( shared_ptr<Y> * ptr, enabl=
e_shared_from_that const * pe )
{
    if( pe !=3D 0 )
    {
        pe->sp_accept_owner( *ptr );
    }
}

template< class Y > inline void sp_accept_owner( shared_ptr<Y> * ptr, enabl=
e_shared_from_that const * pe, void * /*pd*/ )
{
    if( pe !=3D 0 )
    {
        pe->sp_accept_owner( *ptr );
    }
}

} // namespace boost

#endif // #ifndef BOOST_ENABLE_SHARED_FROM_THAT_HPP_INCLUDED

--Boundary-00=_BRSGIXdkcuuiG8S
Content-Type: text/x-c++src; charset="iso-8859-1";
        name="shared_from_that_test.cpp"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
        filename="shared_from_that_test.cpp"

#include <iostream>
#include <boost/enable_shared_from_that.hpp>
#include <boost/shared_ptr.hpp>
#include <cassert>

class X: public boost::enable_shared_from_that
{
public:
    X(boost::shared_from_that<X> &that)
    {
        that = boost::shared_from_that<X>(this);
    }
};

int main()
{
    boost::shared_from_that<X> sft;
    X *px = new X(sft);
    assert(!sft.get()); // sft.get() returns empty shared_ptr
    {
        boost::shared_ptr<X> spx(px);
        boost::shared_ptr<X> spx2 = sft.get(); // sft.get() returns shared_ptr that shares ownership with spx
        assert(spx == spx2);
        assert(!(spx < spx2) && !(spx2 < spx));
    }
    try
    {
        sft.get(); // sft.get() throws since px has been deleted
        assert(false);
    }
    catch(boost::bad_weak_ptr &err)
    {}
    return 0;
}

--Boundary-00=_BRSGIXdkcuuiG8S--


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk