Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

gnu.java.awt.peer.gtk
Class GThreadNativeMethodRunner  view GThreadNativeMethodRunner download GThreadNativeMethodRunner.java

java.lang.Object
  extended byjava.lang.Thread
      extended bygnu.java.awt.peer.gtk.GThreadNativeMethodRunner
All Implemented Interfaces:
java.lang.Runnable

class GThreadNativeMethodRunner
extends java.lang.Thread

Implements pthread_create(), under glib's gthread abstraction, for use with GNU Classpath's --portable-native-sync option. This is used in gthread-jni.c Also implements a registry for threads, mapping Thread objects to small integers. The registry uses weak references for threads that aren't joinable, so that they will be garbage collected. There are a number of possible alternative implementations. The rest of this comment consists of an answer to a question that was raised on the commit-classpath mailing list: Mark Wielaard wrote: > Can't we assume that jobject and gpointer are both (void *) so we don't > need the int <-> Thread (global jobject ref) mapping? > Maybe there are platforms where jobject and gpointer aren't the same, > but I guess that is pretty unlikely. I agree with you on the pointer size issues. A gpointer is a void *, so it's certainly guaranteed to be at least as large as any other pointer. And a jobject is implicitly an opaque pointer (in Jikes RVM, we use small integers, but we coerce them into the representation of a pointer). The int <==> Thread mapping addresses a different issue. I realize that I did not document this properly (two and a half lines in thread_create), and the point is subtle (at least to me; took me a while to figure out). The int => Thread mapping always returns jobjects that are local references, not global ones. This is because Thread objects need to be able to go away and be garbage collected after the thread they refer to has died. If we keep a global object reference to a thread, then when do we delete that global object reference? We have an answer in the case of GThread objects that were explicitly created with the joinable attribute. It is safe for us to maintain a global reference to any joinable thread, since the joinable thread must linger (even if only in a zombie state) until it's explicitly joined via a g_thread_join() call. The global ref could be cleaned up at that point too. However, in the case of GThreads that were created non-joinable by g_thread_create(), and in the case of Java threads that were created within pure Java code (not via g_thread_create()), we don't want them to linger forever, and there is no way to tell when the last reference to such threads needs to expire. In the case of this application -- AWT with GTK peers -- it would probably be safe anyway, since there are not very many threads we create, but I was going for correctness even in the case of long-running programs that might set up and tear down AWT interfaces many times. So, I duplicated the POSIX thread-ID semantics. The thread ID of a non-joinable thread remains valid as long as that thread is still alive. Once that thread dies, the old thread ID may be reused at any moment. And that's why the array indexed by thread ID numbers is an array of weak references. That's also why the int => Thread jobject mapping function always returns local references, since global references would lock the Thread in memory forever. I would dearly love there to be a cleaner solution. I dislike the repeated dips from C code into Java that are necessary to look up thread ID numbers. If anyone can think of one, I'm all ears.


Nested Class Summary
 
Nested classes inherited from class java.lang.Thread
java.lang.Thread.UncaughtExceptionHandler
 
Field Summary
private  long funcArg
          The argument for the function "funcPtr(funcArg)".
private  long funcPtr
          The C function pointer that was passed to g_thread_create().
private static java.util.Set joinable
          Joinable threads need a hard reference, so that they won't go away when they die.
private static java.lang.ref.WeakReference[] threads
          THREADS is an array of threads, indexed by thread ID codes.
 
Fields inherited from class java.lang.Thread
MAX_PRIORITY, MIN_PRIORITY, NORM_PRIORITY
 
Constructor Summary
(package private) GThreadNativeMethodRunner(long funcPtr, long funcArg, boolean joinable)
           
 
Method Summary
(package private) static void deRegisterJoinable(java.lang.Thread thread)
          This method is only called from JNI, and only after we have succeeded in a thread_join() operation.
private  void nativeRun(long funcPtr, long funcArg)
           
private  void registerSelfJoinable()
          Only called from the constructor.
private static int registerThread(java.lang.Thread t)
          Used by threadToThreadID, below.
 void run()
          The method of Thread that will be run if there is no Runnable object associated with the Thread.
(package private) static java.lang.Thread threadIDToThread(int threadID)
           
(package private) static int threadToThreadID(java.lang.Thread t)
          Look up the Thread ID # for a Thread.
 
Methods inherited from class java.lang.Thread
activeCount, checkAccess, countStackFrames, currentThread, destroy, dumpStack, enumerate, getContextClassLoader, getDefaultUncaughtExceptionHandler, getId, getName, getPriority, getThreadGroup, getUncaughtExceptionHandler, holdsLock, interrupt, interrupted, isAlive, isDaemon, isInterrupted, join, join, join, resume, setContextClassLoader, setDaemon, setDefaultUncaughtExceptionHandler, setName, setPriority, setUncaughtExceptionHandler, sleep, sleep, start, stop, stop, suspend, toString, yield
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait
 

Field Detail

funcPtr

private final long funcPtr
The C function pointer that was passed to g_thread_create(). Specifically, this the numeric address of an object of C type "void *(*funcPtr)(void *funcArg)".


funcArg

private final long funcArg
The argument for the function "funcPtr(funcArg)".


threads

private static java.lang.ref.WeakReference[] threads
THREADS is an array of threads, indexed by thread ID codes. Not sure whether this is the "best" approach but it does make it O(1) to look up a thread by its ID. Zero is a valid thread ID code. Any negative number is invalid. Possible future fixes (TODO?) - The THREADS array will only grow. probably not a problem. But we could keep count when nulling entries and shrink when we have lots of nulls at the end. Probably not worth it. --mjw - Could make this a set of Object; see the comment on "joinable" below. The initial size of 17 is just a starting point. Any number will do, including zero.


joinable

private static final java.util.Set joinable
Joinable threads need a hard reference, so that they won't go away when they die. That is because their thread IDs need to stay valid until the thread is joined via thread_join(threadID). Joinable threads have to be explicitly joined before they are allowed to go away completely. Possible Alternative Implementation: Eliminate the Joinable set. When calling getThreadIDFromThread() you know whether or not the thread is joinable. So just store the Thread itself in the threads array? Make that array an Object array and check with instanceof. This looks cleaner and more robust to me and it saves a native -> Java call. But instanceof might be expensive. --mjw

Constructor Detail

GThreadNativeMethodRunner

GThreadNativeMethodRunner(long funcPtr,
                          long funcArg,
                          boolean joinable)
Method Detail

run

public void run()
Description copied from class: java.lang.Thread
The method of Thread that will be run if there is no Runnable object associated with the Thread. Thread's implementation does nothing at all.


nativeRun

private void nativeRun(long funcPtr,
                       long funcArg)

registerThread

private static int registerThread(java.lang.Thread t)
Used by threadToThreadID, below. Returns the registration number of the newly-registered thread.


threadToThreadID

static int threadToThreadID(java.lang.Thread t)
Look up the Thread ID # for a Thread. Assign a Thread ID # if none exists. This is a general routine for handling all threads, including the VM's main thread, if appropriate. Runs in O(n/2) time. We can't just issue a threadID upon thread creation. If we were to do that, not all threads would have a threadID, because not all threads are launched by GThreadNativeMethodRunner.


threadIDToThread

static java.lang.Thread threadIDToThread(int threadID)
                                  throws java.lang.IllegalArgumentException

registerSelfJoinable

private void registerSelfJoinable()
Only called from the constructor.


deRegisterJoinable

static void deRegisterJoinable(java.lang.Thread thread)
This method is only called from JNI, and only after we have succeeded in a thread_join() operation.