Linux: Don't assume JAWT Lock()/Unlock() are re-entrant, fixing a hang with GCJ 4

This commit is contained in:
Elias Naur 2005-10-23 19:41:09 +00:00
parent 1bb8bc04d7
commit 56a56503d6
2 changed files with 52 additions and 8 deletions

View File

@ -49,16 +49,61 @@ import org.lwjgl.input.Keyboard;
final class LinuxDisplay implements DisplayImplementation {
private static final int NUM_BUTTONS = 3;
/** Keep track on the current awt lock owner to avoid
* depending on JAWT locking to be re-entrant (This is a
* problem with GCJ). JAWT locking is not that well specified
* anyway so it is probably best to avoid assuming too much
* about it.
*/
private static Thread current_awt_lock_owner;
private static int awt_lock_count;
private static int display_connection_usage_count = 0;
private static PeerInfo peer_info;
/* Since Xlib is not guaranteed to be thread safe, we need a way to synchronize LWJGL
* Xlib calls with AWT Xlib calls. Fortunately, JAWT implements LockAWT and UnlockAWT() to
* Xlib calls with AWT Xlib calls. Fortunately, JAWT implements Lock()/Unlock() to
* do just that.
*/
static native void lockAWT();
static native void unlockAWT();
static synchronized void lockAWT() {
Thread this_thread = Thread.currentThread();
while (current_awt_lock_owner != null && current_awt_lock_owner != this_thread) {
try {
LinuxDisplay.class.wait();
} catch (InterruptedException e) {
LWJGLUtil.log("Interrupted while waiting for awt lock: " + e);
}
}
if (awt_lock_count == 0) {
current_awt_lock_owner = this_thread;
try {
nLockAWT();
} catch (LWJGLException e) {
LWJGLUtil.log("Caught exception while locking AWT: " + e);
}
}
awt_lock_count++;
}
private static native void nLockAWT() throws LWJGLException;
static synchronized void unlockAWT() {
if (awt_lock_count <= 0)
throw new IllegalStateException("AWT not locked!");
if (Thread.currentThread() != current_awt_lock_owner)
throw new IllegalStateException("AWT already locked by " + current_awt_lock_owner);
awt_lock_count--;
if (awt_lock_count == 0) {
try {
nUnlockAWT();
} catch (LWJGLException e) {
LWJGLUtil.log("Caught exception while unlocking AWT: " + e);
}
current_awt_lock_owner = null;
LinuxDisplay.class.notify();
}
}
private static native void nUnlockAWT() throws LWJGLException;
/**
* increment and decrement display usage.

View File

@ -124,7 +124,6 @@ static int errorHandler(Display *disp, XErrorEvent *error) {
return 0;
}
Display *getDisplay(void) {
return display_connection;
}
@ -556,21 +555,21 @@ JNIEXPORT jboolean JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nIsActive
return focused || isLegacyFullscreen() ? JNI_TRUE : JNI_FALSE;
}
JNIEXPORT void JNICALL Java_org_lwjgl_opengl_LinuxDisplay_lockAWT(JNIEnv *env, jclass clazz) {
JNIEXPORT void JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nLockAWT(JNIEnv *env, jclass clazz) {
JAWT jawt;
jawt.version = JAWT_VERSION_1_4;
if (JAWT_GetAWT(env, &jawt) != JNI_TRUE) {
throwGeneralException(env, "java/lang/RuntimeException", "GetAWT failed");
throwException(env, "GetAWT failed");
return;
}
jawt.Lock(env);
}
JNIEXPORT void JNICALL Java_org_lwjgl_opengl_LinuxDisplay_unlockAWT(JNIEnv *env, jclass clazz) {
JNIEXPORT void JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nUnlockAWT(JNIEnv *env, jclass clazz) {
JAWT jawt;
jawt.version = JAWT_VERSION_1_4;
if (JAWT_GetAWT(env, &jawt) != JNI_TRUE) {
throwGeneralException(env, "java/lang/RuntimeException", "GetAWT failed");
throwException(env, "GetAWT failed");
return;
}
jawt.Unlock(env);