Chuck Messenger wrote:
>
> Suppose I have a cyclic dependency between A and B, which are
> implemented with the pimpl idiom:
>
>      #include <boost/shared_ptr.hpp>
>      #include <iostream>
>
>      using namespace boost;
>      using namespace std;
>
>
>      struct B_impl;
>
>      struct B {
>          shared_ptr<B_impl> pimpl_;
>      };
>
>      struct A_impl {
>          A_impl() { cout << "new A\n"; }
>          ~A_impl() { cout << "del A\n"; }
>          B b_;
>      };
>
>      struct A {
>          shared_ptr<A_impl> pimpl_;
>          B get_B() const { return pimpl_->b_; }
>      };
>
>      struct B_impl {
>          B_impl() { cout << "new B\n"; }
>          ~B_impl() { cout << "del B\n"; }
>          A a_;
>      };
>
>      A get_A(const B& b) { return b.pimpl_->a_; }
>      B get_B(const A& a) { return a.pimpl_->b_; }
>
>      A construct_A() {
>          A a;
>          a.pimpl_.reset(new A_impl);  // a refcount is 1
>          B& b = a.pimpl_->b_;
>          b.pimpl_.reset(new B_impl);  // b refcount is 1
>          b.pimpl_->a_ = a;            // a refcount is 2
>
>          return a;
>      }
>
>      int main() {
>          {
>              A a = construct_A();
>          }
>          // ex-a's refcount is still 1, so object doesn't die
>      }
>
> OK, so we want to solve the problem that A and B keep eachother alive.
>
> I don't see how a weak_ptr can be used, without breaking the whole way
> I'm using A and B -- see get_A() and get_B().

[...]

> In general, the abstraction is: you have a group of intra-referential
> objects.  When any of the group is constructed, they are all
> constructed (so that the master count is temporarily > 1), and the
> master count is
> reset to 1.  When the master count goes to 0, the group is destructed.
> Hence, the group only remains alive as long as there are any external
> references (and as long as the intra-group references remain static).

In the situation you describe, A logically contains a B and B logically
contains an A, so A and B aren't independent; they actually form an AB
object. There is nothing to be gained from separating A and B as this
doesn't eliminate a dependency. If A and B are optional (but still tightly
coupled) parts of AB, the way I'd express this would probably be

class AB
{
    shared_ptr<A_impl> ai_;
    shared_ptr<B_impl> bi_;
};

There are several ways to allow A_impl and B_impl to communicate: store an
AB* pointer in each; pass a B_impl* to A_impl's methods that need it; keep a
B_impl* or a weak_ptr<B_impl> in A_impl.

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

Reply via email to