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 {
|
final class LinuxDisplay implements DisplayImplementation {
|
||||||
private static final int NUM_BUTTONS = 3;
|
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 int display_connection_usage_count = 0;
|
||||||
|
|
||||||
private static PeerInfo peer_info;
|
private static PeerInfo peer_info;
|
||||||
|
|
||||||
/* Since Xlib is not guaranteed to be thread safe, we need a way to synchronize LWJGL
|
/* 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.
|
* do just that.
|
||||||
*/
|
*/
|
||||||
static native void lockAWT();
|
static synchronized void lockAWT() {
|
||||||
static native void unlockAWT();
|
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.
|
* increment and decrement display usage.
|
||||||
|
|
|
@ -124,7 +124,6 @@ static int errorHandler(Display *disp, XErrorEvent *error) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Display *getDisplay(void) {
|
Display *getDisplay(void) {
|
||||||
return display_connection;
|
return display_connection;
|
||||||
}
|
}
|
||||||
|
@ -556,21 +555,21 @@ JNIEXPORT jboolean JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nIsActive
|
||||||
return focused || isLegacyFullscreen() ? JNI_TRUE : JNI_FALSE;
|
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 jawt;
|
||||||
jawt.version = JAWT_VERSION_1_4;
|
jawt.version = JAWT_VERSION_1_4;
|
||||||
if (JAWT_GetAWT(env, &jawt) != JNI_TRUE) {
|
if (JAWT_GetAWT(env, &jawt) != JNI_TRUE) {
|
||||||
throwGeneralException(env, "java/lang/RuntimeException", "GetAWT failed");
|
throwException(env, "GetAWT failed");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
jawt.Lock(env);
|
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 jawt;
|
||||||
jawt.version = JAWT_VERSION_1_4;
|
jawt.version = JAWT_VERSION_1_4;
|
||||||
if (JAWT_GetAWT(env, &jawt) != JNI_TRUE) {
|
if (JAWT_GetAWT(env, &jawt) != JNI_TRUE) {
|
||||||
throwGeneralException(env, "java/lang/RuntimeException", "GetAWT failed");
|
throwException(env, "GetAWT failed");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
jawt.Unlock(env);
|
jawt.Unlock(env);
|
||||||
|
|
Loading…
Reference in New Issue