On Thu, 16 May 2013 20:09:58 +0200, Frank Mori Hess <fmh6jj@gmail.com> wrote:
On Thu, May 16, 2013 at 5:58 AM, Slava <Viatcheslav.Sysoltsev@h-d-gmbh.de> 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