Boost logo

Boost Users :

Subject: Re: [Boost-users] [SmartPtr] enable_shared_from_raw
From: Gavin Lambert (gavinl_at_[hidden])
Date: 2014-07-24 19:21:04


On 25/07/2014 10:50, Frank Mori Hess wrote:
> Also, it doesn't need CRTP they way enable_shared_from_this does.

I was wondering about that. Does it handle the case where a base class
calls shared_from_raw with its own "this" pointer but the derived
pointer is the one that ends up actually being externally owned? I
think that (or something multi-inheritance-related) was the reason ESFT
required CRTP?

On a basic read-through of the code I *think* it's fine, but it never
hurts to get confirmation. :)

>> enable_shared_from_raw almost seems to fit the bill (according to
>> http://stackoverflow.com/questions/22184772/why-is-boostenable-shared-from-raw-so-undocumented),
>> but I encountered the same problem as in this post
>> (http://lists.boost.org/boost-users/2013/05/78833.php); it works with
>> shared_from_raw but not weak_from_raw.
>>
>> However this change:
>> https://github.com/boostorg/smart_ptr/pull/8
>> fixes that. It looks like the two calls went down different code paths for
>> some reason I can't fathom.
>
> I don't remember what the rationale was for the current behavior of
> weak_from_raw, or if I was the one who decided on that behavior.
> However, it seems like the current behavior could be useful in that it
> provides a way to query if an external shared_ptr ever actually took
> ownership of the object (or at least shared_from_raw has been used,
> which commits the coder to giving ownership to an external shared_ptr
> at some point).

I don't think there's any difference in that commitment with
shared_from_raw vs. weak_from_raw. Both of them are insufficient to
give a "real" owning pointer by themselves -- according to the
stackoverflow answer, any pointer obtained from either of these methods
cannot "actually" own the pointer, and instead the real raw pointer has
to be externally passed to a separate shared_ptr instance.

So calling shared_from_raw from within the constructor gives you no
additional guarantees (except that it actually works, at the moment,
while weak_from_raw does not until this patch is applied). Neither
provide a way to tell from the outside whether that second "real"
shared_ptr was ever constructed -- to do that, you'd have to check that
weak_this_ was *not* expired and shared_this_ *was* empty, if I'm
following the code correctly. (Or conversely, you're in the danger
state whenever shared_this_ is non-empty.)

Maybe it would be useful to explicitly expose a way to query for that?
Though to be honest other than unit tests and debugging I doubt anything
would actually use it (but the same could be said of shared_ptr's
use_count).

If you think it will help, I could post a separate PR with the other
style that I mentioned, which would make it more obvious that there's
little difference between shared_from_raw and weak_from_raw, and then
you (or whoever is in charge of SharedPtr at the moment) can choose
which you prefer. I just initially went with the one-liner in the hopes
that it'd be easier to get that into 1.56.


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net