I took another look at the JLS and it does seem to be
perfectly legal to keep a ref to an object after the
finalize() method has been run. Because of this, it
is possible to turn the CObject into a TclEvent
and enqueue it directly. The only catch is that
CObject already extends InternalRep, and MI
is not allowed in Java.

Of course, InternalRep is just an abstract class,
so I don't see any real reason why we should not
be able to just turn it into an interface. With
that change, CObject can be made to extend
TclEvent, like so:

Don't try to apply this patch, it is just a mock
up. To really get this working requires patching
about 20 files, so this is just to give you
the flavor idea of how it works. I ran this
through the test suite, and it seems to be
working just fine.


--- CObject.java        1998/10/14 21:09:10     1.1.1.1
+++ CObject.java        2000/10/23 05:37:24

-class CObject extends InternalRep {

+class CObject extends TclEvent implements InternalRep {

@@ -76,6 +71,12 @@
 {
     this.objPtr = objPtr;
     incrRefCount(objPtr);
+
+    // Use the notifier member from the TclEvent class
+    // to hold a ref to the Notifier this CObject
+    // was created in.
+
+    notifier = Notifier.getNotifierForThread(Thread.currentThread());
 }
 ^L
 /*

@@ -217,12 +219,18 @@
 protected void finalize() throws Throwable
 {
     if (objPtr != 0) {
-       /*
-        * If the object is finalized while the reference is still valid, 
-        * we need to sever the connection to the underlying Tcl_Obj*.
-        */
+        // If a CObject is finalized while the reference is still valid,
+        // we need to send the reference back to the thread that created it.
+        // We can then sever the connection to the underlying Tcl_Obj* by
+        // calling decrRefCount() in that thread. Note that we can not wait
+        // for the event to be processed, as that would block the GC thread.
+        // Also note that this is a little tricky because the object has
+        // already been finalized by the time be put it back into the queue.
+        // This is ok because the memory will not be garbage collected until
+        // after the event has been processed and the last reference dropped.
 
-        decrRefCount(objPtr);
+        notifier.queueEvent(this, TCL.QUEUE_TAIL);
     }
     super.finalize();
 }
@@ -230,6 +238,29 @@
+
+public int processEvent(int flags) {
+    return 1;
+}


Any comments on changing InternalRep over to an
interface or this approach to putting a CObject
directly into the event queue?

Mo DeJong
Red Hat Inc

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