$include_dir="/home/hyper-archives/boost-users/include"; include("$include_dir/msg-header.inc") ?>
Subject: Re: [Boost-users] [SmartPtr] enable_shared_from_raw / weak_from_raw remains not associated
From: Slava (Viatcheslav.Sysoltsev_at_[hidden])
Date: 2013-05-17 03:22:41
On Thu, 16 May 2013 20:09:58 +0200, Frank Mori Hess <fmh6jj_at_[hidden]>  
wrote:
> On Thu, May 16, 2013 at 5:58 AM, Slava
> <Viatcheslav.Sysoltsev_at_[hidden]> wrote:
>> I'm converting existing code with parent-child object tree to boost
>> shared_ptr/weak_ptr with parents having [now shared] ownership over the
>> children and children having weak reference to the parent. In the  
>> existing
>> code a parent usually becomes the children as constructor parameters,  
>> and
>> thus I have to extract the weak_ptr to "this" in constructor, which  
>> does not
>> work with current boost::enable_shared_from_this implementation. So I am
>> looking to enable_shared_from_raw alternative, which is promising, but
>> unfortunately does not quite work for my case. Here is a small example
>> demonstrating the issue:
>
>
>> struct Parent : public boost::enable_shared_from_raw
>> {
>>     Parent(boost::shared_ptr<Child> _child)
>>     {
>>         std::cout << "Construct Parent" << std::endl;
>>         this->child = _child;
>>         this->child->parent = boost::weak_from_raw(this);
>>     }
>
>
> weak_from_raw() doesn't work until after a shared_ptr has taken
> ownership of the object or shared_from_raw()  has been called.  It's
> been long enough don't remember what the rationale for this was, or if
> there even was a rationale, but the enable_shared_from_raw test case
> seems to expect this behavior.  From looking at the code, it seems
> like if you just called shared_from_raw prior to calling weak_from_raw
> it would work.
Thanks, right, the test cases, I always forget they are the good source of  
information!
The example works as expected (difference to previous is only addition of  
boost::shared_from_raw(this) in constructor):
#include <boost/smart_ptr/enable_shared_from_raw.hpp>
#include <iostream>
struct Parent;
struct Child
{
     Child()
     {
         std::cout << "Construct Child" << std::endl;
     }
     ~Child()
     {
         std::cout << "Destruct Child" << std::endl;
     }
     boost::weak_ptr<Parent> parent;
};
struct Parent : public boost::enable_shared_from_raw
{
     Parent(boost::shared_ptr<Child> _child)
     {
         std::cout << "Construct Parent" << std::endl;
         this->child = _child;
         boost::shared_from_raw(this);	// necessary for weak_from_raw() to  
function properly
         this->child->parent = boost::weak_from_raw(this);
     }
     ~Parent()
     {
         std::cout << "Destruct Parent" << std::endl;
     }
     boost::shared_ptr<Child> child;
};
int main()
{
     boost::shared_ptr<Child> child(new Child());
     boost::shared_ptr<Parent> parent(new Parent(child));
     std::cout << "child->parent is " << (child->parent.lock() ? "not null"  
: "null") << std::endl;
     parent.reset();
     std::cout << "child must be alone" << std::endl;
     std::cout << "child->parent is " << (child->parent.lock() ? "not null"  
: "null") << std::endl;
     return 0;
}
output:
==2269== Memcheck, a memory error detector
==2269== Copyright (C) 2002-2012, and GNU GPL'd, by Julian Seward et al.
==2269== Using Valgrind-3.8.1 and LibVEX; rerun with -h for copyright info
==2269== Command: a.out
==2269==
Construct Child
Construct Parent
child->parent is not null
Destruct Parent
child must be alone
child->parent is null
Destruct Child
==2269==
==2269== HEAP SUMMARY:
==2269==     in use at exit: 0 bytes in 0 blocks
==2269==   total heap usage: 5 allocs, 5 frees, 152 bytes allocated
==2269==
==2269== All heap blocks were freed -- no leaks are possible
==2269==
==2269== For counts of detected and suppressed errors, rerun with: -v
==2269== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 2 from 2)
I reached what I needed, but I have some bad feeling about how it works.  
It does not look sane, boost::shared_from_raw(this) class is there only to  
produce the desired side effect.
-- Slava