$include_dir="/home/hyper-archives/boost/include"; include("$include_dir/msg-header.inc") ?>
From: Schoenborn, Oliver (Oliver.Schoenborn_at_[hidden])
Date: 2003-05-28 22:59:46
> -----Original Message-----
> From: Chuck Messenger [mailto:chuckm_at_[hidden]]
> Sent: Wednesday, May 28, 2003 2:35 PM
> To: boost_at_[hidden]
> Subject: [boost] Cyclic smart pointers (holy grail: the uber-pointer)
>
>
> Schoenborn, Oliver wrote:
> >>NoPtr lib -- noptrlib.sourceforge.net
> >>
> >>...I saw no mention of detecting dead cyclic object pools.
> >
> > Can you give me a short example of how NoPtr would even need to detect
that
> > to work correctly? I suspect that if you end up with cyclic object pool
you
> > are using NoPtr incorrectly (just like passing a pointer to an auto
variable
> > to a shared_ptr is incorrect use), but maybe an example will show me to
be
> > wrong.
> >
> > Oliver
>
> Here's my example (from an earlier thread):
>
> #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
> }
The above code does not make sense from a strict ownership point of view.
This is a quality (good or bad depending on what you are looking for) of
strict ownership: it forces you to be clear about who owns and for how long.
In the above code, you would have to decide whether A and B own their pimpl.
struct B_impl;
struct B {
DynObj<B_impl> pimpl_;
};
struct A_impl {
B b_;
};
struct A {
DynObj<A_impl> pimpl_;
};
struct B_impl {
A a_;
};
A construct_A() {
A a;
a.pimpl_.acquire(new A_impl); // a owns A_impl
B& b = a.pimpl_().b_;
b.pimpl_.acquire(new B_impl); // b owns B_impl
b.pimpl_().a_ = a; // compile error, logic wrong
// for strict ownership
return a;
}
Indeed because A owns the pimpl_, the line before returning doesn't make
sense for strict ownership. Without knowing more about your problem, there
are two possibilities:
- You always have A owns A_impl owns B owns B_impl refs A (what your
original code seems to say), in this case B_impl contains an RRef<A> instead
of a DynObj<A> and everything works
- Your program can also have B owns B_impl owns A owns A_impl refs B, i.e.
in some cases you have (indirectly) B owns A, other times A owns B. This one
requires more thought, and strict ownership may not be the solution since
this says that the ownership can have two forms.
Oliver