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
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.