C++Talk.NET Forum Index C++Talk.NET
C++ language newsgroups
 
Archives   FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

What is the rationale behind std::tr1::enable_shared_from_th

 
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ Language (Moderated)
View previous topic :: View next topic  
Author Message
Guest






PostPosted: Thu Dec 14, 2006 1:24 am    Post subject: What is the rationale behind std::tr1::enable_shared_from_th Reply with quote



I'm trying to find the rationale behind this class beyond the Boost
documentation
(http://www.boost.org/libs/smart_ptr/sp_techniques.html#from_this) and
Pete Becker's C++ Standard Library Extensions book (section 2.6, pp
57).

I understand the technicalities of the class, but what are some
practical uses? Are there any "gotchas"? It would seem to me that
once a class is "smartified" there are implications in a design
regarding its lifetime.

Regards,

Javier


--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
Alf P. Steinbach
Guest





PostPosted: Thu Dec 14, 2006 2:57 am    Post subject: Re: What is the rationale behind std::tr1::enable_shared_fro Reply with quote



* ljestrada (AT) hotmail (DOT) com:
Quote:
I'm trying to find the rationale behind this class beyond the Boost
documentation
(http://www.boost.org/libs/smart_ptr/sp_techniques.html#from_this) and
Pete Becker's C++ Standard Library Extensions book (section 2.6, pp
57).

I understand the technicalities of the class, but what are some
practical uses? Are there any "gotchas"?

enable_shared_from_this introduces a weak pointer.

There are two issues: manually adding covariant access down in a class
hierarchy, and ensuring that all objects of the class are allocated
dynamically with the pointer stored in a shared_ptr.

To make sure that all objects of the class are allocated dynamically you
can make the destructor protected or private. This avoids having to
code a factory function for each relevant constructor. Unfortunately
this technique was not in the FAQ last I looked, although the multiple
factory function solution was there.

To make sure that a pointer to a new'ed such object is immediately
placed in a smart pointer, you can overload operator new (the allocator
function), in order to make the "bare" new expression so obfuscated that
it won't be used by accident, and provide your own smart-pointer based
NEW macro; when we get more decent argument forwarding in C++, if we do,
a template function would be more appropriate.

For details see <url:
http://home.no.net/dubjai/win32cpptut/special/pointers/ch_01.pdf>,
section 1.3 (most specifically 1.3.3 and 1.3.5).

Regarding the covariance issue I know of no good solution.

It seems some kind of code generation beyond the ability of templates,
is called for.

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
Javier
Guest





PostPosted: Thu Dec 14, 2006 5:47 am    Post subject: Re: What is the rationale behind std::tr1::enable_shared_fro Reply with quote



Thx for the detailed explanation.

I cannot help to think that this will end up in a Gotcha, Effective TR1
or GotW book or article of some sort.


--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
Pete Becker
Guest





PostPosted: Thu Dec 14, 2006 5:50 am    Post subject: Re: What is the rationale behind std::tr1::enable_shared_fro Reply with quote

ljestrada (AT) hotmail (DOT) com wrote:
Quote:
I'm trying to find the rationale behind this class beyond the Boost
documentation
(http://www.boost.org/libs/smart_ptr/sp_techniques.html#from_this) and
Pete Becker's C++ Standard Library Extensions book (section 2.6, pp
57).

I understand the technicalities of the class, but what are some
practical uses? Are there any "gotchas"? It would seem to me that
once a class is "smartified" there are implications in a design
regarding its lifetime.


If Peter Dimov is reading this thread he can probably step in with a
real-world example. In the meantime, you'll have to make do with this
made-up example.

Suppose you've got a bunch of objects of type X being managed through
shared_ptr<X> objects. You've also got a central registry that holds
shared_ptr<X> objects for some of those X objects, but not all. And the
thing is, it's individual X objects themselves that decide whether they
should go into the registry. So you have something like this:

add_to_registry(shared_ptr<X>);

struct X
{
void decide()
{
if (I_should_be_registered())
add_to_registry(shared_ptr<X>(this)); // WRONG!!!
}
};

int main()
{
shared_ptr<X> x(new X);
x->decide();
return 0;
}

The problem with the line marked WRONG!!! is that this object is already
being managed by a shared_ptr<X> object, so now there are two
independent shared_ptr<X> objects, with two independent reference
counts, managing the same X object. The X object will be destroyed
twice, and that's not good.

So along comes enable_shared_from this:

struct X : enable_shared_from_this<X>
{
void decide()
{
if (I_should_be_registered())
add_to_registry(shared_from_this());
}
};

The member function shared_from_this returns a shared_ptr<X> object that
shares ownership with the shared_ptr<X> object defined in main (and any
others that may be hanging around). There's only one reference count,
and everybody's happy. (Except the person who had to write
enable_shared_from_this; it's tricky)

--

-- Pete
Roundhouse Consulting, Ltd. (www.versatilecoding.com)
Author of "The Standard C++ Library Extensions: a Tutorial and
Reference." (www.petebecker.com/tr1book)

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
Alf P. Steinbach
Guest





PostPosted: Fri Dec 15, 2006 4:42 am    Post subject: Re: What is the rationale behind std::tr1::enable_shared_fro Reply with quote

* David Abrahams:
Quote:
"Alf P. Steinbach" <alfps (AT) start (DOT) no> writes:

There are two issues: manually adding covariant access down in a class
hierarchy, and ensuring that all objects of the class are allocated
dynamically with the pointer stored in a shared_ptr.

IMO the canonical need for enable_shared_from_this doesn't fit either
of those categories:

There seems to be a slight misunderstanding.

I listed issues with /using/ enable_shared_from_this (the original
immediate context of my reply). When you use enable_shared_from_this
there is an issue with covariant access, and there is an issue with
guaranteeing an original shared_ptr. And for the latter one way of
dealing with the issue is as I explained.


Quote:
even when you know an object is managed by a
shared_ptr, you sometimes need that shared_ptr from inside the
object's member functions, but you can't get it without
shared_from_this.

Yes, that's one reason to use it.

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
David Abrahams
Guest





PostPosted: Fri Dec 15, 2006 5:01 am    Post subject: Re: What is the rationale behind std::tr1::enable_shared_fro Reply with quote

David Abrahams <dave@boost-consulting.com> writes:

Quote:
For example, consider a binary tree where parents "own" their children
and where there's a weak "back-link" from child nodes to their
parents.

struct node : enable_shared_from_this<node
{
set_children(shared_ptr<node> left, shared_ptr<node> right)
: left_child(left), right_child(right)

Whoops, obviously I went through some revisions of this as I was
composing it. Please remove the line above and add:

left_child = left; right_child = right;

to the body.

Quote:
{
left.parent = shared_from_this();
right.parent = shared_from_this();
}

weak_ptr<node> parent;
shared_ptr<node> left_child, right_child;
};


--
Dave Abrahams
Boost Consulting
www.boost-consulting.com

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
kwikius
Guest





PostPosted: Fri Dec 15, 2006 10:10 am    Post subject: Re: What is the rationale behind std::tr1::enable_shared_fro Reply with quote

Alf P. Steinbach wrote:

Quote:
To make sure that all objects of the class are allocated dynamically you
can make the destructor protected or private.

And it is at this point that you start to ask yourself...hmm. Doesnt
C++ need some form of automated memory management..

regards
Andy lLittle


--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
Pete Becker
Guest





PostPosted: Sat Dec 16, 2006 4:13 am    Post subject: Re: What is the rationale behind std::tr1::enable_shared_fro Reply with quote

Javier wrote:
Quote:
Peter,

[snip] It serves a very specific need.

I have a follow-up question: Given that enable_shared_from_this serves
a very specific need, why is shared_from_this() public? Shouldn't it
be protected? By making it public the very mechanism that controls the
reference count is exposed.


enable_shared_from_this embeds a weak_ptr object in the object being
managed, turning a non-intrusive smart pointer into an intrusive one.
From the outside, shared_from_this() doesn't pose any risks. Because of
that embedded object, it just returns a shared_ptr object that shares
ownership with any other shared_ptr objects that manage the same object.
Calling shared_from_this is just like constructing a shared_ptr object
from a weak_ptr object.

Which brings me back to the question you raised in your other reply: my
mind is on strike today, but I think you're right that once you've
derived from enable_shared_from_this, shared_ptr<Ty>(this) could be made
to work. In fact, I suspect it typically works today, but that's an
implementation detail, not an explicit requirement. And I think that's
appropriate. Requiring it would permit code like this:

Ty *ptr = new Ty;
shared_ptr<Ty> sp0(ptr); // okay
shared_ptr<TY> sp1(ptr); // ???

That second line would work if Ty was derived from
enable_shared_from_this, but it would be a disaster if it wasn't. You'd
end up with the resource being deleted twice. The right way to write
this code, because it works in both cases, is:

shared_ptr<Ty> sp0(new Ty);
shared_ptr<TY> sp1(sp0);

Providing shared_from_this reduces the temptation to write the first
variant.

--

-- Pete
Roundhouse Consulting, Ltd. (www.versatilecoding.com)
Author of "The Standard C++ Library Extensions: a Tutorial and
Reference." (www.petebecker.com/tr1book)

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
Display posts from previous:   
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ Language (Moderated) All times are GMT
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2006 phpBB Group
SEO toolkit © 2004-2006 webmedic.