summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoman Kennke <roman@kennke.org>2007-04-03 19:33:45 +0000
committerRoman Kennke <roman@kennke.org>2007-04-03 19:33:45 +0000
commitbfc442fc817ea30438cad6117f770aab76f662e3 (patch)
tree4993b4c16e134997fc3f55f7fce2cf9bd854c4ff
parent16d68115c6265f7091ff44f695a53ffe2b909e76 (diff)
downloadclasspath-bfc442fc817ea30438cad6117f770aab76f662e3.tar.gz
2007-04-03 Roman Kennke <roman@kennke.org>
* gnu/java/awt/peer/gtk/GThreadMutex.java, * gnu/java/awt/peer/gtk/GThreadNativeMethodRunner.java, * include/gnu_java_awt_peer_gtk_GThreadNativeMethodRunner.h, * native/jni/gtk-peer/gnu_java_awt_peer_gtk_GThreadNativeMethodRunner.c, * native/jni/gtk-peer/gthread-jni.c, * native/jni/gtk-peer/gthread-jni.h: Removed. * native/jni/gtk-peer/Makefile.am: Removed obsolete entries for removed files. * native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkToolkit.c Removed unused bits from gthread-jni.c.
-rw-r--r--ChangeLog13
-rw-r--r--gnu/java/awt/peer/gtk/GThreadMutex.java109
-rw-r--r--gnu/java/awt/peer/gtk/GThreadNativeMethodRunner.java303
-rw-r--r--include/gnu_java_awt_peer_gtk_GThreadNativeMethodRunner.h19
-rw-r--r--native/jni/gtk-peer/Makefile.am3
-rw-r--r--native/jni/gtk-peer/gnu_java_awt_peer_gtk_GThreadNativeMethodRunner.c70
-rw-r--r--native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkToolkit.c8
-rw-r--r--native/jni/gtk-peer/gthread-jni.c2592
-rw-r--r--native/jni/gtk-peer/gthread-jni.h48
9 files changed, 16 insertions, 3149 deletions
diff --git a/ChangeLog b/ChangeLog
index a2012694b..53c3644ca 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,16 @@
+2007-04-03 Roman Kennke <roman@kennke.org>
+
+ * gnu/java/awt/peer/gtk/GThreadMutex.java,
+ * gnu/java/awt/peer/gtk/GThreadNativeMethodRunner.java,
+ * include/gnu_java_awt_peer_gtk_GThreadNativeMethodRunner.h,
+ * native/jni/gtk-peer/gnu_java_awt_peer_gtk_GThreadNativeMethodRunner.c,
+ * native/jni/gtk-peer/gthread-jni.c,
+ * native/jni/gtk-peer/gthread-jni.h: Removed.
+ * native/jni/gtk-peer/Makefile.am: Removed obsolete entries
+ for removed files.
+ * native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkToolkit.c
+ Removed unused bits from gthread-jni.c.
+
2007-04-03 Francis Kung <fkung@redhat.com>
* gnu/java/awt/peer/gtk/FreetypeGlyphVector.java
diff --git a/gnu/java/awt/peer/gtk/GThreadMutex.java b/gnu/java/awt/peer/gtk/GThreadMutex.java
deleted file mode 100644
index e73df9e55..000000000
--- a/gnu/java/awt/peer/gtk/GThreadMutex.java
+++ /dev/null
@@ -1,109 +0,0 @@
-/* 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., 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;
-
-/** 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/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:
diff --git a/include/gnu_java_awt_peer_gtk_GThreadNativeMethodRunner.h b/include/gnu_java_awt_peer_gtk_GThreadNativeMethodRunner.h
deleted file mode 100644
index 1db809878..000000000
--- a/include/gnu_java_awt_peer_gtk_GThreadNativeMethodRunner.h
+++ /dev/null
@@ -1,19 +0,0 @@
-/* DO NOT EDIT THIS FILE - it is machine generated */
-
-#ifndef __gnu_java_awt_peer_gtk_GThreadNativeMethodRunner__
-#define __gnu_java_awt_peer_gtk_GThreadNativeMethodRunner__
-
-#include <jni.h>
-
-#ifdef __cplusplus
-extern "C"
-{
-#endif
-
-JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GThreadNativeMethodRunner_nativeRun (JNIEnv *env, jobject, jlong, jlong);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* __gnu_java_awt_peer_gtk_GThreadNativeMethodRunner__ */
diff --git a/native/jni/gtk-peer/Makefile.am b/native/jni/gtk-peer/Makefile.am
index b7e84144e..3084c97e4 100644
--- a/native/jni/gtk-peer/Makefile.am
+++ b/native/jni/gtk-peer/Makefile.am
@@ -6,7 +6,6 @@ libgtkpeer_la_SOURCES = gnu_java_awt_peer_gtk_CairoSurface.c \
gnu_java_awt_peer_gtk_ComponentGraphics.c \
gnu_java_awt_peer_gtk_ComponentGraphicsCopy.c \
gnu_java_awt_peer_gtk_FreetypeGlyphVector.c \
- gnu_java_awt_peer_gtk_GThreadNativeMethodRunner.c \
gnu_java_awt_peer_gtk_GdkFontPeer.c \
gnu_java_awt_peer_gtk_GdkGraphicsEnvironment.c \
gnu_java_awt_peer_gtk_GdkPixbufDecoder.c \
@@ -42,10 +41,8 @@ libgtkpeer_la_SOURCES = gnu_java_awt_peer_gtk_CairoSurface.c \
gnu_java_awt_peer_gtk_GtkVolatileImage.c \
GtkDragSourceContextPeer.c \
cairographics2d.h \
- gthread-jni.c \
gdkdisplay.h \
gdkfont.h \
- gthread-jni.h \
gtk_jawt.c \
gtkpeer.h
diff --git a/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GThreadNativeMethodRunner.c b/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GThreadNativeMethodRunner.c
deleted file mode 100644
index 595c1a28a..000000000
--- a/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GThreadNativeMethodRunner.c
+++ /dev/null
@@ -1,70 +0,0 @@
-/* Native implementation of functions in GThreadNativeMethodRunner
- 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., 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. */
-
-
-#include "gnu_java_awt_peer_gtk_GThreadNativeMethodRunner.h"
-#include "gthread-jni.h"
-
-/*
- * Class: GThreadNativeMethodRunner
- * Method: nativeRun
- * Signature: (J)V
- *
- * Purpose: Run the C function whose function pointer is
- *
- */
-JNIEXPORT void JNICALL
-Java_gnu_java_awt_peer_gtk_GThreadNativeMethodRunner_nativeRun
- (JNIEnv *env __attribute__((unused)),
- jobject lcl_obj __attribute__((unused)),
- jlong funcAddr, jlong funcArg)
-{
- /* Convert the function's address back into a pointer to a C function. */
- void *(*funcPtr)(void *) = (void *(*)(void *)) (size_t)funcAddr;
-
- /* We do not need to worry about the return value from funcPtr(); it's
- just thrown away. That is part of the g_threads spec, so no reason
- to worry about returning it. */
- (void) funcPtr((void *) (size_t)funcArg);
- /* Fall off the end and terminate the thread of control. */
-}
-
-/* Local Variables: */
-/* c-file-style: "gnu" */
-/* End: */
-
-
diff --git a/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkToolkit.c b/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkToolkit.c
index 7629a26e3..5d73af4e6 100644
--- a/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkToolkit.c
+++ b/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkToolkit.c
@@ -39,7 +39,6 @@ exception statement from your version. */
#include "gtkpeer.h"
#include "gnu_java_awt_peer_gtk_GtkToolkit.h"
-#include "gthread-jni.h"
#include "jcl.h"
#include <gdk/gdkx.h>
@@ -114,7 +113,7 @@ double cp_gtk_dpi_conversion_factor;
static void jni_lock_cb();
static void jni_unlock_cb();
-static void init_glib_threads(JNIEnv *, jint, jobject);
+static void init_glib_threads(jint, jobject);
static gboolean post_set_running_flag (gpointer);
static gboolean set_running_flag (gpointer);
static gboolean clear_running_flag (gpointer);
@@ -170,7 +169,7 @@ Java_gnu_java_awt_peer_gtk_GtkToolkit_gtkInit (JNIEnv *env,
argv[0][0] = '\0';
argv[1] = NULL;
- init_glib_threads(env, portableNativeSync, lock);
+ init_glib_threads(portableNativeSync, lock);
/* From GDK 2.0 onwards we have to explicitly call gdk_threads_init */
gdk_threads_init();
@@ -257,7 +256,7 @@ static void jni_unlock_cb()
In some release following 0.10, that config.h macro will go away.)
*/
static void
-init_glib_threads(JNIEnv *env, jint portableNativeSync, jobject lock)
+init_glib_threads(jint portableNativeSync, jobject lock)
{
if (portableNativeSync < 0)
{
@@ -269,7 +268,6 @@ init_glib_threads(JNIEnv *env, jint portableNativeSync, jobject lock)
#endif
}
- (*env)->GetJavaVM( env, &cp_gtk_the_vm );
if (!g_thread_supported ())
{
if (portableNativeSync)
diff --git a/native/jni/gtk-peer/gthread-jni.c b/native/jni/gtk-peer/gthread-jni.c
deleted file mode 100644
index 384ad0db6..000000000
--- a/native/jni/gtk-peer/gthread-jni.c
+++ /dev/null
@@ -1,2592 +0,0 @@
-/* gthread-jni.c -- JNI threading routines for GLIB
- Copyright (C) 1998, 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., 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. */
-
-/************************************************************************/
-/* Header */
-/************************************************************************/
-
-/*
- * @author Julian Dolby (dolby@us.ibm.com)
- * @date February 7, 2003 implemented for GLIB v.1
- *
- *
- * @author Steven Augart
- * <steve+classpath at augart dot com>, <augart at watson dot ibm dot com>
- * @date April 30, 2004 -- May 10 2004: Support new functions for Glib v.2,
- * fix cond_wait to free and re-acquire the mutex,
- * replaced trylock stub implementation with a full one.
- *
- * This code implements the GThreadFunctions interface for GLIB using
- * Java threading primitives. All of the locking and conditional variable
- * functionality required by GThreadFunctions is implemented using the
- * monitor and wait/notify functionality of Java objects. The thread-
- * local functionality uses the java.lang.ThreadLocal class.
- *
- * Classpath's AWT support uses GTK+ peers. GTK+ uses GLIB. GLIB by default
- * uses the platform's native threading model -- pthreads in most cases. If
- * the Java runtime doesn't use the native threading model, then it needs this
- * code in order to use Classpath's (GTK+-based) AWT routines.
- *
- * This code should be portable; I believe it makes no assumptions
- * about the underlying VM beyond that it implements the JNI functionality
- * that this code uses.
- *
- * Currently, use of this code is governed by the configuration option
- * --enable-portable-native-sync. We will soon add a VM hook so the VM can
- * select which threading model it wants to use at run time; at that point,
- * the configuration option will go away.
- *
- * The code in this file uses only JNI 1.1, except for one JNI 1.2 function:
- * GetEnv, in the JNI Invocation API. (There seems to be no way around using
- * GetEnv).
- *
- * ACKNOWLEDGEMENT:
- *
- * I would like to thank Mark Wielaard for his kindness in spending at least
- * six hours of his own time in reviewing this code and correcting my GNU
- * coding and commenting style. --Steve Augart
- *
- *
- * NOTES:
- *
- * This code has been tested with Jikes RVM and with Kaffe.
- *
- * This code should have proper automated unit tests. I manually tested it
- * by running an application that uses AWT. --Steven Augart
- *
- * MINOR NIT:
- *
- * - Using a jboolean in the arglist to "throw()" and "rethrow()"
- * triggers many warnings from GCC's -Wconversion operation, because that
- * is not the same as the conversion (upcast to an int) that would occur in
- * the absence of a prototype.
- *
- * It would be very slightly more efficient to just pass the jboolean, but
- * is not worth the clutter of messages. The right solution would be to
- * turn off the -Wconversion warning for just this file, *except* that
- * -Wconversion also warns you against constructs such as:
- * unsigned u = -1;
- * and that is a useful warning. So I went from a "jboolean" to a
- * "gboolean" (-Wconversion is not enabled by default for GNU Classpath,
- * but it is in my own CFLAGS, which, for gcc 3.3.3, read: -pipe -ggdb3 -W
- * -Wall -Wbad-function-cast -Wcast-align -Wpointer-arith -Wcast-qual
- * -Wshadow -Wstrict-prototypes -Wmissing-prototypes -Wmissing-declarations
- * -fkeep-static-consts -fkeep-inline-functions -Wundef -Wwrite-strings
- * -Wno-aggregate-return -Wmissing-noreturn -Wnested-externs -Wtrigraphs
- * -Wconversion -Wsign-compare -Wno-float-equal -Wmissing-format-attribute
- * -Wno-unreachable-code -Wdisabled-optimization )
- */
-
-#include <config.h>
-
-/************************************************************************/
-/* Configuration */
-/************************************************************************/
-
-/** Tracing and Reporting **/
-#define TRACE_API_CALLS 0 /* announce entry and exit into each method,
- by printing to stderr. */
-
-#define TRACE_MONITORS 0 /* Every enterMonitor() and exitMonitor() goes
- to stderr. */
-
-/** Trouble handling. There is a discussion below of this. **/
-#define EXPLAIN_TROUBLE 1 /* Describe any unexpected trouble that
- happens. This is a superset
- of EXPLAIN_BROKEN, and if set trumps an
- unset EXPLAIN_BROKEN. It is not a strict
- superset, since at the moment there is no
- TROUBLE that is not also BROKEN.
-
- Use criticalMsg() to describe the problem.
- */
-
-#define EXPLAIN_BROKEN 1 /* Describe trouble that is serious enough to
- be BROKEN. (Right now all trouble is at
- least BROKEN.) */
-
-/* There is no EXPLAIN_BADLY_BROKEN definition. We always explain
- BADLY_BROKEN trouble, since there is no other way to report it. */
-
-
-/** Error Handling **/
-#define DIE_IF_BROKEN 1 /* Dies if serious trouble happens. There is
- really no non-serious trouble, except
- possibly problems that arise during
- pthread_create, which are reported by a
- GError.
-
- If you do not set DIE_IF_BROKEN, then
- trouble will raise a Java RuntimeException.
- We probably do want to die right away,
- since anything that's BROKEN really
- indicates a programming error or a
- system-wide error, and that's what the glib
- documentation says you should do in case of
- that kind of error in a glib-style
- function. But it does work to turn this
- off. */
-
-#if DIE_IF_BROKEN
-#define DIE_IF_BADLY_BROKEN 1 /* DIE_IF_BROKEN implies DIE_IF_BADLY_BROKEN */
-#else
-#define DIE_IF_BADLY_BROKEN 1 /* Die if the system is badly broken --
- that is, if we have further trouble while
- attempting to throw an exception
- upwards, or if we are unable to generate
- one of the classes we'll need in order to
- throw wrapped exceptions upward.
-
- If unset, we will print a warning message,
- and limp along anyway. Not that the system
- is likely to work. */
-#endif
-
-/** Performance tuning parameters **/
-
-#define ENABLE_EXPENSIVE_ASSERTIONS 0 /* Enable expensive assertions? */
-
-#define DELETE_LOCAL_REFS 1 /* Whether to delete local references.
-
- JNI only guarantees that there wil be 16
- available. (Jikes RVM provides an number
- only limited by VM memory.)
-
- Jikes RVM will probably perform faster if
- this is turned off, but other VMs may need
- this to be turned on in order to perform at
- all, or might need it if things change.
-
- Remember, we don't know how many of those
- local refs might have already been used up
- by higher layers of JNI code that end up
- calling g_thread_self(),
- g_thread_set_private(), and so on.
-
- We set this to 1 for GNU Classpath, since
- one of our principles is "always go for the
- most robust implementation" */
-
-#define HAVE_JNI_VERSION_1_2 0 /* Assume we don't. We could
- dynamically check for this. We will
- assume JNI 1.2 in later versions of
- Classpath.
-
- As it stands, the code in this file
- already needs one JNI 1.2 function:
- GetEnv, in the JNI Invocation API.
-
- TODO This code hasn't been tested yet.
- And really hasn't been implemented yet.
- */
-
-/************************************************************************/
-/* Global data */
-/************************************************************************/
-
-#if defined HAVE_STDINT_H
-#include <stdint.h> /* provides intptr_t */
-#elif defined HAVE_INTTYPES_H
-#include <inttypes.h>
-#endif
-#include <stdarg.h> /* va_list */
-#include <glib.h>
-#include "gthread-jni.h"
-#include <assert.h> /* assert() */
-
-/* For Java thread priority constants. */
-#include <gnu_java_awt_peer_gtk_GThreadNativeMethodRunner.h>
-
-/* Since not all JNI header generators actually define constants we
- define them here explicitly. */
-#ifndef gnu_java_awt_peer_gtk_GThreadNativeMethodRunner_MIN_PRIORITY
-#define gnu_java_awt_peer_gtk_GThreadNativeMethodRunner_MIN_PRIORITY 1
-#endif
-#ifndef gnu_java_awt_peer_gtk_GThreadNativeMethodRunner_NORM_PRIORITY
-#define gnu_java_awt_peer_gtk_GThreadNativeMethodRunner_NORM_PRIORITY 5
-#endif
-#ifndef gnu_java_awt_peer_gtk_GThreadNativeMethodRunner_MAX_PRIORITY
-#define gnu_java_awt_peer_gtk_GThreadNativeMethodRunner_MAX_PRIORITY 10
-#endif
-
-/* The VM handle. This is set in
- Java_gnu_java_awt_peer_gtk_GtkMainThread_gtkInit */
-JavaVM *cp_gtk_the_vm;
-
-/* Unions used for type punning. */
-union env_union
-{
- void **void_env;
- JNIEnv **jni_env;
-};
-
-union func_union
-{
- void *void_func;
- GThreadFunc g_func;
-};
-
-/* Forward Declarations for Functions */
-static int threadObj_set_priority (JNIEnv * env, jobject threadObj,
- GThreadPriority gpriority);
-static void fatalMsg (const char fmt[], ...)
- __attribute__ ((format (printf, 1, 2)))
- __attribute__ ((noreturn));
-
-static void criticalMsg (const char fmt[], ...)
- __attribute__ ((format (printf, 1, 2)));
-
-static void tracing (const char fmt[], ...)
- __attribute__ ((format (printf, 1, 2)));
-
-static jint javaPriorityLevel (GThreadPriority priority)
- __attribute__ ((const));
-
-/************************************************************************/
-/* Trouble-handling, including utilities to reflect exceptions */
-/* back to the VM. Also some status reporting. */
-/************************************************************************/
-
-/* How are we going to handle problems?
-
- There are several approaches:
-
- 1) Report them with the GError mechanism.
-
- (*thread_create)() is the only one of these functions that takes a
- GError pointer. And the only G_THREAD error defined maps onto EAGAIN.
- We don't have any errors in our (*thread_create)() implementation that
- can be mapped to EAGAIN. So this idea is a non-starter.
-
- 2) Reflect the exception back to the VM, wrapped in a RuntimeException.
- This will fail sometimes, if we're so broken (BADLY_BROKEN) that we
- fail to throw the exception.
-
- 3) Abort execution. This is what the glib functions themselves do for
- errors that they can't report via GError.
-
- Enable DIE_IF_BROKEN and/or DIE_IF_BADLY_BROKEN to
- make this the default for BROKEN and/or BADLY_BROKEN trouble.
-
- 4) Display messages to stderr. We always do this for BADLY_BROKEN
- trouble. The glib functions do that for errors they can't report via
- GError.
-
- There are some complications.
-
- When I attempted to report a problem in g_thread_self() using g_critical (a
- macro around g_log(), I found that g_log in turn looks for thread-private
- data and calls g_thread_self() again.
-
- We got a segfault, probably due to stack overflow. So, this code doesn't
- use the g_critical() and g_error() functions any more. Nor do we use
- g_assert(); we use the C library's assert() instead.
-*/
-
-
-#define WHERE __FILE__ ":" G_STRINGIFY(__LINE__) ": "
-
-/* This is portable to older compilers that lack variable-argument macros.
- This used to be just g_critical(), but then we ran into the error reporting
- problem discussed above.
-*/
-static void
-fatalMsg (const char fmt[], ...)
-{
- va_list ap;
- va_start (ap, fmt);
- vfprintf (stderr, fmt, ap);
- va_end (ap);
- fputs ("\nAborting execution\n", stderr);
- abort ();
-}
-
-
-static void
-criticalMsg (const char fmt[], ...)
-{
- va_list ap;
- va_start (ap, fmt);
- vfprintf (stderr, fmt, ap);
- va_end (ap);
- putc ('\n', stderr);
-}
-
-/* Unlike the other two, this one does not append a newline. This is only
- used if one of the TRACE_ macros is defined. */
-static void
-tracing (const char fmt[], ...)
-{
- va_list ap;
- va_start (ap, fmt);
- vfprintf (stderr, fmt, ap);
- va_end (ap);
-}
-
-#define assert_not_reached() \
- do \
- { \
- fputs(WHERE "You should never get here. Aborting execution.\n", \
- stderr); \
- abort(); \
- } \
- while(0)
-
-
-#if DIE_IF_BADLY_BROKEN
-#define BADLY_BROKEN fatalMsg
-#else
-#define BADLY_BROKEN criticalMsg
-/* So, the user may still attempt to recover, even though we do not advise
- this. */
-#endif
-
-/* I find it so depressing to have to use C without varargs macros. */
-#define BADLY_BROKEN_MSG WHERE "Something fundamental" \
- " to GNU Classpath's AWT JNI broke while we were trying to pass up a Java error message"
-
-#define BADLY_BROKEN0() \
- BADLY_BROKEN(BADLY_BROKEN_MSG);
-#define BADLY_BROKEN1(msg) \
- BADLY_BROKEN(BADLY_BROKEN_MSG ": " msg)
-#define BADLY_BROKEN2(msg, arg) \
- BADLY_BROKEN(BADLY_BROKEN_MSG ": " msg, arg)
-#define BADLY_BROKEN3(msg, arg, arg2) \
- BADLY_BROKEN(BADLY_BROKEN_MSG ": " msg, arg1, arg2)
-#define BADLY_BROKEN4(msg, arg, arg2, arg3) \
- BADLY_BROKEN(BADLY_BROKEN_MSG ": " msg, arg1, arg2, arg3)
-
-#define DELETE_LOCAL_REF(env, ref) \
- do \
- { \
- if ( DELETE_LOCAL_REFS ) \
- { \
- (*env)->DeleteLocalRef (env, ref); \
- (ref) = NULL; \
- } \
- } \
- while(0)
-
-/* Cached info for Exception-wrapping */
-
-static jclass runtimeException_class; /* java.lang.RuntimeException */
-static jmethodID runtimeException_ctor; /* constructor for it */
-
-
-/* Throw a new RuntimeException. It may wrap around an existing exception.
- 1 if we did rethrow, -1 if we had trouble while rethrowing.
- isBroken is always true in this case. */
-static int
-throw (JNIEnv * env, jthrowable cause, const char *message,
- gboolean isBroken, const char *file, int line)
-{
- jstring jmessage;
- gboolean describedException = FALSE; /* Did we already describe the
- exception to stderr or the
- equivalent? */
- jthrowable wrapper;
-
- /* allocate local message in Java */
- const char fmt[] = "In AWT JNI, %s (at %s:%d)";
- size_t len = strlen (message) + strlen (file) + sizeof fmt + 25;
- char *buf;
-
- if (EXPLAIN_TROUBLE || (isBroken && EXPLAIN_BROKEN))
- {
- criticalMsg ("%s:%d: AWT JNI failure%s: %s\n", file, line,
- isBroken ? " (BROKEN)" : "", message);
- if (cause)
- {
- jthrowable currentException = (*env)->ExceptionOccurred (env);
-
- if (cause == currentException)
- {
- criticalMsg ("Description follows to System.err:");
- (*env)->ExceptionDescribe (env);
- /* ExceptionDescribe has the side-effect of clearing the pending
- exception; relaunch it. */
- describedException = TRUE;
-
- if ((*env)->Throw (env, cause))
- {
- BADLY_BROKEN1
- ("Relaunching an exception with Throw failed.");
- return -1;
- }
- }
- else
- {
- DELETE_LOCAL_REF (env, currentException);
- criticalMsg (WHERE
- "currentException != cause; something else happened"
- " while handling an exception.");
- }
- }
- } /* if (EXPLAIN_TROUBLE) */
-
- if (isBroken && DIE_IF_BROKEN)
- fatalMsg ("%s:%d: Aborting execution; BROKEN: %s\n", file, line, message);
-
- if ((buf = malloc (len)))
- {
- memset (buf, 0, len);
- g_snprintf (buf, len, fmt, message, file, line);
- jmessage = (*env)->NewStringUTF (env, buf);
- free (buf);
- }
- else
- {
- jmessage = NULL;
- }
-
- /* Create the RuntimeException wrapper object and throw it. It is OK for
- CAUSE to be NULL. */
- wrapper = (jthrowable) (*env)->NewObject
- (env, runtimeException_class, runtimeException_ctor, jmessage, cause);
- DELETE_LOCAL_REF (env, jmessage);
-
- if (!wrapper)
- {
- /* I think this should only happen:
- - if there are bugs in my JNI code, or
- - if the VM is broken, or
- - if we run out of memory.
- */
- if (EXPLAIN_TROUBLE)
- {
- criticalMsg (WHERE "GNU Classpath: JNI NewObject() could not create"
- " a new java.lang.RuntimeException.");
- criticalMsg ("We were trying to warn about the following"
- " previous failure:");
- criticalMsg ("%s:%d: %s", file, line, message);
- criticalMsg ("The latest (NewObject()) exception's description"
- " follows, to System.err:");
- (*env)->ExceptionDescribe (env);
- }
- BADLY_BROKEN1 ("Failure of JNI NewObject()"
- " to make a java.lang.RuntimeException");
- return -1;
- }
-
-
- /* throw it */
- if ((*env)->Throw (env, wrapper))
- {
- /* Throw() should just never fail, unless we're in such severe trouble
- that we might as well die. */
- BADLY_BROKEN1
- ("GNU Classpath: Failure of JNI Throw to report an Exception");
- return -1;
- }
-
- DELETE_LOCAL_REF (env, wrapper);
- return 1;
-}
-
-
-
-/* Rethrow an exception we received, wrapping it with a RuntimeException. 1
- if we did rethrow, -1 if we had trouble while rethrowing.
- CAUSE should be identical to the most recent exception that happened, so
- that ExceptionDescribe will work. (Otherwise nix.) */
-static int
-rethrow (JNIEnv * env, jthrowable cause, const char *message,
- gboolean isBroken, const char *file, int line)
-{
- assert (cause);
- return throw (env, cause, message, isBroken, file, line);
-}
-
-
-/* This function checks for a pending exception, and rethrows it with
- * a wrapper RuntimeException to deal with possible type problems (in
- * case some calling piece of code does not expect the exception being
- * thrown) and to include the given extra message.
- *
- * Returns 0 if no problems found (so no exception thrown), 1 if we rethrew an
- * exception. Returns -1 on failure.
- */
-static int
-maybe_rethrow (JNIEnv * env, const char *message, gboolean isBroken,
- const char *file, int line)
-{
- jthrowable cause = (*env)->ExceptionOccurred (env);
- int ret = 0;
-
- /* rethrow if an exception happened */
- if (cause)
- {
- ret = rethrow (env, cause, message, isBroken, file, line);
- DELETE_LOCAL_REF (env, cause);
- }
-
- return 0;
-}
-
-/* MAYBE_TROUBLE() is used to include a source location in the exception
- message. Once we have run maybe_rethrow, if there WAS trouble,
- return TRUE, else FALSE.
-
- MAYBE_TROUBLE() is actually never used; all problems that throw exceptions
- are BROKEN, at least. Nothing is recoverable :(. See the discussion of
- possible errors at thread_create_jni_impl(). */
-#define MAYBE_TROUBLE(_env, _message) \
- maybe_rethrow(_env, _message, FALSE, __FILE__, __LINE__)
-
-/* MAYBE_TROUBLE(), but something would be BROKEN if it were true. */
-#define MAYBE_BROKEN(_env, _message) \
- maybe_rethrow(_env, _message, TRUE, __FILE__, __LINE__)
-
-/* Like MAYBE_TROUBLE(), TROUBLE() is never used. */
-#define TROUBLE(_env, _message) \
- rethrow(_env, (*env)->ExceptionOccurred (env), _message, FALSE, \
- __FILE__, __LINE__)
-
-#define BROKEN(_env, _message) \
- rethrow (_env, (*env)->ExceptionOccurred (env), _message, TRUE, \
- __FILE__, __LINE__)
-
-/* Like MAYBE_TROUBLE(), NEW_TROUBLE() is never used. */
-#define NEW_TROUBLE(_env, _message) \
- throw (_env, NULL, _message, FALSE, __FILE__, __LINE__)
-
-#define NEW_BROKEN(_env, _message) \
- throw (_env, NULL, _message, TRUE, __FILE__, __LINE__)
-
-/* Like MAYBE_TROUBLE(), RETHROW_CAUSE() is never used. */
-#define RETHROW_CAUSE(_env, _cause, _message) \
- rethrow (_env, _cause, _message, FALSE, __FILE__, __LINE__)
-
-#define BROKEN_CAUSE(_env, _cause, _message) \
- rethrow (_env, _cause, _message, TRUE, __FILE__, __LINE__)
-
-/* Macros to handle the possibility that someone might have called one of the
- GThreadFunctions API functions with a Java exception pending. It is
- generally discouraged to continue to use JNI after a Java exception has
- been raised. Sun's JNI book advises that one trap JNI errors immediately
- and not continue with an exception pending.
-
- These are #if'd out for these reasons:
-
- 1) They do not work in the C '89 subset that Classpath is currently
- (2004 May 10) sticking to; HIDE_OLD_TROUBLE() includes a declaration
- that should be in scope for the rest of the function, so it needs a
- language version that lets you mix declarations and statements. (This
- could be worked around if it were important.)
-
- 2) They chew up more time and resources.
-
- 3) There does not ever seem to be old trouble -- the assertion in
- HIDE_OLD_TROUBLE never goes off.
-
- You will want to re-enable them if this code needs to be used in a context
- where old exceptions might be pending when the GThread functions are
- called.
-
- The implementations in this file are responsible for skipping around calls
- to SHOW_OLD_TROUBLE() if they've raised exceptions during the call. So, if
- we reach SHOW_OLD_TROUBLE, we are guaranteed that there are no exceptions
- pending. */
-#if 1
-#define HIDE_OLD_TROUBLE(env) \
- assert ( NULL == (*env)->ExceptionOccurred (env) )
-
-#define SHOW_OLD_TROUBLE() \
- assert ( NULL == (*env)->ExceptionOccurred (env) )
-#else /* 0 */
-#define HIDE_OLD_TROUBLE(env) \
- jthrowable savedTrouble = (*env)->ExceptionOccurred (env); \
- (*env)->ExceptionClear (env);
-
-#define SHOW_OLD_TROUBLE() do \
-{ \
- assert ( NULL == (*env)->ExceptionOccurred (env) ) \
- if (savedTrouble) \
- { \
- if ((*env)->Throw (env, savedTrouble)) \
- BADLY_BROKEN ("ReThrowing the savedTrouble failed"); \
- } \
- DELETE_LOCAL_REF (env, savedTrouble); \
-} while(0)
-
-#endif /* 0 */
-
-/* Set up the cache of jclass and jmethodID primitives we need
- in order to throw new exceptions and rethrow exceptions. We do this
- independently of the other caching. We need to have this cache set up
- first, so that we can then report errors properly.
-
- If any errors while setting up the error cache, the world is BADLY_BROKEN.
-
- May be called more than once.
-
- Returns -1 if the cache was not initialized properly, 1 if it was.
-*/
-static int
-setup_exception_cache (JNIEnv * env)
-{
- static int exception_cache_initialized = 0; /* -1 for trouble, 1 for proper
- init. */
-
- jclass lcl_class; /* a class used for local refs */
-
- if (exception_cache_initialized)
- return exception_cache_initialized;
- lcl_class = (*env)->FindClass (env, "java/lang/RuntimeException");
- if ( ! lcl_class )
- {
- BADLY_BROKEN1 ("Broken Class library or VM?"
- " Couldn't find java/lang/RuntimeException");
- return exception_cache_initialized = -1;
- }
- /* Pin it down. */
- runtimeException_class = (jclass) (*env)->NewGlobalRef (env, lcl_class);
- DELETE_LOCAL_REF (env, lcl_class);
- if (!runtimeException_class)
- {
- BADLY_BROKEN1 ("Serious trouble: could not turn"
- " java.lang.RuntimeException into a global reference");
- return exception_cache_initialized = -1;
- }
-
- runtimeException_ctor =
- (*env)->GetMethodID (env, runtimeException_class, "<init>",
- "(Ljava/lang/String;Ljava/lang/Throwable;)V");
- if ( ! runtimeException_ctor )
- {
- BADLY_BROKEN1 ("Serious trouble: classpath couldn't find a"
- " two-arg constructor for java/lang/RuntimeException");
- return exception_cache_initialized = -1;
- }
-
- return exception_cache_initialized = 1;
-}
-
-
-/**********************************************************/
-/***** The main cache *************************************/
-/**********************************************************/
-
-/** This is a cache of all classes, methods, and field IDs that we use during
- the run. We maintain a permanent global reference to each of the classes
- we cache, since otherwise the (local) jclass that refers to that class
- would go out of scope and possibly be reused in further calls.
-
- The permanent global reference also achieves the secondary goal of
- protecting the validity of the methods and field IDs in case the classes
- were otherwise unloaded and then later loaded again. Obviously, this will
- never happen to classes such as java.lang.Thread and java.lang.Object, but
- the primary reason for maintaining permanent global refs is sitll valid.
-
- The code in jnilink.c has a similar objective. TODO: Consider using that
- code instead.
-
- --Steven Augart
-*/
-
-/* All of these are cached classes and method IDs: */
-/* java.lang.Object */
-static jclass obj_class; /* java.lang.Object */
-static jmethodID obj_ctor; /* no-arg Constructor for java.lang.Object */
-static jmethodID obj_notify_mth; /* java.lang.Object.notify() */
-static jmethodID obj_notifyall_mth; /* java.lang.Object.notifyall() */
-static jmethodID obj_wait_mth; /* java.lang.Object.wait() */
-static jmethodID obj_wait_nanotime_mth; /* java.lang.Object.wait(JI) */
-
-/* GThreadMutex and its methods */
-static jclass mutex_class;
-static jmethodID mutex_ctor;
-static jfieldID mutex_lockForPotentialLockers_fld;
-static jfieldID mutex_potentialLockers_fld;
-
-/* java.lang.Thread and its methods*/
-static jclass thread_class; /* java.lang.Thread */
-static jmethodID thread_current_mth; /* Thread.currentThread() */
-static jmethodID thread_equals_mth; /* Thread.equals() */
-static jmethodID thread_join_mth; /* Thread.join() */
-static jmethodID thread_setPriority_mth; /* Thread.setPriority() */
-static jmethodID thread_stop_mth; /* Thread.stop() */
-static jmethodID thread_yield_mth; /* Thread.yield() */
-
-/* java.lang.ThreadLocal and its methods */
-static jclass threadlocal_class; /* java.lang.ThreadLocal */
-static jmethodID threadlocal_ctor; /* Its constructor */
-static jmethodID threadlocal_set_mth; /* ThreadLocal.set() */
-static jmethodID threadlocal_get_mth; /* ThreadLocal.get() */
-
-/* java.lang.Long and its methods */
-static jclass long_class; /* java.lang.Long */
-static jmethodID long_ctor; /* constructor for it: (J) */
-static jmethodID long_longValue_mth; /* longValue()J */
-
-
-/* GThreadNativeMethodRunner */
-static jclass runner_class;
-static jmethodID runner_ctor;
-static jmethodID runner_threadToThreadID_mth;
-static jmethodID runner_threadIDToThread_mth;
-static jmethodID runner_deRegisterJoinable_mth;
-static jmethodID runner_start_mth; /* Inherited Thread.start() */
-
-
-/* java.lang.InterruptedException */
-static jclass interrupted_exception_class;
-
-
-
-
-/* Returns a negative value if there was trouble during initialization.
- Returns a positive value of the cache was initialized correctly.
- Never returns zero. */
-static int
-setup_cache (JNIEnv * env)
-{
- jclass lcl_class;
- static int initialized = 0; /* 1 means initialized, 0 means uninitialized,
- -1 means mis-initialized */
-
- if (initialized)
- return initialized;
-
- /* make sure we can report on trouble */
- if (setup_exception_cache (env) < 0)
- return initialized = -1;
-
-#ifdef JNI_VERSION_1_2
- if (HAVE_JNI_VERSION_1_2)
- assert ( ! (*env)->ExceptionCheck (env));
- else
-#endif
- assert ( ! (*env)->ExceptionOccurred (env));
-
- /* java.lang.Object and its methods */
- lcl_class = (*env)->FindClass (env, "java/lang/Object");
- if (!lcl_class)
- {
- BROKEN (env, "cannot find java.lang.Object");
- return initialized = -1;
- }
-
- /* Pin it down. */
- obj_class = (jclass) (*env)->NewGlobalRef (env, lcl_class);
- DELETE_LOCAL_REF (env, lcl_class);
- if (!obj_class)
- {
- BROKEN (env, "Cannot get a global reference to java.lang.Object");
- return initialized = -1;
- }
-
- obj_ctor = (*env)->GetMethodID (env, obj_class, "<init>", "()V");
- if (!obj_ctor)
- {
- BROKEN (env, "cannot find constructor for java.lang.Object");
- return initialized = -1;
- }
-
- obj_notify_mth = (*env)->GetMethodID (env, obj_class, "notify", "()V");
- if ( ! obj_notify_mth )
- {
- BROKEN (env, "cannot find java.lang.Object.notify()V");
- return initialized = -1;
- }
-
- obj_notifyall_mth =
- (*env)->GetMethodID (env, obj_class, "notifyAll", "()V");
- if ( ! obj_notifyall_mth)
- {
- BROKEN (env, "cannot find java.lang.Object.notifyall()V");
- return initialized = -1;
- }
-
- obj_wait_mth = (*env)->GetMethodID (env, obj_class, "wait", "()V");
- if ( ! obj_wait_mth )
- {
- BROKEN (env, "cannot find Object.<wait()V>");
- return initialized = -1;
- }
-
- obj_wait_nanotime_mth =
- (*env)->GetMethodID (env, obj_class, "wait", "(JI)V");
- if ( ! obj_wait_nanotime_mth )
- {
- BROKEN (env, "cannot find Object.<wait(JI)V>");
- return initialized = -1;
- }
-
- /* GThreadMutex and its methods */
- lcl_class = (*env)->FindClass (env, "gnu/java/awt/peer/gtk/GThreadMutex");
- if ( ! lcl_class)
- {
- BROKEN (env, "cannot find gnu.java.awt.peer.gtk.GThreadMutex");
- return initialized = -1;
- }
- /* Pin it down. */
- mutex_class = (jclass) (*env)->NewGlobalRef (env, lcl_class);
- DELETE_LOCAL_REF (env, lcl_class);
- if ( ! mutex_class)
- {
- BROKEN (env, "Cannot get a global reference to GThreadMutex");
- return initialized = -1;
- }
-
- mutex_ctor = (*env)->GetMethodID (env, mutex_class, "<init>", "()V");
- if ( ! mutex_ctor)
- {
- BROKEN (env, "cannot find zero-arg constructor for GThreadMutex");
- return initialized = -1;
- }
-
- mutex_potentialLockers_fld = (*env)->GetFieldID
- (env, mutex_class, "potentialLockers", "I");
- if ( ! mutex_class )
- {
- BROKEN (env, "cannot find GThreadMutex.potentialLockers");
- return initialized = -1;
- }
-
- if (! (mutex_lockForPotentialLockers_fld = (*env)->GetFieldID
- (env, mutex_class, "lockForPotentialLockers", "Ljava/lang/Object;")))
- {
- BROKEN (env, "cannot find GThreadMutex.lockForPotentialLockers");
- return initialized = -1;
- }
-
-
- /* java.lang.Thread */
- if (! (lcl_class = (*env)->FindClass (env, "java/lang/Thread")))
- {
- BROKEN (env, "cannot find java.lang.Thread");
- return initialized = -1;
- }
-
- /* Pin it down. */
- thread_class = (jclass) (*env)->NewGlobalRef (env, lcl_class);
- DELETE_LOCAL_REF (env, lcl_class);
- if (!thread_class)
- {
- BROKEN (env, "Cannot get a global reference to java.lang.Thread");
- return initialized = -1;
- }
-
- thread_current_mth =
- (*env)->GetStaticMethodID (env, thread_class, "currentThread",
- "()Ljava/lang/Thread;");
- if (!thread_current_mth)
- {
- BROKEN (env, "cannot find Thread.currentThread() method");
- return initialized = -1;
- }
-
- thread_equals_mth =
- (*env)->GetMethodID (env, thread_class, "equals", "(Ljava/lang/Object;)Z");
- if (!thread_equals_mth)
- {
- BROKEN (env, "cannot find Thread.equals() method");
- return initialized = -1;
- }
-
- thread_join_mth = (*env)->GetMethodID (env, thread_class, "join", "()V");
- if (!thread_join_mth)
- {
- BROKEN (env, "cannot find Thread.join() method");
- return initialized = -1;
- }
-
- thread_stop_mth = (*env)->GetMethodID (env, thread_class, "stop", "()V");
- if ( ! thread_stop_mth )
- {
- BROKEN (env, "cannot find Thread.stop() method");
- return initialized = -1;
- }
-
- thread_setPriority_mth =
- (*env)->GetMethodID (env, thread_class, "setPriority", "(I)V");
- if ( ! thread_setPriority_mth )
- {
- BROKEN (env, "cannot find Thread.setPriority() method");
- return initialized = -1;
- }
-
- thread_yield_mth =
- (*env)->GetStaticMethodID (env, thread_class, "yield", "()V");
- if ( ! thread_yield_mth )
- {
- BROKEN (env, "cannot find Thread.yield() method");
- return initialized = -1;
- }
-
- /* java.lang.ThreadLocal */
- lcl_class = (*env)->FindClass (env, "java/lang/ThreadLocal");
- if ( ! lcl_class )
- {
- BROKEN (env, "cannot find class java.lang.ThreadLocal");
- return initialized = -1;
- }
-
- /* Pin it down. */
- threadlocal_class = (jclass) (*env)->NewGlobalRef (env, lcl_class);
- DELETE_LOCAL_REF (env, lcl_class);
- if ( ! threadlocal_class )
- {
- BROKEN (env, "Cannot get a global reference to java.lang.ThreadLocal");
- return initialized = -1;
- }
-
- threadlocal_ctor = (*env)->GetMethodID (env, threadlocal_class,
- "<init>", "()V");
- if ( ! threadlocal_ctor )
- {
- BROKEN (env, "cannot find ThreadLocal.<init>()V");
- return initialized = -1;
- }
-
- threadlocal_get_mth = (*env)->GetMethodID (env, threadlocal_class,
- "get", "()Ljava/lang/Object;");
- if ( ! threadlocal_get_mth )
- {
- BROKEN (env, "cannot find java.lang.ThreadLocal.get()Object");
- return initialized = -1;
- }
-
- threadlocal_set_mth = (*env)->GetMethodID (env, threadlocal_class,
- "set", "(Ljava/lang/Object;)V");
- if ( ! threadlocal_set_mth )
- {
- BROKEN (env, "cannot find ThreadLocal.set(Object)V");
- return initialized = -1;
- }
-
- /* java.lang.Long */
- lcl_class = (*env)->FindClass (env, "java/lang/Long");
- if ( ! lcl_class )
- {
- BROKEN (env, "cannot find class java.lang.Long");
- return initialized = -1;
- }
-
- /* Pin it down. */
- long_class = (jclass) (*env)->NewGlobalRef (env, lcl_class);
- DELETE_LOCAL_REF (env, lcl_class);
- if (!long_class)
- {
- BROKEN (env, "Cannot get a global reference to java.lang.Long");
- return initialized = -1;
- }
-
- long_ctor = (*env)->GetMethodID (env, long_class, "<init>", "(J)V");
- if (!long_ctor)
- {
- BROKEN (env, "cannot find method java.lang.Long.<init>(J)V");
- return initialized = -1;
- }
-
- long_longValue_mth =
- (*env)->GetMethodID (env, long_class, "longValue", "()J");
- if (!long_longValue_mth)
- {
- BROKEN (env, "cannot find method java.lang.Long.longValue()J");
- return initialized = -1;
- }
-
-
- /* GThreadNativeMethodRunner */
- lcl_class =
- (*env)->FindClass (env,
- "gnu/java/awt/peer/gtk/GThreadNativeMethodRunner");
- if ( ! lcl_class )
- {
- BROKEN (env,
- "cannot find gnu.java.awt.peer.gtk.GThreadNativeMethodRunner");
- return initialized = -1;
- }
-
- /* Pin it down. */
- runner_class = (jclass) (*env)->NewGlobalRef (env, lcl_class);
- DELETE_LOCAL_REF (env, lcl_class);
- if (!runner_class)
- {
- BROKEN (env,
- "Cannot get a global reference to the class GThreadNativeMethodRunner");
- return initialized = -1;
- }
-
- runner_ctor = (*env)->GetMethodID (env, runner_class, "<init>", "(JJZ)V");
- if ( ! runner_ctor )
- {
- BROKEN (env,
- "cannot find method GThreadNativeMethodRunner.<init>(JJZ)");
- return initialized = -1;
- }
-
- runner_start_mth = (*env)->GetMethodID (env, runner_class, "start", "()V");
- if ( ! runner_start_mth )
- {
- BROKEN (env, "cannot find method GThreadNativeMethodRunner.start()V");
- return initialized = -1;
- }
-
-
- runner_threadToThreadID_mth =
- (*env)->GetStaticMethodID (env, runner_class,
- "threadToThreadID", "(Ljava/lang/Thread;)I");
- if ( ! runner_threadToThreadID_mth )
- {
- BROKEN (env,
- "cannot find method GThreadNativeMethodRunner.threadToThreadID(java.lang.Thread)I");
- return initialized = -1;
- }
-
-
- runner_threadIDToThread_mth =
- (*env)->GetStaticMethodID (env, runner_class,
- "threadIDToThread", "(I)Ljava/lang/Thread;");
- if ( ! runner_threadIDToThread_mth )
- {
- BROKEN (env,
- "cannot find method GThreadNativeMethodRunner.threadIDToThread(I)java.lang.Thread");
- return initialized = -1;
- }
-
-
- runner_deRegisterJoinable_mth =
- (*env)->GetStaticMethodID (env, runner_class, "deRegisterJoinable",
- "(Ljava/lang/Thread;)V");
- if (!runner_deRegisterJoinable_mth)
- {
- BROKEN (env,
- "cannot find method GThreadNativeMethodRunner.deRegisterJoinable(java.lang.Thread)V");
- return initialized = -1;
- }
-
-
- /* java.lang.InterruptedException */
- lcl_class = (*env)->FindClass (env, "java/lang/InterruptedException");
- if ( ! lcl_class )
- {
- BROKEN (env, "cannot find class java.lang.InterruptedException");
- return initialized = -1;
- }
-
- /* Pin it down. */
- interrupted_exception_class = (jclass) (*env)->NewGlobalRef (env, lcl_class);
- DELETE_LOCAL_REF (env, lcl_class);
- if (!interrupted_exception_class)
- {
- BROKEN (env, "Cannot make a global reference"
- " to java.lang.InterruptedException");
- return initialized = -1;
- }
-
-#ifdef JNI_VERSION_1_2
- if (HAVE_JNI_VERSION_1_2)
- assert ( ! (*env)->ExceptionCheck (env));
- else
-#endif
- assert ( ! (*env)->ExceptionOccurred (env));
-
-
- return initialized = 1;
-}
-
-
-
-
-
-/************************************************************************/
-/* Utilities to allocate and free java.lang.Objects */
-/************************************************************************/
-
-/* The condition variables are java.lang.Object objects,
- * which this method allocates and returns a global ref. Note that global
- * refs must be explicitly freed (isn't C fun?).
- */
-static jobject
-allocatePlainObject (JNIEnv * env)
-{
- jobject lcl_obj, global_obj;
-
- lcl_obj = (*env)->NewObject (env, obj_class, obj_ctor);
- if (!lcl_obj)
- {
- BROKEN (env, "cannot allocate object");
- return NULL;
- }
-
- global_obj = (*env)->NewGlobalRef (env, lcl_obj);
- DELETE_LOCAL_REF (env, lcl_obj);
- if (!global_obj)
- {
- NEW_BROKEN (env, "cannot make global ref for a new plain Java object");
- /* Deliberate fall-through */
- }
-
- return global_obj;
-}
-
-/* Frees any Java object given a global ref (isn't C fun?) */
-static void
-freeObject (JNIEnv * env, jobject obj)
-{
- if (obj)
- {
- (*env)->DeleteGlobalRef (env, obj);
- /* DeleteGlobalRef can never fail */
- }
-}
-
-
-/************************************************************************/
-/* Utilities to allocate and free Java mutexes */
-/************************************************************************/
-
-/* The mutexes are gnu.java.awt.peer.gtk.GThreadMutex objects,
- * which this method allocates and returns a global ref. Note that global
- * refs must be explicitly freed (isn't C fun?).
- *
- * Free this with freeObject()
- */
-static jobject
-allocateMutexObject (JNIEnv * env)
-{
- jobject lcl_obj, global_obj;
-
- lcl_obj = (*env)->NewObject (env, mutex_class, mutex_ctor);
- if (!lcl_obj)
- {
- BROKEN (env, "cannot allocate a GThreadMutex");
- return NULL;
- }
-
- global_obj = (*env)->NewGlobalRef (env, lcl_obj);
- DELETE_LOCAL_REF (env, lcl_obj);
- if (!global_obj)
- {
- NEW_BROKEN (env, "cannot make global ref");
- /* Deliberate fallthrough */
- }
-
- return global_obj;
-}
-
-
-/************************************************************************/
-/* Locking code */
-/************************************************************************/
-
-/* Lock a Java object */
-#define ENTER_MONITOR(env, m) \
- enterMonitor(env, m, G_STRINGIFY(m))
-
-/* Return -1 on failure, 0 on success. */
-static int
-enterMonitor (JNIEnv * env, jobject monitorObj, const char monName[])
-{
- if (TRACE_MONITORS)
- tracing (" <MonitorEnter(%s)>", monName);
- assert (monitorObj);
- if ((*env)->MonitorEnter (env, monitorObj) < 0)
- {
- BROKEN (env, "cannot enter monitor");
- return -1;
- }
- return 0;
-}
-
-
-/* Unlock a Java object */
-#define EXIT_MONITOR(env, m) \
- exitMonitor(env, m, G_STRINGIFY(m))
-
-static int
-exitMonitor (JNIEnv * env, jobject mutexObj, const char monName[])
-{
- if (TRACE_MONITORS)
- tracing (" <MonitorExit(%s)>", monName);
- assert (mutexObj);
- if ((*env)->MonitorExit (env, mutexObj) < 0)
- {
- BROKEN (env, "cannot exit monitor ");
- return -1;
- }
- return 0;
-}
-
-
-/************************************************************************/
-/* Miscellaneous utilities */
-/************************************************************************/
-
-/* Get the Java Thread object that corresponds to a particular thread ID.
- A negative thread Id gives us a null object.
-
- Returns a local reference.
-*/
-static jobject
-getThreadFromThreadID (JNIEnv * env, gpointer gThreadID)
-{
- jint threadNum = GPOINTER_TO_INT(gThreadID);
- jobject thread;
-
- if (threadNum < 0)
- {
- NEW_BROKEN (env, "getThreadFromThreadID asked to look up"
- " a negative thread index");
- return NULL;
- }
-
- thread = (*env)->CallStaticObjectMethod
- (env, runner_class, runner_threadIDToThread_mth, threadNum);
-
- if (MAYBE_BROKEN (env, "cannot get Thread for threadID "))
- return NULL;
-
- return thread;
-}
-
-/** Return the unique threadID of THREAD.
-
- Error handling: Return (gpointer) -1 on all failures,
- and propagate an exception.
-*/
-static gpointer
-getThreadIDFromThread (JNIEnv * env, jobject thread)
-{
- jint threadNum;
-
- if (ENABLE_EXPENSIVE_ASSERTIONS)
- assert ((*env)->IsInstanceOf (env, thread, thread_class));
-
- HIDE_OLD_TROUBLE (env);
-
- threadNum = (*env)->CallStaticIntMethod
- (env, runner_class, runner_threadToThreadID_mth, thread);
-
- if (MAYBE_BROKEN (env, "cannot get ThreadID for a Thread "))
- {
- threadNum = -1;
- goto done;
- }
-
-
- SHOW_OLD_TROUBLE ();
-
-done:
- return GINT_TO_POINTER(threadNum);
-}
-
-
-/************************************************************************/
-/* The Actual JNI functions that we pass to the function vector. */
-/************************************************************************/
-
-
-/************************************************************************/
-/* Mutex Functions */
-/************************************************************************/
-
-/*** Mutex Utilities ****/
-struct mutexObj_cache
-{
- jobject lockForPotentialLockersObj; /* Lock for the potentialLockers
- field. Local reference. */
- jobject lockObj; /* The real lock we use. This is a GLOBAL
- reference and must not be freed. */
-};
-
-/* Initialize the cache of sub-locks for a particular mutex object.
-
- -1 on error, 0 on success. The caller is not responsible for freeing the
- partially-populated cache in case of failure (but in practice does anyway)
- (This actually never fails, though, since GetObjectField allegedly never
- fails.)
-
- Guaranteed to leave all fields of the cache initialized, even if only to
- zero.
-*/
-static int
-populate_mutexObj_cache (JNIEnv * env, jobject mutexObj,
- struct mutexObj_cache *mcache)
-{
- mcache->lockObj = mutexObj; /* the mutexObj is its own lock. */
- assert (mcache->lockObj);
-
- mcache->lockForPotentialLockersObj = (*env)->GetObjectField
- (env, mutexObj, mutex_lockForPotentialLockers_fld);
- /* GetObjectField can never fail. */
-
- /* Retrieving a NULL object could only happen if we somehow got a
- a mutex object that was not properly intialized. */
- assert (mcache->lockForPotentialLockersObj);
-
- return 0;
-}
-
-
-/* Clean out the mutexObj_cache, even if it was never populated. */
-static void
-clean_mutexObj_cache (JNIEnv * env, struct mutexObj_cache *mcache)
-{
- /* OK to pass NULL refs to DELETE_LOCAL_REF */
- DELETE_LOCAL_REF (env, mcache->lockForPotentialLockersObj);
- /* mcache->lockObj is a GLOBAL reference. */
- mcache->lockObj = NULL;
-}
-
-/* -1 on failure, 0 on success.
- The mutexObj_cache is already populated for this particular object. */
-static int
-mutexObj_lock (JNIEnv * env, jobject mutexObj, struct mutexObj_cache *mcache)
-{
- jint potentialLockers;
-
- if (ENTER_MONITOR (env, mcache->lockForPotentialLockersObj))
- return -1;
-
- assert(mutexObj);
- potentialLockers =
- (*env)->GetIntField (env, mutexObj, mutex_potentialLockers_fld);
- /* GetIntField() never fails. */
-
- ++potentialLockers;
-
- (*env)->SetIntField
- (env, mutexObj, mutex_potentialLockers_fld, potentialLockers);
-
- if (EXIT_MONITOR (env, mcache->lockForPotentialLockersObj))
- return -1;
-
- if (ENTER_MONITOR (env, mcache->lockObj))
- return -1;
-
- SHOW_OLD_TROUBLE ();
-
- return 0;
-}
-
-/* Unlock a GMutex, once we're already in JNI and have already gotten the
- mutexObj for it. This skips the messages that TRACE_API_CALLS would
- print.
-
- Returns -1 on error, 0 on success. */
-static int
-mutexObj_unlock (JNIEnv * env, jobject mutexObj,
- struct mutexObj_cache *mcache)
-{
- jint potentialLockers;
- int ret = -1; /* assume failure until we suceed. */
-
- /* Free the lock first, so that someone waiting for the lock can get it
- ASAP. */
- /* This is guaranteed not to block. */
- if (EXIT_MONITOR (env, mcache->lockObj) < 0)
- goto done;
-
- /* Kick down potentialLockers by one. We do this AFTER we free the lock, so
- that we hold it no longer than necessary. */
- if (ENTER_MONITOR (env, mcache->lockForPotentialLockersObj) < 0)
- goto done;
-
- potentialLockers = (*env)->GetIntField
- (env, mutexObj, mutex_potentialLockers_fld);
- /* GetIntField never fails */
-
- assert (potentialLockers >= 1);
- --potentialLockers;
-
- (*env)->SetIntField
- (env, mutexObj, mutex_potentialLockers_fld, potentialLockers);
- /* Never fails, so the JNI book says. */
-
- /* Clean up. */
- if (EXIT_MONITOR (env, mcache->lockForPotentialLockersObj) < 0)
- goto done;
- ret = 0;
-
-done:
- return ret;
-}
-
-/*** Mutex Implementations ****/
-
-/* Create a mutex, which is a java.lang.Object for us.
- In case of failure, we'll return NULL. Which will implicitly
- cause future calls to fail. */
-static GMutex *
-mutex_new_jni_impl (void)
-{
- jobject mutexObj;
- JNIEnv *env;
- union env_union e;
-
- if (TRACE_API_CALLS)
- tracing ("mutex_new_jni_impl()");
-
- e.jni_env = &env;
- (*cp_gtk_the_vm)->GetEnv (cp_gtk_the_vm, e.void_env, JNI_VERSION_1_1);
-
- if (setup_cache (env) < 0)
- {
- mutexObj = NULL;
- goto done;
- }
-
- mutexObj = allocateMutexObject (env);
-
-done:
- if (TRACE_API_CALLS)
- tracing (" ==> %p \n", mutexObj);
-
- return (GMutex *) mutexObj;
-
-}
-
-/* Lock a mutex. */
-static void
-mutex_lock_jni_impl (GMutex * mutex)
-{
- struct mutexObj_cache mcache;
- jobject mutexObj = (jobject) mutex;
- JNIEnv *env;
- union env_union e;
-
- if (TRACE_API_CALLS)
- tracing ("mutex_lock_jni_impl( mutexObj = %p )", mutexObj);
-
- assert (mutexObj);
- e.jni_env = &env;
- (*cp_gtk_the_vm)->GetEnv (cp_gtk_the_vm, e.void_env, JNI_VERSION_1_1);
-
- if (setup_cache (env) < 0)
- goto done;
-
- HIDE_OLD_TROUBLE (env);
-
- if (populate_mutexObj_cache (env, mutexObj, &mcache) < 0)
- goto done;
-
- mutexObj_lock (env, mutexObj, &mcache);
- /* No need to error check; we've already reported it in any case. */
-
-done:
- clean_mutexObj_cache (env, &mcache);
- if (TRACE_API_CALLS)
- tracing (" ==> VOID \n");
-}
-
-
-/* Try to lock a mutex. Return TRUE if we succeed, FALSE if we fail.
- FALSE on error. */
-static gboolean
-mutex_trylock_jni_impl (GMutex * gmutex)
-{
- jobject mutexObj = (jobject) gmutex;
- jint potentialLockers;
- gboolean ret = FALSE;
- JNIEnv *env;
- union env_union e;
- struct mutexObj_cache mcache;
-
- if (TRACE_API_CALLS)
- tracing ("mutex_trylock_jni_impl(mutexObj=%p)", mutexObj);
-
- assert (mutexObj);
-
- e.jni_env = &env;
- (*cp_gtk_the_vm)->GetEnv (cp_gtk_the_vm, e.void_env, JNI_VERSION_1_1);
- if (setup_cache (env) < 0)
- goto done;
- HIDE_OLD_TROUBLE (env);
-
- if (populate_mutexObj_cache (env, mutexObj, &mcache) < 0)
- goto done;
-
- if (ENTER_MONITOR (env, mcache.lockForPotentialLockersObj))
- goto done;
-
- potentialLockers = (*env)->GetIntField
- (env, mutexObj, mutex_potentialLockers_fld);
-
- assert (potentialLockers >= 0);
-
- if (potentialLockers)
- {
- /* Already locked. Clean up and leave. */
- EXIT_MONITOR (env, mcache.lockForPotentialLockersObj);
- /* Ignore any error code from EXIT_MONITOR; there's nothing we could do
- at this level, in any case. */
- goto done;
- }
-
- /* Guaranteed not to block. */
- if (ENTER_MONITOR (env, mcache.lockObj))
- {
- /* Clean up the existing lock. */
- EXIT_MONITOR (env, mcache.lockForPotentialLockersObj);
- /* Ignore any error code from EXIT_MONITOR; there's nothing we could do
- at this level, in any case. */
- goto done;
- }
-
-
- /* We have the monitor. Record that fact. */
- potentialLockers = 1;
- (*env)->SetIntField
- (env, mutexObj, mutex_potentialLockers_fld, potentialLockers);
- /* Set*Field() never fails */
-
- ret = TRUE; /* We have the lock. */
-
- /* Clean up. */
- if (EXIT_MONITOR (env, mcache.lockForPotentialLockersObj))
- goto done; /* If we fail at this point, still keep the
- main lock. */
-
- SHOW_OLD_TROUBLE ();
-done:
- clean_mutexObj_cache (env, &mcache);
- if (TRACE_API_CALLS)
- tracing (" ==> %s\n", ret ? "TRUE" : "FALSE");
- return ret;
-}
-
-
-/* Unlock a mutex. */
-static void
-mutex_unlock_jni_impl (GMutex * gmutex)
-{
- jobject mutexObj = (jobject) gmutex;
- struct mutexObj_cache mcache;
- JNIEnv *env;
- union env_union e;
-
- if (TRACE_API_CALLS)
- tracing ("mutex_unlock_jni_impl(mutexObj=%p)", mutexObj);
-
- e.jni_env = &env;
- (*cp_gtk_the_vm)->GetEnv (cp_gtk_the_vm, e.void_env, JNI_VERSION_1_1);
- if (setup_cache (env) < 0)
- goto done;
- HIDE_OLD_TROUBLE (env);
-
- assert (mutexObj);
-
- if ( populate_mutexObj_cache (env, mutexObj, &mcache) < 0)
- goto done;
-
- (void) mutexObj_unlock (env, mutexObj, &mcache);
-
- SHOW_OLD_TROUBLE ();
-
-done:
- clean_mutexObj_cache (env, &mcache);
- if (TRACE_API_CALLS)
- tracing (" ==> VOID\n");
-}
-
-
-
-/* Free a mutex (isn't C fun?). OK this time for it to be NULL.
- No failure conditions, for a change. */
-static void
-mutex_free_jni_impl (GMutex * mutex)
-{
- jobject mutexObj = (jobject) mutex;
- JNIEnv *env;
- union env_union e;
-
- e.jni_env = &env;
- (*cp_gtk_the_vm)->GetEnv (cp_gtk_the_vm, e.void_env, JNI_VERSION_1_1);
-
- if (TRACE_API_CALLS)
- tracing ("mutex_free_jni_impl(%p)", mutexObj);
-
- freeObject (env, mutexObj);
-
- if (TRACE_API_CALLS)
- tracing (" ==> VOID\n");
-}
-
-
-
-
-/************************************************************************/
-/* Condition variable code */
-/************************************************************************/
-
-/* Create a new condition variable. This is a java.lang.Object for us. */
-static GCond *
-cond_new_jni_impl (void)
-{
- jobject condObj;
- JNIEnv *env;
- union env_union e;
-
- if (TRACE_API_CALLS)
- tracing ("mutex_free_jni_impl()");
-
- e.jni_env = &env;
- (*cp_gtk_the_vm)->GetEnv (cp_gtk_the_vm, e.void_env, JNI_VERSION_1_1);
-
- condObj = allocatePlainObject (env);
-
- if (TRACE_API_CALLS)
- tracing (" ==> %p\n", condObj);
-
- return (GCond *) condObj;
-}
-
-/* Signal on a condition variable. This is simply calling Object.notify
- * for us.
- */
-static void
-cond_signal_jni_impl (GCond * gcond)
-{
- JNIEnv *env;
- union env_union e;
- jobject condObj = (jobject) gcond;
-
- if (TRACE_API_CALLS)
- tracing ("cond_signal_jni_impl(condObj = %p)", condObj);
-
- e.jni_env = &env;
- (*cp_gtk_the_vm)->GetEnv (cp_gtk_the_vm, e.void_env, JNI_VERSION_1_1);
- if (setup_cache (env) < 0)
- goto done;
- HIDE_OLD_TROUBLE (env);
-
- assert (condObj);
-
- /* Must have locked an object to call notify */
- if (ENTER_MONITOR (env, condObj))
- goto done;
-
- (*env)->CallVoidMethod (env, condObj, obj_notify_mth);
- if (MAYBE_BROKEN (env, "cannot signal mutex with Object.notify()"))
- {
- if (EXIT_MONITOR (env, condObj))
- BADLY_BROKEN1 ("Failed to unlock a monitor; the VM may deadlock.");
- goto done;
- }
-
- EXIT_MONITOR (env, condObj);
-
- SHOW_OLD_TROUBLE ();
-
-done:
- if (TRACE_API_CALLS)
- tracing (" ==> VOID\n");
-}
-
-/* Broadcast to all waiting on a condition variable. This is simply
- * calling Object.notifyAll for us.
- */
-static void
-cond_broadcast_jni_impl (GCond * gcond)
-{
- jobject condObj = (jobject) gcond;
- JNIEnv *env;
- union env_union e;
-
- if (TRACE_API_CALLS)
- tracing ("cond_broadcast_jni_impl(condObj=%p)", condObj);
-
- e.jni_env = &env;
- (*cp_gtk_the_vm)->GetEnv (cp_gtk_the_vm, e.void_env, JNI_VERSION_1_1);
- if (setup_cache (env) < 0)
- goto done;
- HIDE_OLD_TROUBLE (env);
-
- assert (condObj);
- /* Must have locked an object to call notifyAll */
- if (ENTER_MONITOR (env, condObj))
- goto done;
-
- (*env)->CallVoidMethod (env, condObj, obj_notifyall_mth);
- if (MAYBE_BROKEN (env, "cannot broadcast to mutex with Object.notify()"))
- {
- EXIT_MONITOR (env, condObj);
- goto done;
- }
-
- EXIT_MONITOR (env, condObj);
-
- SHOW_OLD_TROUBLE ();
-
-done:
- if (TRACE_API_CALLS)
- tracing (" ==> VOID\n");
-}
-
-
-/* Wait on a condition variable. For us, this simply means calling
- * Object.wait.
- *
- * Throws a Java exception on trouble; may leave the mutexes set arbitrarily.
- * XXX TODO: Further improve error recovery.
- */
-static void
-cond_wait_jni_impl (GCond * gcond, GMutex * gmutex)
-{
- struct mutexObj_cache cache;
- jobject condObj = (jobject) gcond;
- jobject mutexObj = (jobject) gmutex;
- JNIEnv *env;
- union env_union e;
-
- if (TRACE_API_CALLS)
- tracing ("cond_wait_jni_impl(condObj=%p, mutexObj=%p)",
- condObj, mutexObj);
-
- e.jni_env = &env;
- (*cp_gtk_the_vm)->GetEnv (cp_gtk_the_vm, e.void_env, JNI_VERSION_1_1);
- if (setup_cache (env) < 0)
- goto done;
- HIDE_OLD_TROUBLE (env);
-
- assert (condObj);
- assert (mutexObj);
- /* Must have locked a Java object to call wait on it */
- if (ENTER_MONITOR (env, condObj) < 0)
- goto done;
-
- /* Our atomicity is now guaranteed; we're protected by the Java monitor on
- condObj. Unlock the GMutex. */
- if (mutexObj_unlock (env, mutexObj, &cache))
- goto done;
-
- (*env)->CallVoidMethod (env, condObj, obj_wait_mth);
- if (MAYBE_BROKEN (env, "cannot wait on condObj"))
- {
- EXIT_MONITOR (env, condObj); /* ignore err checking */
- goto done;
- }
-
- /* Re-acquire the lock on the GMutex. Do this while we're protected by the
- Java monitor on condObj. */
- if (mutexObj_lock (env, mutexObj, &cache))
- goto done;
-
- EXIT_MONITOR (env, condObj);
-
- SHOW_OLD_TROUBLE ();
-
-done:
- if (TRACE_API_CALLS)
- tracing (" ==> VOID\n");
-}
-
-
-/** Wait on a condition variable until a timeout. This is a little tricky
- * for us. We first call Object.wait(J) giving it the appropriate timeout
- * value. On return, we check whether an InterruptedException happened. If
- * so, that is Java-speak for wait timing out.
- *
- * We return FALSE if we timed out. Return TRUE if the condition was
- * signalled first, before we timed out.
- *
- * In case of trouble we throw a Java exception. Whether we return FALSE or
- * TRUE depends upon whether the condition was raised before the trouble
- * happened.
- *
- * I believe that this function goes to the proper lengths to try to unlock
- * all of the locked mutexes and monitors, as appropriate, and that it further
- * tries to make sure that the thrown exception is the current one, not any
- * future cascaded one from something like a failure to unlock the monitors.
- */
-static gboolean
-cond_timed_wait_jni_impl (GCond * gcond, GMutex * gmutex, GTimeVal * end_time)
-{
- JNIEnv *env;
- union env_union e;
- jlong time_millisec;
- jint time_nanosec;
- jthrowable cause;
- jobject condObj = (jobject) gcond;
- jobject mutexObj = (jobject) gmutex;
- gboolean condRaised = FALSE; /* Condition has not been raised yet. */
- struct mutexObj_cache cache;
- gboolean interrupted;
-
- if (TRACE_API_CALLS)
- {
- tracing ("cond_timed_wait_jni_impl(cond=%p, mutex=%p,"
- " end_time=< sec=%lu, usec=%lu >)", condObj, mutexObj,
- (unsigned long) end_time->tv_sec,
- (unsigned long) end_time->tv_usec);
- }
-
-
- e.jni_env = &env;
- (*cp_gtk_the_vm)->GetEnv (cp_gtk_the_vm, e.void_env, JNI_VERSION_1_1);
- if (setup_cache (env) < 0)
- goto done;
- HIDE_OLD_TROUBLE (env);
-
- time_millisec = end_time->tv_sec * 1000 + end_time->tv_usec / 1000;
- time_nanosec = 1000 * (end_time->tv_usec % 1000);
-
- /* Must have locked an object to call wait */
- if (ENTER_MONITOR (env, condObj) < 0)
- goto done;
-
- if (mutexObj_unlock (env, mutexObj, &cache) < 0)
- {
- if (EXIT_MONITOR (env, condObj) < 0)
- criticalMsg
- ("Unable to unlock an existing lock on a condition; your proram may deadlock");
- goto done;
- }
-
-
- (*env)->CallVoidMethod (env, condObj, obj_wait_nanotime_mth,
- time_millisec, time_nanosec);
-
- /* If there was trouble, save that fact, and the reason for the trouble. We
- want to respond to this condition as fast as possible. */
- cause = (*env)->ExceptionOccurred (env);
-
- if ( ! cause )
- {
- condRaised = TRUE; /* condition was signalled */
- }
- else if ((*env)->IsInstanceOf (env, cause, interrupted_exception_class))
- {
- condRaised = FALSE; /* Condition was not raised before timeout.
- (This is redundant with the initialization
- of condRaised above) */
- (*env)->ExceptionClear (env); /* Clear the InterruptedException. */
- cause = NULL; /* no pending cause now. */
- }
- else
- {
- interrupted = FALSE; /* Trouble, but not because of
- InterruptedException. Assume the condition
- was not raised. */
- /* Leave condRaised set to FALSE */
- }
-
- /* Irrespective of whether there is a pending problem to report, go ahead
- and try to clean up. This may end up throwing an exception that is
- different from the one that was thrown by the call to Object.wait().
- So we will override it with the first exception (don't want to have
- cascading problems). */
- if (mutexObj_lock (env, mutexObj, &cache) && !cause)
- {
- cause = (*env)->ExceptionOccurred (env);
- assert (cause);
- }
-
- if (EXIT_MONITOR (env, condObj) && !cause)
- {
- cause = (*env)->ExceptionOccurred (env);
- assert (cause);
- }
-
- if (cause) /* Raise the first cause. */
- {
- BROKEN_CAUSE (env, cause, "error in timed wait or during its cleanup");
- goto done;
- }
-
- SHOW_OLD_TROUBLE ();
-
-done:
- if (TRACE_API_CALLS)
- tracing (" ==> condRaised = %s\n", condRaised ? "TRUE" : "FALSE");
- return condRaised;
-}
-
-
-/* Free a condition variable. (isn't C fun?). Can not fail. */
-static void
-cond_free_jni_impl (GCond * cond)
-{
- jobject condObj = (jobject) cond;
- JNIEnv *env;
- union env_union e;
-
- if (TRACE_API_CALLS)
- tracing ("cond_free_jni_impl(condObj = %p)", condObj);
- e.jni_env = &env;
- (*cp_gtk_the_vm)->GetEnv (cp_gtk_the_vm, e.void_env, JNI_VERSION_1_1);
-
- freeObject (env, condObj);
-
- if (TRACE_API_CALLS)
- tracing (" ==> VOID\n");
-}
-
-
-/************************************************************************/
-/* Thread-local data code */
-/************************************************************************/
-
-/* Create a new thread-local key. We use java.lang.ThreadLocal objects
- * for this. This returns the pointer representation of a Java global
- * reference.
- *
- * We will throw a Java exception and return NULL in case of failure.
- */
-static GPrivate *
-private_new_jni_impl (GDestroyNotify notify __attribute__ ((unused)))
-{
- JNIEnv *env;
- union env_union e;
- jobject lcl_key;
- jobject global_key;
- GPrivate *gkey = NULL; /* Error return code */
-
- if (TRACE_API_CALLS)
- tracing ("private_new_jni_impl()");
-
- e.jni_env = &env;
- (*cp_gtk_the_vm)->GetEnv (cp_gtk_the_vm, e.void_env, JNI_VERSION_1_1);
- if (setup_cache (env) < 0)
- goto done;
- HIDE_OLD_TROUBLE (env);
-
- lcl_key = (*env)->NewObject (env, threadlocal_class, threadlocal_ctor);
- if ( ! lcl_key )
- {
- BROKEN (env, "cannot allocate a ThreadLocal");
- goto done;
- }
-
- global_key = ((*env)->NewGlobalRef (env, lcl_key));
- DELETE_LOCAL_REF (env, lcl_key);
- if ( ! global_key)
- {
- NEW_BROKEN (env, "cannot create a GlobalRef to a new ThreadLocal");
- goto done;
- }
-
- gkey = (GPrivate *) global_key;
- SHOW_OLD_TROUBLE ();
-
-done:
- if (TRACE_API_CALLS)
- tracing (" ==> %p\n", (void *) gkey);
-
- return gkey;
-}
-
-/* Get this thread's value for a thread-local key. This is simply
- * ThreadLocal.get for us. Return NULL if no value. (I can't think of
- * anything else to do.)
- */
-static gpointer
-private_get_jni_impl (GPrivate * gkey)
-{
- JNIEnv *env;
- union env_union e;
- jobject val_wrapper;
- jobject keyObj = (jobject) gkey;
- gpointer thread_specific_data = NULL; /* Init to the error-return value */
-
- jlong val;
-
- if (TRACE_API_CALLS)
- tracing ("private_get_jni_impl(keyObj=%p)", keyObj);
-
- e.jni_env = &env;
- (*cp_gtk_the_vm)->GetEnv (cp_gtk_the_vm, e.void_env, JNI_VERSION_1_1);
- if (setup_cache (env) < 0)
- goto done;
- HIDE_OLD_TROUBLE (env);
-
- val_wrapper = (*env)->CallObjectMethod (env, keyObj, threadlocal_get_mth);
- if (MAYBE_BROKEN (env, "cannot find thread-local object"))
- goto done;
-
- if (! val_wrapper )
- {
- /* It's Java's "null" object. No ref found. This is OK; we must never
- have set a value in this thread. Note that this next statement is
- not necessary, strictly speaking, since we're already initialized to
- NULL. A good optimizing C compiler will detect that and optimize out
- this statement. */
- thread_specific_data = NULL;
- goto done;
- }
-
- val = (*env)->CallLongMethod (env, val_wrapper, long_longValue_mth);
-
- if (MAYBE_BROKEN (env, "cannot get thread local value"))
- goto done;
-
- thread_specific_data = (gpointer) (intptr_t) val;
-
- /* Only re-raise the old pending exception if a new one hasn't come along to
- supersede it. */
- SHOW_OLD_TROUBLE ();
-
-done:
-
- if (TRACE_API_CALLS)
- tracing (" ==> %p\n", thread_specific_data);
-
- return thread_specific_data;
-}
-
-/* Set this thread's value for a thread-local key. This is simply
- * ThreadLocal.set() for us.
- */
-static void
-private_set_jni_impl (GPrivate * gkey, gpointer thread_specific_data)
-{
- JNIEnv *env;
- union env_union e;
- jobject val_wrapper;
- jobject keyObj = (jobject) gkey;
-
-
- if (TRACE_API_CALLS)
- tracing ("private_set_jni_impl(keyObj=%p, thread_specific_data=%p)",
- keyObj, thread_specific_data);
-
- e.jni_env = &env;
- (*cp_gtk_the_vm)->GetEnv (cp_gtk_the_vm, e.void_env, JNI_VERSION_1_1);
- if (setup_cache (env) < 0)
- goto done;
- HIDE_OLD_TROUBLE (env);
-
- /* We are just going to always use a Java long to represent a C pointer.
- Otherwise all of the code would end up being conditionalized for various
- pointer sizes, and that seems like too much of a hassle, in order to save
- a paltry few bytes, especially given the horrendous overhead of JNI in
- any case.
- */
-
- val_wrapper = (*env)->NewObject (env, long_class, long_ctor,
- (jlong) (intptr_t) thread_specific_data);
- if ( ! val_wrapper )
- {
- BROKEN (env, "cannot create a java.lang.Long");
- goto done;
- }
-
- /* At this point, we now have set lcl_obj as a numeric class that wraps
- around the thread-specific data we were given. */
- (*env)->CallVoidMethod (env, keyObj, threadlocal_set_mth, val_wrapper);
- if (MAYBE_BROKEN (env, "cannot set thread local value"))
- goto done;
-
- SHOW_OLD_TROUBLE ();
-done:
- if (TRACE_API_CALLS)
- tracing (" ==> VOID\n");
-}
-
-
-/** Create an object of type gnu.java.awt.peer.gtk.GThreadNativeMethodRunner.
- Run it.
-
- We need to create joinable threads. We handle the notion of a joinable
- thread by determining whether or not we are going to maintain a permanent
- hard reference to it until it croaks.
-
- Posix does not appear to have a Java-like concept of daemon threads, where
- the JVM will exit when there are only daemon threads running.
-
- Error handling:
-
- To quote from the glib guide:
- "GError should only be used to report recoverable runtime errors, never
- to report programming errors."
-
- So how do we consider the failure to create a thread? Well, each of the
- failure cases in this function are discussed, and none of them are really
- recoverable.
-
- The glib library is really designed so that you should fail
- catastrophically in case of "programming errors". The only error defined
- for the GThread functions is G_THREAD_ERROR_AGAIN, and that for
- thread_create.
-
- Most of these GThread functions could fail if we run out of memory, for
- example, but the only one capable of reporting that fact is
- thread_create. */
-static void
-thread_create_jni_impl (GThreadFunc func,
- gpointer data,
- gulong stack_size __attribute__((unused)),
- gboolean joinable,
- gboolean bound __attribute__((unused)),
- GThreadPriority gpriority,
- /* This prototype is horrible. threadIDp is actually
- a gpointer to the thread's thread-ID. Which is,
- of course, itself a gpointer-typed value. Ouch. */
- gpointer threadIDp,
- /* Do not touch the GError stuff unless you have
- RECOVERABLE trouble. There is no recoverable
- trouble in this implementation. */
- GError **errorp __attribute__((unused)))
-{
- JNIEnv *env;
- union env_union e;
- union func_union f;
- jboolean jjoinable = joinable;
- jobject newThreadObj;
- gpointer threadID; /* to be filled in */
-
- if (TRACE_API_CALLS)
- {
- f.g_func = func;
- tracing ("thread_create_jni_impl(func=%p, data=%p, joinable=%s,"
- " threadIDp=%p, *(int *) threadIDp = %d)",
- f.void_func, data, joinable ? "TRUE" : "FALSE",
- threadIDp, *(int *) threadIDp);
- }
-
- e.jni_env = &env;
- (*cp_gtk_the_vm)->GetEnv (cp_gtk_the_vm, e.void_env, JNI_VERSION_1_1);
- if (setup_cache (env) < 0)
- {
- /* The failed call to setup the cache is certainly not recoverable;
- not appropriate for G_THREAD_ERROR_AGAIN. */
- *(gpointer *) threadIDp = NULL;
- goto done;
- }
- HIDE_OLD_TROUBLE (env);
-
- /* If a thread is joinable, then notify its constructor. The constructor
- will enter a hard reference for it, and the hard ref. won't go away until
- the thread has been joined. */
- newThreadObj =
- (*env)->NewObject (env, runner_class, runner_ctor,
- (jlong) (intptr_t) func, (jlong) (intptr_t) data,
- jjoinable);
- if ( ! newThreadObj )
- {
- BROKEN (env, "creating a new thread failed in the constructor");
- *(gpointer *) threadIDp = NULL;
- /* The failed call to the constructor does not throw any errors such
- that G_THREAD_ERROR_AGAIN is appropriate. No other recoverable
- errors defined. Once again, we go back to the VM. */
- goto done;
- }
-
- if (threadObj_set_priority (env, newThreadObj, gpriority) < 0)
- {
- *(gpointer *) threadIDp = NULL;
- /* None of these possible exceptions from Thread.setPriority() are
- recoverable, so they are not appropriate for EAGAIN. So we should
- fail. */
- goto done;
- }
-
- (*env)->CallVoidMethod (env, runner_class, runner_start_mth);
-
- if (MAYBE_BROKEN (env, "starting a new thread failed"))
- {
- *(gpointer *) threadIDp = NULL;
- /* The only exception Thread.start() throws is
- IllegalStateException. And that would indicate a programming error.
-
- So there are no situations such that G_THREAD_ERROR_AGAIN would be
- OK.
-
- So, we don't use g_set_error() here to perform any error reporting.
- */
- goto done;
- }
-
- threadID = getThreadIDFromThread (env, newThreadObj);
-
- *(gpointer *) threadIDp = threadID;
- SHOW_OLD_TROUBLE ();
-
-done:
- if (TRACE_API_CALLS)
- tracing (" ==> (threadID = %p) \n", threadID);
-}
-
-
-/* Wraps a call to g_thread_yield. */
-static void
-thread_yield_jni_impl (void)
-{
- JNIEnv *env;
- union env_union e;
-
- if (TRACE_API_CALLS)
- tracing ("thread_yield_jni_impl()");
-
- e.jni_env = &env;
- (*cp_gtk_the_vm)->GetEnv (cp_gtk_the_vm, e.void_env, JNI_VERSION_1_1);
- if (setup_cache (env) < 0)
- goto done;
- HIDE_OLD_TROUBLE (env);
-
- (*env)->CallStaticVoidMethod (env, thread_class, thread_yield_mth);
- if (MAYBE_BROKEN (env, "Thread.yield() failed"))
- goto done;
-
- SHOW_OLD_TROUBLE ();
-
-done:
- if (TRACE_API_CALLS)
- tracing (" ==> VOID\n");
-}
-
-
-static void
-thread_join_jni_impl (gpointer threadID)
-{
- JNIEnv *env;
- union env_union e;
- jobject threadObj = NULL;
-
- if ( TRACE_API_CALLS )
- tracing ("thread_join_jni_impl(threadID=%p) ", threadID);
-
- e.jni_env = &env;
- (*cp_gtk_the_vm)->GetEnv (cp_gtk_the_vm, e.void_env, JNI_VERSION_1_1);
- if (setup_cache (env) < 0)
- goto done;
- HIDE_OLD_TROUBLE (env);
-
- threadObj = getThreadFromThreadID (env, threadID);
- if ( ! threadObj ) /* Already reported with BROKEN */
- goto done;
-
- (*env)->CallVoidMethod (env, threadObj, thread_join_mth);
- if (MAYBE_BROKEN (env, "Thread.join() failed"))
- goto done;
-
-
- (*env)->CallStaticVoidMethod
- (env, runner_class, runner_deRegisterJoinable_mth, threadObj);
- if (MAYBE_BROKEN (env, "Thread.deRegisterJoinableThread() failed"))
- goto done;
-
- SHOW_OLD_TROUBLE ();
-
-done:
- DELETE_LOCAL_REF (env, threadObj);
- if (TRACE_API_CALLS)
- tracing (" ==> VOID \n");
-}
-
-/* Terminate the current thread. Unlike pthread_exit(), here we do not need
- to bother with a return value or exit value for the thread which is about
- to croak. (The gthreads abstraction doesn't use it.) However, we *do*
- need to bail immediately. We handle this with Thread.stop(), which is
- a deprecated method.
-
- It's deprecated since we might leave objects protected by monitors in
- half-constructed states on the way out -- Thread.stop() throws a
- ThreadDeath exception, which is usually unchecked. There is no good
- solution that I can see. */
-static void
-thread_exit_jni_impl (void)
-{
- JNIEnv *env;
- union env_union e;
- jobject this_thread;
-
- if (TRACE_API_CALLS)
- tracing ("thread_exit_jni_impl() ");
-
- e.jni_env = &env;
- (*cp_gtk_the_vm)->GetEnv (cp_gtk_the_vm, e.void_env, JNI_VERSION_1_1);
- if (setup_cache (env) < 0)
- goto done;
-
- HIDE_OLD_TROUBLE (env);
-
- this_thread = (*env)->
- CallStaticObjectMethod (env, thread_class, thread_current_mth);
-
- if ( ! this_thread )
- {
- BROKEN (env, "cannot get current thread");
- goto done;
- }
-
- (*env)->CallVoidMethod (env, this_thread, thread_stop_mth);
- if (MAYBE_BROKEN (env, "cannot call Thread.stop() on current thread"))
- goto done;
-
- SHOW_OLD_TROUBLE ();
-
-done:
- if (TRACE_API_CALLS)
- tracing (" ==> VOID \n");
-}
-
-
-/* Translate a GThreadPriority to a Java priority level. */
-static jint
-javaPriorityLevel (GThreadPriority priority)
-{
- /* We have these fields in java.lang.Thread to play with:
-
- static int MIN_PRIORITY The minimum priority that a thread can have.
- static int NORM_PRIORITY The default priority that is assigned to a
- thread.
- static int MAX_PRIORITY The maximum priority that a thread can have.
-
- We get these from the header file generated by javah, even though they're
- documented as being 1, 5, and 10.
- */
- static const jint minJPri =
- gnu_java_awt_peer_gtk_GThreadNativeMethodRunner_MIN_PRIORITY;
- static const jint normJPri =
- gnu_java_awt_peer_gtk_GThreadNativeMethodRunner_NORM_PRIORITY;
- static const jint maxJPri =
- gnu_java_awt_peer_gtk_GThreadNativeMethodRunner_MAX_PRIORITY;
-
- switch (priority)
- {
- case G_THREAD_PRIORITY_LOW:
- return minJPri;
- break;
-
- default:
- assert_not_reached ();
- /* Deliberate fall-through if assertions are turned off; also shuts up
- GCC warnings if they're turned on. */
- case G_THREAD_PRIORITY_NORMAL:
- return normJPri;
- break;
-
- case G_THREAD_PRIORITY_HIGH:
- return (normJPri + maxJPri) / 2;
- break;
-
- case G_THREAD_PRIORITY_URGENT:
- return maxJPri;
- break;
- }
-}
-
-
-/** It would be safe not to implement this, according to the JNI docs, since
- not all platforms do thread priorities. However, we might as well
- provide the hint for those who want it.
-*/
-static void
-thread_set_priority_jni_impl (gpointer gThreadID, GThreadPriority gpriority)
-{
- jobject threadObj = NULL;
- JNIEnv *env;
- union env_union e;
-
- if (TRACE_API_CALLS)
- tracing ("thread_set_priority_jni_impl(gThreadID=%p, gpriority = %u) ",
- gThreadID, gpriority);
-
- e.jni_env = &env;
- (*cp_gtk_the_vm)->GetEnv (cp_gtk_the_vm, e.void_env, JNI_VERSION_1_1);
-
- if (setup_cache (env) < 0)
- goto done;
-
- HIDE_OLD_TROUBLE (env);
-
-
- threadObj = getThreadFromThreadID (env, gThreadID);
- if ( ! threadObj) /* Reported with BROKEN already. */
- goto done;
-
- if (threadObj_set_priority (env, threadObj, gpriority))
- goto done;
-
- SHOW_OLD_TROUBLE ();
-
-done:
- DELETE_LOCAL_REF (env, threadObj);
-
- if (TRACE_API_CALLS)
- tracing (" ==> VOID\n");
-}
-
-
-/** It would be safe not to implement this, according to the JNI docs, since
- not all platforms do thread priorities. However, we might as well
- provide the hint for those who want it.
-
- -1 on failure, 0 on success. */
-static int
-threadObj_set_priority (JNIEnv * env, jobject threadObj,
- GThreadPriority gpriority)
-{
- jint javaPriority = javaPriorityLevel (gpriority);
- (*env)->CallVoidMethod (env, threadObj, thread_setPriority_mth,
- javaPriority);
- return MAYBE_BROKEN (env, "Thread.setPriority() failed");
-}
-
-
-/** Return the result of Thread.currentThread(), a static method. */
-static void
-thread_self_jni_impl (/* Another confusing glib prototype. This is
- actually a gpointer to the thread's thread-ID.
- Which is, of course, a gpointer. */
- gpointer my_thread_IDp)
-{
- JNIEnv *env;
- union env_union e;
- jobject this_thread;
- gpointer my_threadID;
-
- if (TRACE_API_CALLS)
- tracing ("thread_self_jni_impl(my_thread_IDp=%p)", my_thread_IDp);
-
- e.jni_env = &env;
- (*cp_gtk_the_vm)->GetEnv (cp_gtk_the_vm, e.void_env, JNI_VERSION_1_1);
-
- if (setup_cache (env) < 0)
- return;
-
- HIDE_OLD_TROUBLE (env);
-
- this_thread = (*env)->
- CallStaticObjectMethod (env, thread_class, thread_current_mth);
- if (! this_thread )
- {
- BROKEN (env, "cannot get current thread");
- my_threadID = NULL;
- goto done;
- }
-
- my_threadID = getThreadIDFromThread (env, this_thread);
- SHOW_OLD_TROUBLE ();
-
-done:
- if (TRACE_API_CALLS)
- tracing (" ==> (my_threadID = %p) \n", my_threadID);
-
- *(gpointer *) my_thread_IDp = my_threadID;
-}
-
-
-static gboolean
-thread_equal_jni_impl (gpointer thread1, gpointer thread2)
-{
- JNIEnv *env;
- union env_union e;
-
- gpointer threadID1 = *(gpointer *) thread1;
- gpointer threadID2 = *(gpointer *) thread2;
-
- jobject thread1_obj = NULL;
- jobject thread2_obj = NULL;
- gboolean ret;
-
- if (TRACE_API_CALLS)
- tracing ("thread_equal_jni_impl(threadID1=%p, threadID2=%p)",
- threadID1, threadID2);
-
- e.jni_env = &env;
- (*cp_gtk_the_vm)->GetEnv (cp_gtk_the_vm, e.void_env, JNI_VERSION_1_1);
- if (setup_cache (env) < 0)
- {
- ret = FALSE; /* what is safer? We really don't ever want
- to return from here. */
- goto done;
- }
-
- HIDE_OLD_TROUBLE (env);
- thread1_obj = getThreadFromThreadID (env, threadID1);
- thread2_obj = getThreadFromThreadID (env, threadID2);
-
- ret = (*env)->CallBooleanMethod (env, thread1_obj,
- thread_equals_mth, thread2_obj);
-
- if (MAYBE_BROKEN (env, "Thread.equals() failed"))
- {
- ret = FALSE;
- goto done;
- }
-
- SHOW_OLD_TROUBLE ();
-
-
-done:
- DELETE_LOCAL_REF (env, thread1_obj);
- DELETE_LOCAL_REF (env, thread2_obj);
-
- if (TRACE_API_CALLS)
- tracing (" ==> %s\n", ret ? "TRUE" : "FALSE");
-
- return ret;
-}
-
-
-
-
-/************************************************************************/
-/* GLIB interface */
-/************************************************************************/
-
-/* set of function pointers to give to glib. */
-GThreadFunctions cp_gtk_portable_native_sync_jni_functions = {
- mutex_new_jni_impl, /* mutex_new */
- mutex_lock_jni_impl, /* mutex_lock */
- mutex_trylock_jni_impl, /* mutex_trylock */
- mutex_unlock_jni_impl, /* mutex_unlock */
- mutex_free_jni_impl, /* mutex_free */
- cond_new_jni_impl, /* cond_new */
- cond_signal_jni_impl, /* cond_signal */
- cond_broadcast_jni_impl, /* cond_broadcast */
- cond_wait_jni_impl, /* cond_wait */
- cond_timed_wait_jni_impl, /* cond_timed_wait */
- cond_free_jni_impl, /* cond_free */
- private_new_jni_impl, /* private_new */
- private_get_jni_impl, /* private_get */
- private_set_jni_impl, /* private_set */
- thread_create_jni_impl, /* thread_create */
- thread_yield_jni_impl, /* thread_yield */
- thread_join_jni_impl, /* thread_join */
- thread_exit_jni_impl, /* thread_exit */
- thread_set_priority_jni_impl, /* thread_set_priority */
- thread_self_jni_impl, /* thread_self */
- thread_equal_jni_impl, /* thread_equal */
-};
-
-
-/* Keep c-font-lock-extra-types in alphabetical order. */
-/* Local Variables: */
-/* c-file-style: "gnu" */
-/* c-font-lock-extra-types: ("\\sw+_t" "gboolean" "GError" "gpointer"
- "GPrivate" "GThreadFunc" "GThreadFunctions" "GThreadPriority"
- "gulong"
- "JNIEnv"
- "jboolean" "jclass" "jfieldID" "jint" "jlong" "jmethodID" "jobject" "jstring" "jthrowable" ) */
-/* End: */
diff --git a/native/jni/gtk-peer/gthread-jni.h b/native/jni/gtk-peer/gthread-jni.h
deleted file mode 100644
index 3d052dc10..000000000
--- a/native/jni/gtk-peer/gthread-jni.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/* gthread-jni.h
- Copyright (C) 1998, 2002 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. */
-
-#ifndef __GTHREADJNI_H__
-#define __GTHREADJNI_H__
-
-#include <jni.h>
-#include <glib.h>
-#include "gtkpeer.h"
-
-extern GThreadFunctions cp_gtk_portable_native_sync_jni_functions;
-extern JavaVM *cp_gtk_the_vm;
-
-#endif /* __GTHREADJNI_H__ */