diff options
Diffstat (limited to 'gnu/java/awt/peer/gtk/GThreadNativeMethodRunner.java')
-rw-r--r-- | gnu/java/awt/peer/gtk/GThreadNativeMethodRunner.java | 303 |
1 files changed, 0 insertions, 303 deletions
diff --git a/gnu/java/awt/peer/gtk/GThreadNativeMethodRunner.java b/gnu/java/awt/peer/gtk/GThreadNativeMethodRunner.java deleted file mode 100644 index 9a1b8e3a3..000000000 --- a/gnu/java/awt/peer/gtk/GThreadNativeMethodRunner.java +++ /dev/null @@ -1,303 +0,0 @@ -/* GThreadNativeMethodRunner.java -- Implements pthread_create(), under - glib's gthread abstraction, for use with GNU Classpath's - --portable-native-sync option. - This is used by gthread-jni.c - - Copyright (C) 2004, 2005 Free Software Foundation, Inc. - -This file is part of GNU Classpath. - -GNU Classpath is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. - -GNU Classpath is distributed in the hope that it will be useful, but -WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GNU Classpath; see the file COPYING. If not, write to the -Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -02110-1301 USA. - -Linking this library statically or dynamically with other modules is -making a combined work based on this library. Thus, the terms and -conditions of the GNU General Public License cover the whole -combination. - -As a special exception, the copyright holders of this library give you -permission to link this library with independent modules to produce an -executable, regardless of the license terms of these independent -modules, and to copy and distribute the resulting executable under -terms of your choice, provided that you also meet, for each linked -independent module, the terms and conditions of the license of that -module. An independent module is a module which is not derived from -or based on this library. If you modify this library, you may extend -this exception to your version of the library, but you are not -obligated to do so. If you do not wish to do so, delete this -exception statement from your version. */ - -package gnu.java.awt.peer.gtk; - -import java.lang.ref.WeakReference; -import java.util.Collections; -import java.util.HashSet; -import java.util.Set; - -/** 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. -*/ - -class GThreadNativeMethodRunner - extends Thread -{ - /** 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)". - */ - private final long funcPtr; - - /** The argument for the function "funcPtr(funcArg)". */ - private final long funcArg; - - GThreadNativeMethodRunner(long funcPtr, long funcArg, boolean joinable) - { - this.funcPtr = funcPtr; - this.funcArg = funcArg; - - if (joinable) - registerSelfJoinable(); - } - - public void run() - { - nativeRun(funcPtr, funcArg); - } - - private native void nativeRun(long funcPtr, long funcArg); - - /** 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. - */ - private static WeakReference[] threads = new WeakReference[17]; - - /** Used by threadToThreadID, below. Returns the registration number of - the newly-registered thread. - */ - private static synchronized int registerThread(Thread t) - { - int i; - - for (i = 0; i < threads.length; ++i) - { - WeakReference ref = threads[i]; - if (ref == null) - break; // found an empty spot. - } - - if (i == threads.length) - { - /* expand the array */ - WeakReference[] bigger = new WeakReference[threads.length * 2]; - System.arraycopy(threads, 0, bigger, 0, threads.length); - threads = bigger; - } - - threads[i] = new WeakReference(t); - - return i; - } - - /** 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. - */ - static synchronized int threadToThreadID(Thread t) - { - for (int i = 0; i < threads.length; ++i ) - { - if (threads[i] == null) - continue; - Thread referent = (Thread) threads[i].get(); - if (referent == null) - { - threads[i] = null; // Purge the dead WeakReference. - continue; - } - if (referent.equals(t)) - return i; - } // for() - - /* No match found. */ - return registerThread(t); - } - - /** @param threadID Must be a non-negative integer. - - Used to return null if the thread number was out of range or if - the thread was unregistered. Now we throw an exception. - - Possible Alternative Interface: We could go back to returning null in - some sort of check-free mode, so code that calls this function must - be prepared to get null. - */ - static Thread threadIDToThread(int threadID) - throws IllegalArgumentException - { - if (threadID < 0) - throw new IllegalArgumentException("Received a negative threadID, " - + threadID); - if (threadID >= threads.length) - throw new IllegalArgumentException("Received a threadID (" + threadID - + ") higher than was" - + " ever issued"); - - /* Note: if the user is using a stale reference, things will just - break. We might end up getting a different thread than the one - expected. - - TODO: Add an error-checking mode where the user's problems with threads - are announced. For instance, if the user asks for the thread - associated with a threadID that was never issued, we could print a - warning or even abort. - - TODO: Consider optionally disabling all of the error-checking we - already have; it probably slows down the implementation. We could - just return NULL. This is just the reverse of the above TODO item. - */ - - WeakReference threadRef = threads[threadID]; - - if (threadRef == null) - throw new IllegalArgumentException("Asked to look up a stale or unissued" - + "threadID (" + threadID + ")" ); - - - Thread referent = (Thread) threadRef.get(); - if (referent == null) - throw new IllegalArgumentException ("Asked to look up a stale threadID (" - + threadID + ")"); - return referent; - } - - /** 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 - */ - private static final Set joinable = - Collections.synchronizedSet(new HashSet()); - - /** Only called from the constructor. */ - private void registerSelfJoinable() - { - joinable.add(this); - } - - /** This method is only called from JNI, and only after we have succeeded in - a thread_join() operation. */ - static void deRegisterJoinable(Thread thread) - { - joinable.remove(thread); - } -} - -// Local Variables: -// c-file-style: "gnu" -// End: |