enable_shared_from_this - or an alternative..

classic Classic list List threaded Threaded
13 messages Options
Reply | Threaded
Open this post in threaded view
|

enable_shared_from_this - or an alternative..

Hughes, James
Hello All,

I have a couple of classes that I want to self register themselves with a
monitoring class. To do this they must pass a shared_ptr of themselves to
the monitor register function.

Therefore I need to make a shared_ptr form the this pointer, in the
constructor.

I have derived my classes from enabled_shared_from_this...(code to get
monitor omitted)

//psuedo code..
monitor::AddSource1(boost::shared_ptr<CSource1>);
monitor::AddSource2(boost::shared_ptr<CSource2>);

class CSource1 : public enable_shared_from_this<CSource1>
{
        CSource1() {  Monitor->AddSource(shared_from_this()); };
}

and

class CSource2 : public base1, public enable_shared_from_this<CSource2>
{
        CSource2() {  Monitor->AddSource(shared_from_this()); };}
}


This all compile fine, but when run, the shared_from_this call asserts with
a bad weak ptr - at the time of calling the weak_ptr has no content, and
looking at the boost code, I cannot see where it is supposed to get set to
access the this value.

Should I be using enable_shared_from_this in this way or is there a better
way to convert the this ptr to a shared_ptr in a constructor that I need to
use.


James
_______________________________________________
Boost-users mailing list
[hidden email]
http://lists.boost.org/mailman/listinfo.cgi/boost-users
Reply | Threaded
Open this post in threaded view
|

Re: enable_shared_from_this - or an alternative..

David Klein-2
[hidden email] wrote:

> Hello All,
>
> I have a couple of classes that I want to self register themselves
> with a monitoring class. To do this they must pass a shared_ptr of
> themselves to the monitor register function.
>
> Therefore I need to make a shared_ptr form the this pointer, in the
> constructor.
>
> I have derived my classes from enabled_shared_from_this...(code to get
> monitor omitted)
>
> //psuedo code..
> monitor::AddSource1(boost::shared_ptr<CSource1>);
> monitor::AddSource2(boost::shared_ptr<CSource2>);
>
> class CSource1 : public enable_shared_from_this<CSource1>
> {
> CSource1() {  Monitor->AddSource(shared_from_this()); };
> }
>
> and
>
> class CSource2 : public base1, public
> enable_shared_from_this<CSource2> {
> CSource2() {  Monitor->AddSource(shared_from_this()); };}
> }
>
>
> This all compile fine, but when run, the shared_from_this call
> asserts with a bad weak ptr - at the time of calling the weak_ptr has
> no content, and looking at the boost code, I cannot see where it is
> supposed to get set to access the this value.
>
> Should I be using enable_shared_from_this in this way or is there a
> better way to convert the this ptr to a shared_ptr in a constructor
> that I need to use.
>
>
> James
> _______________________________________________
> Boost-users mailing list
> [hidden email]
> http://lists.boost.org/mailman/listinfo.cgi/boost-users

hi james,

see: http://boost.org/libs/smart_ptr/sp_techniques.html#in_constructor

HTH dave
_______________________________________________
Boost-users mailing list
[hidden email]
http://lists.boost.org/mailman/listinfo.cgi/boost-users
Reply | Threaded
Open this post in threaded view
|

Re: enable_shared_from_this - or an alternative..

Stuart Dootson
In reply to this post by Hughes, James
On 3/20/06, James Hughes <[hidden email]> wrote:

> Hello All,
>
> I have a couple of classes that I want to self register themselves with a
> monitoring class. To do this they must pass a shared_ptr of themselves to
> the monitor register function.
>
> Therefore I need to make a shared_ptr form the this pointer, in the
> constructor.
>
> I have derived my classes from enabled_shared_from_this...(code to get
> monitor omitted)
>
> //psuedo code..
> monitor::AddSource1(boost::shared_ptr<CSource1>);
> monitor::AddSource2(boost::shared_ptr<CSource2>);
>
> class CSource1 : public enable_shared_from_this<CSource1>
> {
>         CSource1() {  Monitor->AddSource(shared_from_this()); };
> }
>
> and
>
> class CSource2 : public base1, public enable_shared_from_this<CSource2>
> {
>         CSource2() {  Monitor->AddSource(shared_from_this()); };}
> }
>
>
> This all compile fine, but when run, the shared_from_this call asserts with
> a bad weak ptr - at the time of calling the weak_ptr has no content, and
> looking at the boost code, I cannot see where it is supposed to get set to
> access the this value.
>
> Should I be using enable_shared_from_this in this way or is there a better
> way to convert the this ptr to a shared_ptr in a constructor that I need to
> use.
>
>
> James

I suspect you're running foul of this condition on
enable_shared_from_this: "There must exist at least one shared_ptr
instance p that owns  t." If you're using something like:

boost::shared_ptr<CSource1> pSource(new CSource1);

then when the CSource1 constructor is executed, the raw pointer hasn't
been assigned to the shared pointer yet.

HTH

Stuart Dootson
_______________________________________________
Boost-users mailing list
[hidden email]
http://lists.boost.org/mailman/listinfo.cgi/boost-users
Reply | Threaded
Open this post in threaded view
|

Re: enable_shared_from_this - or an alternative..

Hughes, James
In reply to this post by Hughes, James


> -----Original Message-----
> From: David Klein [mailto:[hidden email]]
> Sent: 20 March 2006 10:27
> To: [hidden email]
> Subject: Re: [Boost-users] enable_shared_from_this - or an
> alternative..
>
>
> [hidden email] wrote:
> > Hello All,
> >
> > I have a couple of classes that I want to self register themselves
> > with a monitoring class. To do this they must pass a shared_ptr of
> > themselves to the monitor register function.
> >
> > Therefore I need to make a shared_ptr form the this pointer, in the
> > constructor.
> >
> > I have derived my classes from
> enabled_shared_from_this...(code to get
> > monitor omitted)
> >
> > //psuedo code..
> > monitor::AddSource1(boost::shared_ptr<CSource1>);
> > monitor::AddSource2(boost::shared_ptr<CSource2>);
> >
> > class CSource1 : public enable_shared_from_this<CSource1>
> > {
> > CSource1() {  Monitor->AddSource(shared_from_this()); };
> > }
> >
> > and
> >
> > class CSource2 : public base1, public
> > enable_shared_from_this<CSource2> {
> > CSource2() {  Monitor->AddSource(shared_from_this()); };}
> > }
> >
> >
> > This all compile fine, but when run, the shared_from_this call
> > asserts with a bad weak ptr - at the time of calling the
> weak_ptr has
> > no content, and looking at the boost code, I cannot see where it is
> > supposed to get set to access the this value.
> >
> > Should I be using enable_shared_from_this in this way or is there a
> > better way to convert the this ptr to a shared_ptr in a constructor
> > that I need to use.
> >
> >
> > James
> > _______________________________________________
> > Boost-users mailing list
> > [hidden email]
> > http://lists.boost.org/mailman/listinfo.cgi/boost-users
>
> hi james,
>
> see: http://boost.org/libs/smart_ptr/sp_techniques.html#in_constructor
>
> HTH dave
> _______________________________________________
> Boost-users mailing list
> [hidden email]
> http://lists.boost.org/mailman/listinfo.cgi/boost-users


Thanks Dave, that does cover the problem well.

However, I cannot use the null deleter mechanism suggested as the shared_ptr
is passed on to monitor and is used there. The second scheme, using a
factory fucntion, would seem to be approriate, however, how to I handle
creation when the CSource1 class is actually to be used as a base class? If
the factory function is in CSource1, it doesnt know about any derived
classes. I don't want to have to write factory functions in every dervied
class - that seems a waste. Is there a correct technique for getting around
this issue? I am assuming a template of some description, but now sure what
that entails.




James

>
_______________________________________________
Boost-users mailing list
[hidden email]
http://lists.boost.org/mailman/listinfo.cgi/boost-users
Reply | Threaded
Open this post in threaded view
|

Re: enable_shared_from_this - or an alternative..

David Klein-2
In reply to this post by Hughes, James
[hidden email] wrote:
>> -----Original Message-----
>> From: David Klein [mailto:[hidden email]]
>> Sent: 20 March 2006 10:27
>> To: [hidden email]
>> Subject: Re: [Boost-users] enable_shared_from_this - or an
>> alternative..
>>>

[snip]

>
> Thanks Dave, that does cover the problem well.
>
> However, I cannot use the null deleter mechanism suggested as the
> shared_ptr is passed on to monitor and is used there. The second
> scheme, using a factory fucntion, would seem to be approriate,
> however, how to I handle creation when the CSource1 class is actually
> to be used as a base class? If the factory function is in CSource1,
> it doesnt know about any derived classes. I don't want to have to
> write factory functions in every dervied class - that seems a waste.
> Is there a correct technique for getting around this issue? I am
> assuming a template of some description, but now sure what that
> entails.
>
>
>
>
> James
>
>>
> _______________________________________________
> Boost-users mailing list
> [hidden email]
> http://lists.boost.org/mailman/listinfo.cgi/boost-users


is the following snipped what you have in mind?

struct base {};
struct derived1 : public base {};
struct derived2 : public derived1 {};

typedef boost::shared_ptr<base> base_ptr;

struct monitor
{
        void
        add( const base_ptr & _ptr)
        {
                // ...
        }
};

struct factory
{
        factory( monitor & _monitor ) :
                monitor_(_monitor)
        {
        }

        template<typename T>
        boost::shared_ptr<T>
        create( void )
        {
                boost::shared_ptr<T> tmp(new T);
                monitor_.add(tmp);
                return tmp;
        }

private:
        monitor & monitor_;
};

void
foo( void )
{
        monitor m;
        factory f(m);
        f.create<derived1>();
        f.create<derived2>();
}

-- dave
_______________________________________________
Boost-users mailing list
[hidden email]
http://lists.boost.org/mailman/listinfo.cgi/boost-users
Reply | Threaded
Open this post in threaded view
|

Re: enable_shared_from_this - or an alternative..

Alan M. Carroll
In reply to this post by Hughes, James
At 04:13 AM 3/20/2006, James Hughes wrote:
>Hello All,
>
>I have a couple of classes that I want to self register themselves with a
>monitoring class. To do this they must pass a shared_ptr of themselves to
>the monitor register function.
>
>Therefore I need to make a shared_ptr form the this pointer, in the
>constructor.

Why not use intrusive_ptr? Way back when, I wrote my own equivalent of that instead of using Boost.shared_ptr partly for this very reason (i.e., having to use smart pointers in constructors).  

_______________________________________________
Boost-users mailing list
[hidden email]
http://lists.boost.org/mailman/listinfo.cgi/boost-users
Reply | Threaded
Open this post in threaded view
|

Re: enable_shared_from_this - or an alternative..

Hughes, James
In reply to this post by Hughes, James

> >
> >>
> > _______________________________________________
> > Boost-users mailing list
> > [hidden email]
> > http://lists.boost.org/mailman/listinfo.cgi/boost-users
>
>
> is the following snipped what you have in mind?
>
> struct base {};
> struct derived1 : public base {};
> struct derived2 : public derived1 {};
>
> typedef boost::shared_ptr<base> base_ptr;
>
> struct monitor
> {
> void
> add( const base_ptr & _ptr)
> {
> // ...
> }
> };
>
> struct factory
> {
> factory( monitor & _monitor ) :
> monitor_(_monitor)
> {
> }
>
> template<typename T>
> boost::shared_ptr<T>
> create( void )
> {
> boost::shared_ptr<T> tmp(new T);
> monitor_.add(tmp);
> return tmp;
> }
>
> private:
> monitor & monitor_;
> };
>
> void
> foo( void )
> {
> monitor m;
> factory f(m);
> f.create<derived1>();
> f.create<derived2>();
> }
>
> -- dave
> _______________________________________________
> Boost-users mailing list
> [hidden email]
> http://lists.boost.org/mailman/listinfo.cgi/boost-users
>


Hi Dave,

Yes, I think that pretty much does exactly what I require. And gives me a
(almost comnpletely) generic factory class to boot!

Thanks very much!

James
_______________________________________________
Boost-users mailing list
[hidden email]
http://lists.boost.org/mailman/listinfo.cgi/boost-users
Reply | Threaded
Open this post in threaded view
|

Re: enable_shared_from_this - or an alternative..

Hughes, James
In reply to this post by Hughes, James
> -----Original Message-----
> From: Alan M. Carroll [mailto:[hidden email]]
> Sent: 20 March 2006 13:44
> To: [hidden email]
> Cc: [hidden email]
> Subject: Re: [Boost-users] enable_shared_from_this - or an
> alternative..
>
>
> At 04:13 AM 3/20/2006, James Hughes wrote:
> >Hello All,
> >
> >I have a couple of classes that I want to self register
> themselves with a
> >monitoring class. To do this they must pass a shared_ptr of
> themselves to
> >the monitor register function.
> >
> >Therefore I need to make a shared_ptr form the this pointer, in the
> >constructor.
>
> Why not use intrusive_ptr? Way back when, I wrote my own
> equivalent of that instead of using Boost.shared_ptr partly
> for this very reason (i.e., having to use smart pointers in
> constructors).  
>


Ah, just read my Boost book on intrusive pointers and I think they would
work. Not sure I will use for current issues, as have now written code for a
factory mechanism (which appears to work!), but certainly worth knowing for
the future. Thanks

Rgds

James
_______________________________________________
Boost-users mailing list
[hidden email]
http://lists.boost.org/mailman/listinfo.cgi/boost-users
Reply | Threaded
Open this post in threaded view
|

Re: enable_shared_from_this - or an alternative..

Nat Goodspeed
In reply to this post by Hughes, James
> -----Original Message-----
> From: [hidden email] [mailto:boost-users-
> [hidden email]] On Behalf Of James Hughes
> Sent: Monday, March 20, 2006 11:29 AM
> To: '[hidden email]'
> Subject: Re: [Boost-users] enable_shared_from_this - or an
alternative..
>
> > >I have a couple of classes that I want to self register
> > themselves with a
> > >monitoring class. To do this they must pass a shared_ptr of
> > themselves to
> > >the monitor register function.
> > >
> > >Therefore I need to make a shared_ptr form the this pointer, in the
> > >constructor.

[Nat] We have a similar need: the base class registers in a central
registry; we have many subclasses of the base class.

We use dumb base* pointers for this purpose. We can get away with that
because, just as the base-class constructor registers each instance, so
the base-class virtual destructor unregisters the instance.

Indeed, for our purposes, we don't WANT smart pointers in the registry.
If the last smart-pointer reference to a heap object goes away, we don't
want the reference in the registry to make the instance immortal. In
that case, the smart pointer to the heap object decrements the count to
0, the object is destroyed, and its destructor unregisters the instance.

A side benefit is that we don't have to care whether the instance is
static, auto or heap. Nor do we need factory functions.
_______________________________________________
Boost-users mailing list
[hidden email]
http://lists.boost.org/mailman/listinfo.cgi/boost-users
Reply | Threaded
Open this post in threaded view
|

Re: enable_shared_from_this - or an alternative..

Felipe Magno de Almeida
On 3/20/06, Nat Goodspeed <[hidden email]> wrote:


[snip]

> Indeed, for our purposes, we don't WANT smart pointers in the registry.
> If the last smart-pointer reference to a heap object goes away, we don't
> want the reference in the registry to make the instance immortal. In
> that case, the smart pointer to the heap object decrements the count to
> 0, the object is destroyed, and its destructor unregisters the instance.

Couldnt be a weak_ptr ?

[snip]

--
Felipe Magno de Almeida
_______________________________________________
Boost-users mailing list
[hidden email]
http://lists.boost.org/mailman/listinfo.cgi/boost-users
Reply | Threaded
Open this post in threaded view
|

Re: enable_shared_from_this - or an alternative..

Nat Goodspeed
In reply to this post by Hughes, James
> -----Original Message-----
> From: [hidden email] [mailto:boost-users-
> [hidden email]] On Behalf Of Felipe Magno de Almeida
> Sent: Monday, March 20, 2006 8:53 PM
> To: [hidden email]
> Subject: Re: [Boost-users] enable_shared_from_this - or an
alternative..
>
> On 3/20/06, Nat Goodspeed <[hidden email]> wrote:
>
> > Indeed, for our purposes, we don't WANT smart pointers in the
registry.
>
> Couldnt be a weak_ptr ?

[Nat] It could. But AFAICT the big advantage of a weak_ptr over a dumb
base* pointer is that a weak_ptr can detect when the referenced object
has been deleted. Since our base-class destructor unregisters the
object, deleting the registered pointer, that becomes a non-issue. So
for this use case, I see no particular advantage to using weak_ptr
rather than a dumb pointer.

Indeed, for this use case, there appear to be a couple of advantages to
using a dumb pointer. It's cheaper than a weak_ptr. But more
importantly, it works regardless of whether the referenced object is
allocated on the heap, on the stack or in static storage. That's useful
to us, as we do have a number of tracked objects declared statically.
_______________________________________________
Boost-users mailing list
[hidden email]
http://lists.boost.org/mailman/listinfo.cgi/boost-users
Reply | Threaded
Open this post in threaded view
|

Re: enable_shared_from_this - or an alternative..

Felipe Magno de Almeida
On 3/21/06, Nat Goodspeed <[hidden email]> wrote:

[snipped]

> >
> > Couldnt be a weak_ptr ?
>
> [Nat] It could. But AFAICT the big advantage of a weak_ptr over a dumb
> base* pointer is that a weak_ptr can detect when the referenced object
> has been deleted. Since our base-class destructor unregisters the
> object, deleting the registered pointer, that becomes a non-issue. So
> for this use case, I see no particular advantage to using weak_ptr
> rather than a dumb pointer.

weak-ptr is thread-safe.

So, if someone was trying to work with the pointer while the class
gets its reference counting to zero there wouldnt be a race condition.

But I dont know how important it was to your project. Probably you
enforced that this couldnt be possible somehow.

[snipped]

Best regards,
--
Felipe Magno de Almeida
_______________________________________________
Boost-users mailing list
[hidden email]
http://lists.boost.org/mailman/listinfo.cgi/boost-users
Reply | Threaded
Open this post in threaded view
|

Re: enable_shared_from_this - or an alternative..

Nat Goodspeed
In reply to this post by Hughes, James
> -----Original Message-----
> From: [hidden email] [mailto:boost-users-
> [hidden email]] On Behalf Of Felipe Magno de Almeida
> Sent: Tuesday, March 21, 2006 1:15 PM
> To: [hidden email]
> Subject: Re: [Boost-users] enable_shared_from_this - or an
alternative..
>
> > [Nat]
> > for this use case, I see no particular advantage to using weak_ptr
> > rather than a dumb pointer.
>
> weak-ptr is thread-safe.

[Nat] Okay, that's worth remembering, thanks. Our project is
single-threaded, so the issue didn't arise for us.
_______________________________________________
Boost-users mailing list
[hidden email]
http://lists.boost.org/mailman/listinfo.cgi/boost-users