Linux: Don't assume JAWT Lock()/Unlock() are re-entrant, fixing a hang with GCJ 4
This commit is contained in:
parent
1bb8bc04d7
commit
56a56503d6
|
@ -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.
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue