I tried Mo's patch on CObject.finalize() to see if any TclBlend code will
leak C objects.  And it does.  There are a number of places in the "tcljava"
code that do:

        TclList.index(interp,list,0).toString();

This will cause a CObject to be garbage collected without first releasing
the native Tcl_Obj.  Does anyone has any opinion as to how we should go
about fixing these?  We can make all those instance of
TclList.index(...).toString() into:

        TclObject listElement = TclList.index(...);
        listElement.preserve();
        listElement.toString();
        listElement.release();

Or we can try to fix the CObject finalize.  I propose something like this:

       1. In CObject.finalize(), add any pointer to Tcl_Obj to a global
Vector.  Then create and queue a TclEvent.
        2. Inside the TclEvent, free all Tcl_Obj on the global Vector using
the Tcl interpreter thread.

My problem with the above approach is that the user of TclBlend must
register a Interp object to be used to perform the freeing of the Tcl_Obj.
Here is some pseudo code to do the above:

class CObject {
protected void finalize() throws Throwable
{
    if (objPtr != 0) {
        addToFreeList(objPtr);
    }
    super.finalize();
}

// a vector of Tcl_Obj pointers to be free'ed
private static Vector freeTclObjPtrs = new Vector();

// a lock object to synchronize access to the 'freeTclObjPtr'.
private static Object freeTclObjPtrsLock = new Object();

/*
 * Add a pointer to the to be free'ed vector.  The CObject containing
 * this pointer is being finalized by the GC.  This method is only
 * called by 'CObject.finalize()'.  This method is thread safe.
 */
private static void addToFreeList (long objPtr) {
    synchronized (freeTclObjPtrsLock) {
        freeTclObjPtrs.addElement(new Long(objPtr));
       // create and queue a TclEvent, to be completed
    }
}

/*
 * This method makes a copy of the existing 'freeTclObjPtr' vector and
 * starts to free the Tcl_Obj pointers contained in the old vector.  This
 * method should be called from inside of a TclEvent.
 */
static void freeTclObjs () {
    Vector newFreeTclObjPtrs = new Vector();
    Vector oldFreeTclObjPtrs;
    int    i;
    
    // we want to quickly grab the content of the existing
    // 'freeTclObjPtrs' so that we don't lock the GC thread
    synchronized (freeTclObjPtrsLock) {
        oldFreeTclObjPtrs = freeTclObjPtrs;
        freeTclObjPtrs = newFreeTclObjPtrs;
    }

    // now we can safely walk through the vector without any
    // synchronization problems.
    for (i = 0 ; i < oldFreeTclObjPtrs.size() ; i++) {
        decrRefCount(((Long) oldFreeTclObjPtrs.elementAt(i)).longValue());
    }
}
} // end of CObject

Any comments?

-- Jiang Wu
   [EMAIL PROTECTED]

----------------------------------------------------------------
The TclJava mailing list is sponsored by Scriptics Corporation.
To subscribe:    send mail to [EMAIL PROTECTED]  
                 with the word SUBSCRIBE as the subject.
To unsubscribe:  send mail to [EMAIL PROTECTED] 
                 with the word UNSUBSCRIBE as the subject.
To send to the list, send email to '[EMAIL PROTECTED]'. 
An archive is available at http://www.mail-archive.com/tcljava@scriptics.com

Reply via email to