I was looking through the latest boost documentation, trying to find a way to get a shared_ptr from a this pointer of an object that already is contained by a shared_ptr somewhere, without knowing about that other shared_ptr out there. I noticed this intriguing comment in the latest docs:
[This constructor has been changed to a template in order to remember the actual pointer type passed. The destructor will call delete with the same pointer, complete with its original type, even when T does not have a virtual destructor, or is void.
In the current implementation, if p is convertible to counted_base *, shared_ptr will use the embedded reference count supplied by counted_base. This is an (experimental) attempt to provide a way for shared_ptr to be constructed from a raw pointer such as this. A free function shared_from_this(q) performs the conversion when q is convertible to counted_base const *.
The optional intrusive counting employed by the current implementation allows shared_ptr to interoperate with intrusive_ptr, an experimental generic intrusive-counted smart pointer.
Another possible implementation is to use a global pointer-to-count map instead of intrusive counting. shared_from_this would no longer be O(1), which is a concern for some users, although I do not expect any performance problems, since the operation is rare. Maintaining a global map is difficult; it needs to be initialized before any shared_ptr instances are constructed, and the initialization needs to be thread safe. In addition, under the Windows dynamic library model, it is possible for several maps to exist.
It is not yet clear which implementation should be used, or whether the specification should allow both; nevertheless, the ability to make a shared_ptr from this is considered essential by experienced smart pointer users.]
That looks like EXACTLY what I am looking for. But a couple things aren't clear to me: 1. Usage - The docs tell me its there but don't really say explicitly how to use it. It looks like, to use this, all I have to do is subclass boost::counted_base in my class that is being shared. Then I can just call shared_from_this to get another shared_ptr out of myself and it should just work. If that is all I have to do, then awesome! Is it really that easy or is there another step I am missing? 2. The word "experimental" above scares me. :-) If I use the counted_base subclass and shared_from_this function, is that code going to break later on if you guys change your minds? Anyway, I just want to reiterate what the comment at the end says, that the ability to make a shared_ptr from *this is essential to use these things. :-) -- Bobby --------------------------------------------------------------------- Bobby Thomale Senior Software Developer Inoveon Corporation http://www.inoveon.com/ ---------------------------------------------------------------------
From: "Bobby Thomale"
I was looking through the latest boost documentation, trying to find a way to get a shared_ptr from a this pointer of an object that already is contained by a shared_ptr somewhere, without knowing about that other shared_ptr out there.
I noticed this intriguing comment in the latest docs:
[...]
That looks like EXACTLY what I am looking for. But a couple things aren't clear to me:
1. Usage - The docs tell me its there but don't really say explicitly how to use it. It looks like, to use this, all I have to do is subclass boost::counted_base in my class that is being shared. Then I can just call shared_from_this to get another shared_ptr out of myself and it should just work. If that is all I have to do, then awesome! Is it really that easy or is there another step I am missing?
Yes, it should be that simple, if you use only shared_ptrs; weak pointers to counted_base-derived objects are a bit more complicated: "> If you derive from counted_base, what happens with weak_ptr?
It seems as though every live weak_ptr ends up keeping the object alive...
Weak pointers to intrusive counted objects require a bit of help from the user. As the count and the object are inseparable, a weak_ptr will keep the whole object alive. However, counted_base::dispose will be called when the use count drops to zero and only weak pointers to the object remain. If the object manages any resources, it should override dispose() and release them. An important special case is that any shared_ptr members should be reset(), or potential cycles won't be broken. The current implementation has a defect since shared_ptr::reset() is not guaranteed to never throw, but counted_base::dispose is. This will be fixed in the next release."
2. The word "experimental" above scares me. :-) If I use the counted_base subclass and shared_from_this function, is that code going to break later on if you guys change your minds?
I think that you'll be pretty safe. counted_base will most likely become "official" in 1.30.
Weak pointers to intrusive counted objects require a bit of help from the user. As the count and the object are inseparable, a weak_ptr will keep the whole object alive. However, counted_base::dispose will be called when the use count drops to zero and only weak pointers to the object remain. If the object manages any resources, it should override dispose() and release them. An important special case is that any shared_ptr members should be reset(), or potential cycles won't be broken.
Ah. So if I want to "destruct" my object when only weak pointers remain, I should essentially move the contents of my destructor to dispose? Will dispose get called once and only once, whether there are weak pointers or not, when the last reference goes away and the ref count goes to 0? Cool. I can live with that. -- Bobby --------------------------------------------------------------------- Bobby Thomale Senior Software Developer Inoveon Corporation http://www.inoveon.com/ ---------------------------------------------------------------------
participants (2)
-
Bobby Thomale
-
Peter Dimov