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
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_) or I will go the painful Boehm's road and use conservative GC.
but a custom smart pointer would probably be a better choice for idiomatic Java code.
I wish you are right! I'll give myself all the evenings and week-ends until the end of May. If I fail to come up with something that is acceptable, I'll go conservative, because "Real artists ship!" :-)
As for intrusive_ptr, its main strength is that it has the size of a pointer.
HoHum ...scoped_ptr shares this "exclusive" strength ...
Adding a boolean would likely meet serious opposition.
Never mind the opposition. Is that the right thing to do or not? Since I don't understand your use cases, I just can't comment.
Your requirements are very interesting, however, and point to a shared/intrusive hybrid along the lines of:
template<class T> class intrusive_ptr_2 { T * px_; intrusive_ptr<Object> pn_;
// insert smart pointer boilerplate here ;-) };
I'm not sure I understand. pn_ is supposed to perform the refCounting part, and px_ is supposed to be the actual _body_ ?
It's an intrusive pointer that's close to shared_ptr in expressive power; you can use it to point to a subobject, for example.
Extending intrusive_ptr to accommodate the above along the lines of
template
class intrusive_ptr { T * px_; U * pn_; // not present when U == void }; could be feasible.
I'm lost. I don't see how this relates to the problem of providing an indirection ("pointer") construct such that, once you've have written xxxx_ptr<X> p(new X) ; you're done, once and for all, never asking _user_ code to deal with the intricacies of your xxxx_ptr *implementation*. When you come to think of it, a garbage collector is meant to provide _automatic_ garbage collection, not semi-automatic, or half-manual. Compounding the problem of memory management with additional idiosyncratic problems is not going to free that one remaining brain cell out of a total of 7, that holds the whole universe under your current consciousness level. A bad guarantee is worse than no guarantee at all. IMHO :) Many thanks -- JFB
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.
participants (2)
-
Jean-François Brouillet
-
Peter Dimov