|
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