aboutsummaryrefslogtreecommitdiff
path: root/libjava/gnu
diff options
context:
space:
mode:
authorGraydon Hoare <graydon@gcc.gnu.org>2004-09-02 06:58:08 +0000
committerGraydon Hoare <graydon@gcc.gnu.org>2004-09-02 06:58:08 +0000
commit61341707b3db764c90f954097bf89b0811f92965 (patch)
tree57dc5b899889b3288ee8c497478f985857cfcd2e /libjava/gnu
parent9969aaf67e4c806bc58a5b110f6a0849365eee05 (diff)
downloadgcc-61341707b3db764c90f954097bf89b0811f92965.zip
gcc-61341707b3db764c90f954097bf89b0811f92965.tar.gz
gcc-61341707b3db764c90f954097bf89b0811f92965.tar.bz2
missing added files from merge
From-SVN: r86958
Diffstat (limited to 'libjava/gnu')
-rw-r--r--libjava/gnu/java/awt/peer/gtk/GThreadMutex.java109
-rw-r--r--libjava/gnu/java/awt/peer/gtk/GThreadNativeMethodRunner.java302
2 files changed, 411 insertions, 0 deletions
diff --git a/libjava/gnu/java/awt/peer/gtk/GThreadMutex.java b/libjava/gnu/java/awt/peer/gtk/GThreadMutex.java
new file mode 100644
index 0000000..111c9a8
--- /dev/null
+++ b/libjava/gnu/java/awt/peer/gtk/GThreadMutex.java
@@ -0,0 +1,109 @@
+/* GThreadMutex.java -- Implements a mutex object for glib's gthread
+ abstraction, for use with GNU Classpath's --portable-native-sync option.
+ This is used in gthread-jni.c
+
+ Copyright (C) 2004 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., 59 Temple Place, Suite 330, Boston, MA
+02111-1307 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;
+
+/** Implements a mutex object for glib's gthread
+ abstraction, for use with GNU Classpath's --portable-native-sync option.
+ This is used in gthread-jni.c.
+
+ We use this object to implement the POSIX semantics for Mutexes. They are
+ needed are needed for the function vector that is passed to glib's
+ g_thread subpackage's initialization function.
+
+ The GThreadMutex object itself serves as the Real Lock; if code has
+ entered the monitor for this GThreadMutex object (in Java language, if
+ it's synchronized on this object) then it holds the lock that this object
+ represents.
+
+ @author Steven Augart
+ May, 2004
+
+
+*/
+
+class GThreadMutex
+{
+ /** Might "lock" be locked? Is anyone waiting
+ to get that lock? How long is the queue?
+
+ If zero, nobody holds a lock on this GThreadMutex object, and nobody is
+ trying to get one. Before someone attempts to acquire a lock on this
+ object, they must increment potentialLockers. After they release their
+ lock on this object, they must decrement potentialLockers.
+
+ Access to this field is guarded by synchronizing on the object
+ <code>lockForPotentialLockers</code>.
+
+ After construction, we only access this field via JNI.
+ */
+ volatile int potentialLockers;
+
+ /** An object to synchronize to if you want to examine or modify the
+ <code>potentialLockers</code> field. Only hold this lock for brief
+ moments, just long enough to check or set the value of
+ <code>lockForPotentialLockers</code>.
+
+ We use this representation so that g_thread_mutex_trylock() will work
+ with the POSIX semantics. This is the only case in which you ever hold a
+ lock on <code>lockForPotentialLockers</code> while trying to get another
+ lock -- if you are the mutex_trylock() implementation, and you have just
+ checked that <code>potentialLockers</code> has the value zero. In that
+ case, mutex_trylock() holds the lock on lockForPotentialLockers so that
+ another thread calling mutex_trylock() or mutex_lock() won't increment
+ potentialLockers after we've checked it and before we've gained the lock
+ on the POSIX mutex. Of course, in that case the operation of gaining
+ the POSIX lock itself will succeed immediately, and once it has
+ succeeded, trylock releases lockForPotentialLockers right away,
+ incremented to 1 (one).
+
+ After construction, we only access this field via JNI.
+ */
+ Object lockForPotentialLockers;
+
+ GThreadMutex()
+ {
+ potentialLockers = 0;
+ lockForPotentialLockers = new Object();
+ }
+}
+// Local Variables:
+// c-file-style: "gnu"
+// End:
diff --git a/libjava/gnu/java/awt/peer/gtk/GThreadNativeMethodRunner.java b/libjava/gnu/java/awt/peer/gtk/GThreadNativeMethodRunner.java
new file mode 100644
index 0000000..a4cb35a
--- /dev/null
+++ b/libjava/gnu/java/awt/peer/gtk/GThreadNativeMethodRunner.java
@@ -0,0 +1,302 @@
+/* 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 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., 59 Temple Place, Suite 330, Boston, MA
+02111-1307 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.Set;
+import java.util.Collections;
+import java.util.HashSet;
+
+/** 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: