Hi again,

On Oct 19, 2012, at 3:55 PM, marvin persona <public.marvin@gmail.com> wrote:

In several of our use cases we pass the c++ half of the director down into a c++ framework, where the life cycle off the passed object (a smart pointer) is difficult to model.  In this case we simply want the "java half" to stay alive as long as the c++ half is alive, cMemOwned= true, or whatever.  I think that is what was being suggested, but haven't had time to investigate and implement.  For now we just hold the java object ref for "longer than necessary" which is actually wrong since in some hard to model cases it won't be long enough.  But we're in a beta now.

cMemOwned= true will not cause SWIG to keep the Java half alive, it will just cause the Java finalize() to deallocate the C++ object or not, afaict. It has nothing to do with the life-time of the Java objects, which is only related to the Java GC. And a C++ director without its Java half is useless as the whole idea is to invoke Java code.

In your first example from stack overflow, the MyHeldBase instance will be marked for garbage collection as soon as the hold() method returns as no one is keeping a reference. Whether its finalize will also deallocate your C++ object (cMemOwned) has no influence on whether your Java implementation of doSomething is still available - generally it will not as the corresponding object just got garbage collected. If it worked at any point, then only because you called doSomething on the director before the Java GC ran.

So you could try doing something with a separate case for those using a class member Collection, and a static method addOwned() (and perhaps rmOwned()).  And BTW, our initial approach was to tell our alpha users to just hold references in their own code, before we figured out some of these approaches.

That all seems over-engineered for a problem that would vanish if proxy classes would keep references to directors they receive.

The proxy  jni classes do hold a reference (as a long), which is how swig does everything.  I think changing cMemOwned essentially does what you want.  But...  I haven't looked at this in some weeks, and this is all hard to keep in your head for 30 minutes.  Maybe your suggestion is correct.  Perhaps you can mock up a small example demonstrating. Hopefully some "director experts" will chime in.

I am talking about the pure Java proxy classes, the ones you actually instantiate in your Java code. They keep a reference to the c++ object as "swigCPtr" (the long you mentioned), but they will not keep a reference to any Java object which is what would be needed. E.g. with the renamed setReceiver, Swig will generate the following code in the Proxy class:

private void setReceiverNative(Receiver receiver) {
  umundoNativeJavaJNI.Subscriber_setReceiverNative(swigCPtr, this, Receiver.getCPtr(receiver), receiver);
}

and umundoNativeJavaJNI.Subscriber_setReceiverNative is already JNI native. Nowhere will it keep a reference to the passed Receiver director.

The problem arises when the Receiver we passed goes out of scope. The only difference cMemOwned might make is whether it will crash with a SegFault as the Subscriber tries to access a freed pointer or whether it will fail somewhere in the C++ director class methods.

Again I'd like to argue that all Java proxy classes should maintain a reference to every director they get passed. Or that there ought to be a feature associated with directors that will cause proxy classes to keep a reference to instances of those directors when they receive them. Causing something like:

private Receiver _receiver;
private void setReceiverNative(Receiver receiver) {
  _receiver = receiver;
  umundoNativeJavaJNI.Subscriber_setReceiverNative(swigCPtr, this, Receiver.getCPtr(receiver), receiver);
}

to be generated.

Best regards
Stefan