Boost logo

Boost Users :

From: Peter Dimov (pdimov_at_[hidden])
Date: 2005-05-18 18:15:07

Jean-François Brouillet wrote:
>>> intrusive_ptr(T * p, bool add_ref = true);
>>> Effects: if(p != 0 && add_ref) intrusive_ptr_add_ref(p);.
>>> Postconditions: get() == p.
>> [...]
>> Right, so you can't call it a bug if the implementation does
>> exactly as stated. ;-)
> Consider:
> X * x = new X ;
> {
> intrusive_ptr<X> px(x) ;
> }
> Here, x is destroyed, and rightly so.
> Now (same example as yesterday):
> X * x = new X ;
> {
> intrusive_ptr<X, false> px(x) ;

          intrusive_ptr<X> px(x, false);

> }
> Here, x is destroyed *too*,

More precisely, intrusive_ptr_release is called exactly as specified in the
documentation for ~intrusive_ptr, and the count will probably go negative;
what X does with negative counts is up to the author of X, but usually bad
things happen.

> even though the additional "false"
> was supposed to mean: "please, don't mess-up with refCounts at
> all, *I* have everything under control.

It was never supposed to mean that. It means that the initial add_ref should
not be performed by the constructor, nothing more, nothing less (presumably
because the reference count is already one, or that someone has already
incremented it).

> If preserving the current intrusive_ptr semantics is paramount
> (as I kind of sense it is now), some confusion could be avoided
> by renaming "addRef" to something less ambiguous or suggestive.

So setting add_ref to false does not suggest that intrusive_ptr_add_ref will
not be called?

>> I'm pretty sure that a shared_ptr-based port can closely
>> approximate the original,
> "approximate"! That's the key. I don't want to "approximate".
> Either I find a way to *completely* hide the smart pointer modulo:
> - the initial "new X"
> - "on the fly" packaging of ``this'' when required __from within__
> (ie when passing ``this'' to some other unrelated method of
> some other class that requires an _envelope_ as argument and
> not a _body_, since my whole API, once translated from Java,
> will only expose _envelopes_)

We already went over this. You can package 'this' in a shared_ptr<> in a
member function by using enable_shared_from_this<>. You can package 'this'
in a shared_ptr<> in the constructor by using a null_deleter if the
shared_ptr<> will not be used outside the class, so it can't outlive it.

You can't package 'this' in a shared_ptr<> in the constructor and pass it to
someone else; you can do this in a static create() function. However, ...

> or I will go the painful Boehm's road and use conservative GC.

... if you want to stay true to the original Java code, GC may be the only
choice. Few smart pointers can cope with user code of the form

xxx_ptr p1( new X );
xxx_ptr p2( new X );

p1->set_callback( p2 );
p2->set_callback( p1 );

Even if you take care of every 'this', you can't stop people from creating
circular dependencies.

C++ code is usually designed from the ground up to avoid these scenarios (if
it doesn't ignore them outright) but Java doesn't have to.

Boost-users list run by williamkempf at, kalb at, bjorn.karlsson at, gregod at, wekempf at