summaryrefslogtreecommitdiff
path: root/gnu/java/awt/peer/gtk/GThreadNativeMethodRunner.java
diff options
context:
space:
mode:
Diffstat (limited to 'gnu/java/awt/peer/gtk/GThreadNativeMethodRunner.java')
-rw-r--r--gnu/java/awt/peer/gtk/GThreadNativeMethodRunner.java303
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: