aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSven Gothel <[email protected]>2010-10-08 01:56:46 +0200
committerSven Gothel <[email protected]>2010-10-08 01:56:46 +0200
commitb9adfc2c67d2bc46cae887ed39a5953b1e74e96a (patch)
treea11a1815fc25496245ebc1c13a6277a9996b8330
parent7c2916a999ece43ada42a1964bab3d6b886f3984 (diff)
Fix: JOGL GLContextLock starvation; Tighten NEWT/AWT focus unit tests
Fix: JOGL GLContextLock starvation - Apply changes made in RecursiveToolkitLock (c8a9c59e4838cd43090378a7ed60544449472801), ie notifyAll() -> notify(), plus sync (flow/mem) usage. Fix: Tighten NEWT/AWT focus unit tests - AWTRobotUtil.requestFocusAndWait() waits for EventCountAdapter gain and lost focus as well. - In case of NewtCanvasAWT, additionally wait for it's lost focus
-rwxr-xr-xmake/scripts/java-run-all.sh4
-rwxr-xr-xmake/scripts/java-win32-dbg.bat12
-rw-r--r--make/scripts/tests.bat4
-rw-r--r--src/jogl/classes/com/jogamp/opengl/impl/GLContextLock.java75
-rw-r--r--src/junit/com/jogamp/test/junit/newt/TestFocus01SwingAWTRobot.java7
-rw-r--r--src/junit/com/jogamp/test/junit/newt/TestFocus02SwingAWTRobot.java16
-rw-r--r--src/junit/com/jogamp/test/junit/util/AWTRobotUtil.java46
7 files changed, 118 insertions, 46 deletions
diff --git a/make/scripts/java-run-all.sh b/make/scripts/java-run-all.sh
index 6bb053a16..bd8b16faf 100755
--- a/make/scripts/java-run-all.sh
+++ b/make/scripts/java-run-all.sh
@@ -45,9 +45,9 @@ uname -a | grep -i Darwin && MOSX=1
# D_ARGS="-Djogl.debug=all -Dnewt.debug=all -Dnativewindow.debug=all"
# D_ARGS="-Dnewt.debug=all"
# D_ARGS="-Dnewt.debug.Window -Dnewt.debug.Display -Dnewt.debug.EDT"
-# D_ARGS="-Dnewt.debug.EDT -Dnewt.debug.Window"
+D_ARGS="-Dnewt.debug.EDT -Dnewt.debug.Window"
# D_ARGS="-Dsun.awt.disableMixing=true -Dnewt.debug.EDT"
-D_ARGS="-Dnewt.debug.EDT"
+# D_ARGS="-Dnewt.debug.EDT"
# D_ARGS="-Dnativewindow.debug.TraceLock"
# D_ARGS="-Dnewt.debug.Display"
# D_ARGS="-Djogl.debug.Animator -Dnewt.debug.Window -Dnewt.debug.Display"
diff --git a/make/scripts/java-win32-dbg.bat b/make/scripts/java-win32-dbg.bat
index 1021e2457..b0474c824 100755
--- a/make/scripts/java-win32-dbg.bat
+++ b/make/scripts/java-win32-dbg.bat
@@ -13,4 +13,14 @@ set CP_ALL=.;%BLD_DIR%\jogl\jogl.all.jar;%BLD_DIR%\nativewindow\nativewindow.all
echo CP_ALL %CP_ALL%
-%J2RE_HOME%\bin\java -classpath %CP_ALL% "-Djava.library.path=%LIB_DIR%" "-Dnativewindow.debug=all" "-Djogl.debug=all" "-Dnewt.debug=all" "-Dsun.java2d.noddraw=true" "-Dsun.awt.noerasebackground=true" %1 %2 %3 %4 %5 %6 %7 %8 %9 > java-win32-dbg.log 2>&1
+REM set D_ARGS="-Djogamp.debug.JNILibLoader=true" "-Djogamp.debug.NativeLibrary=true" "-Djogamp.debug.NativeLibrary.Lookup=true" "-Djogl.debug.GLProfile=true"
+REM set D_ARGS="-Djogl.debug=all" "-Dnewt.debug=all" "-Dnativewindow.debug=all"
+REM set D_ARGS="-Dnewt.debug.Window" "-Dnativewindow.debug.TraceLock"
+REM set D_ARGS="-Dnativewindow.debug.TraceLock"
+set D_ARGS="-Dnewt.debug.Window" "-Dnewt.debug.Display"
+REM set D_ARGS="-Dnewt.debug.Window" "-Dnewt.debug.Display" "-Dnewt.test.Window.reparent.incompatible=true"
+
+set X_ARGS="-Dsun.java2d.noddraw=true" "-Dsun.awt.noerasebackground=true"
+
+%J2RE_HOME%\bin\java -classpath %CP_ALL% "-Djava.library.path=%LIB_DIR%" %D_ARGS% %X_ARGS% %1 %2 %3 %4 %5 %6 %7 %8 %9 > java-win32-dbg.log 2>&1
+
diff --git a/make/scripts/tests.bat b/make/scripts/tests.bat
index f9bc7a5c8..453633ec0 100644
--- a/make/scripts/tests.bat
+++ b/make/scripts/tests.bat
@@ -12,6 +12,8 @@ REM # ./scripts/java-run-all.sh ../build-x86_64 com.jogamp.test.junit.newt.paren
REM # ./scripts/java-run-all.sh ../build-x86_64 com.jogamp.test.junit.newt.TestGLWindows01NEWT
REM # ./scripts/java-run-all.sh ../build-x86_64 com.jogamp.test.junit.newt.TestGLWindows02NEWTAnimated
REM scripts\java-win64-dbg.bat com.jogamp.test.junit.newt.parenting.TestParenting01NEWT
-scripts\java-win64-dbg.bat com.jogamp.test.junit.newt.TestFocus01SwingAWTRobot
+REM scripts\java-win64-dbg.bat com.jogamp.test.junit.newt.TestFocus02SwingAWTRobot
REM scripts\java-win64-dbg.bat com.jogamp.test.junit.newt.TestFocus01SwingAWTRobot
REM scripts\java-win64-dbg.bat com.jogamp.test.junit.nativewindow.TestRecursiveToolkitLockCORE
+
+scripts\java-win32.bat com.jogamp.test.junit.newt.TestFocus02SwingAWTRobot
diff --git a/src/jogl/classes/com/jogamp/opengl/impl/GLContextLock.java b/src/jogl/classes/com/jogamp/opengl/impl/GLContextLock.java
index 56a5b023f..6d0c5d984 100644
--- a/src/jogl/classes/com/jogamp/opengl/impl/GLContextLock.java
+++ b/src/jogl/classes/com/jogamp/opengl/impl/GLContextLock.java
@@ -1,5 +1,6 @@
/*
* Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright (c) 2010 JogAmp Community. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -49,36 +50,38 @@ import javax.media.opengl.*;
be raised. */
public class GLContextLock {
- private Object lock = new Object();
- private Thread owner;
- private boolean failFastMode = true;
- private volatile int waiters;
+ static class SyncData {
+ Thread owner = null;
+ boolean failFastMode = true;
+ int waiters = 0;
+ }
+ private SyncData sdata = new SyncData(); // synchronized (flow/mem) mutable access
/** Locks this GLContextLock on the current thread. If fail fast
mode is enabled and the GLContextLock is already owned by
another thread, throws GLException. */
- public void lock() throws GLException {
- synchronized(lock) {
+ public final void lock() throws GLException {
+ synchronized(sdata) {
Thread current = Thread.currentThread();
- if (owner == null) {
- owner = current;
- } else if (owner != current) {
- while (owner != null) {
- if (failFastMode) {
+ if (sdata.owner == null) {
+ sdata.owner = current;
+ } else if (sdata.owner != current) {
+ while (sdata.owner != null) {
+ if (sdata.failFastMode) {
throw new GLException("Attempt to make context current on thread " + current +
- " which is already current on thread " + owner);
+ " which is already current on thread " + sdata.owner);
} else {
try {
- ++waiters;
- lock.wait();
+ ++sdata.waiters;
+ sdata.wait();
} catch (InterruptedException e) {
throw new GLException(e);
} finally {
- --waiters;
+ --sdata.waiters;
}
}
}
- owner = current;
+ sdata.owner = current;
} else {
throw new GLException("Attempt to make the same context current twice on thread " + current);
}
@@ -86,16 +89,18 @@ public class GLContextLock {
}
/** Unlocks this GLContextLock. */
- public void unlock() throws GLException {
- synchronized (lock) {
+ public final void unlock() throws GLException {
+ synchronized (sdata) {
Thread current = Thread.currentThread();
- if (owner == current) {
- owner = null;
- lock.notifyAll();
+ if (sdata.owner == current) {
+ sdata.owner = null;
+ // Assuming notify() implementation weaks up the longest waiting thread, to avoid starvation.
+ // Otherwise we would need to have a Thread queue implemented, using sleep(timeout) and interrupt.
+ sdata.notify();
} else {
- if (owner != null) {
+ if (sdata.owner != null) {
throw new GLException("Attempt by thread " + current +
- " to release context owned by thread " + owner);
+ " to release context owned by thread " + sdata.owner);
} else {
throw new GLException("Attempt by thread " + current +
" to release unowned context");
@@ -105,22 +110,28 @@ public class GLContextLock {
}
/** Indicates whether this lock is held by the current thread. */
- public boolean isHeld() {
- synchronized(lock) {
+ public final boolean isHeld() {
+ synchronized(sdata) {
Thread current = Thread.currentThread();
- return (owner == current);
+ return (sdata.owner == current);
}
}
- public void setFailFastMode(boolean onOrOff) {
- failFastMode = onOrOff;
+ public final void setFailFastMode(boolean onOrOff) {
+ synchronized(sdata) {
+ sdata.failFastMode = onOrOff;
+ }
}
- public boolean getFailFastMode() {
- return failFastMode;
+ public final boolean getFailFastMode() {
+ synchronized(sdata) {
+ return sdata.failFastMode;
+ }
}
- public boolean hasWaiters() {
- return (waiters != 0);
+ public final boolean hasWaiters() {
+ synchronized(sdata) {
+ return (sdata.waiters != 0);
+ }
}
}
diff --git a/src/junit/com/jogamp/test/junit/newt/TestFocus01SwingAWTRobot.java b/src/junit/com/jogamp/test/junit/newt/TestFocus01SwingAWTRobot.java
index 97b37aec0..6ae0ee9d3 100644
--- a/src/junit/com/jogamp/test/junit/newt/TestFocus01SwingAWTRobot.java
+++ b/src/junit/com/jogamp/test/junit/newt/TestFocus01SwingAWTRobot.java
@@ -161,7 +161,7 @@ public class TestFocus01SwingAWTRobot extends UITestCase {
Thread.sleep(100); // allow event sync
System.err.println("FOCUS AWT Button request");
EventCountAdapterUtil.reset(eventCountAdapters);
- Assert.assertTrue(AWTRobotUtil.requestFocusAndWait(robot, button, button));
+ Assert.assertTrue(AWTRobotUtil.requestFocusAndWait(robot, button, button, buttonFA, null));
Assert.assertEquals(1, buttonFA.getCount());
Assert.assertEquals(0, glWindow1FA.getCount());
Assert.assertEquals(0, newtCanvasAWTFA.getCount());
@@ -172,10 +172,11 @@ public class TestFocus01SwingAWTRobot extends UITestCase {
Thread.sleep(100); // allow event sync
System.err.println("FOCUS NEWT Canvas/GLWindow request");
EventCountAdapterUtil.reset(eventCountAdapters);
- Assert.assertTrue(AWTRobotUtil.requestFocusAndWait(robot, newtCanvasAWT, newtCanvasAWT.getNEWTChild()));
+ Assert.assertTrue(AWTRobotUtil.requestFocusAndWait(robot, newtCanvasAWT, newtCanvasAWT.getNEWTChild(), glWindow1FA, buttonFA));
+ Assert.assertTrue(AWTRobotUtil.waitForCount(0, newtCanvasAWTFA));
Assert.assertEquals(1, glWindow1FA.getCount());
Assert.assertEquals(0, newtCanvasAWTFA.getCount());
- // Assert.assertEquals(-1, buttonFA.getCount()); // lost focus
+ Assert.assertEquals(-1, buttonFA.getCount()); // lost focus
System.err.println("FOCUS NEWT Canvas/GLWindow sync");
Assert.assertEquals(2, AWTRobotUtil.testKeyType(robot, 2, glWindow1, glWindow1KA));
Assert.assertEquals("AWT parent canvas received keyboard events", 0, newtCanvasAWTKA.getCount());
diff --git a/src/junit/com/jogamp/test/junit/newt/TestFocus02SwingAWTRobot.java b/src/junit/com/jogamp/test/junit/newt/TestFocus02SwingAWTRobot.java
index a7602b49b..1ca5e6cd7 100644
--- a/src/junit/com/jogamp/test/junit/newt/TestFocus02SwingAWTRobot.java
+++ b/src/junit/com/jogamp/test/junit/newt/TestFocus02SwingAWTRobot.java
@@ -177,7 +177,7 @@ public class TestFocus02SwingAWTRobot extends UITestCase {
Thread.sleep(100); // allow event sync
System.err.println("FOCUS AWT Button Outer request");
EventCountAdapterUtil.reset(eventCountAdapters);
- Assert.assertTrue(AWTRobotUtil.requestFocusAndWait(robot, buttonNorthOuter, buttonNorthOuter));
+ Assert.assertTrue(AWTRobotUtil.requestFocusAndWait(robot, buttonNorthOuter, buttonNorthOuter, buttonNorthOuterFA, null));
Assert.assertEquals(1, buttonNorthOuterFA.getCount());
Assert.assertEquals(0, glWindow1FA.getCount());
Assert.assertEquals(0, newtCanvasAWTFA.getCount());
@@ -194,11 +194,12 @@ public class TestFocus02SwingAWTRobot extends UITestCase {
Thread.sleep(100); // allow event sync
System.err.println("FOCUS NEWT Canvas/GLWindow request");
EventCountAdapterUtil.reset(eventCountAdapters);
- Assert.assertTrue(AWTRobotUtil.requestFocusAndWait(robot, newtCanvasAWT, newtCanvasAWT.getNEWTChild()));
+ Assert.assertTrue(AWTRobotUtil.requestFocusAndWait(robot, newtCanvasAWT, newtCanvasAWT.getNEWTChild(), glWindow1FA, buttonNorthOuterFA));
+ Assert.assertTrue(AWTRobotUtil.waitForCount(0, newtCanvasAWTFA));
Assert.assertEquals(1, glWindow1FA.getCount());
Assert.assertEquals(0, newtCanvasAWTFA.getCount());
Assert.assertEquals(0, buttonNorthInnerFA.getCount());
- // Assert.assertEquals(-1, buttonNorthOuterFA.getCount()); // lost focus
+ Assert.assertEquals(-1, buttonNorthOuterFA.getCount()); // lost focus
Assert.assertEquals(0, jFrame1FA.getCount());
System.err.println("FOCUS NEWT Canvas/GLWindow sync");
Assert.assertEquals(2, AWTRobotUtil.testKeyType(robot, 2, glWindow1, glWindow1KA));
@@ -213,9 +214,9 @@ public class TestFocus02SwingAWTRobot extends UITestCase {
Thread.sleep(100); // allow event sync
System.err.println("FOCUS AWT Button request");
EventCountAdapterUtil.reset(eventCountAdapters);
- Assert.assertTrue(AWTRobotUtil.requestFocusAndWait(robot, buttonNorthInner, buttonNorthInner));
+ Assert.assertTrue(AWTRobotUtil.requestFocusAndWait(robot, buttonNorthInner, buttonNorthInner, buttonNorthInnerFA, glWindow1FA));
Assert.assertEquals(1, buttonNorthInnerFA.getCount());
- // Assert.assertEquals(-1, glWindow1FA.getCount()); // lost focus
+ Assert.assertEquals(-1, glWindow1FA.getCount()); // lost focus
Assert.assertEquals(0, newtCanvasAWTFA.getCount());
Assert.assertEquals(0, buttonNorthOuterFA.getCount());
Assert.assertEquals(0, jFrame1FA.getCount());
@@ -230,10 +231,11 @@ public class TestFocus02SwingAWTRobot extends UITestCase {
Thread.sleep(100); // allow event sync
System.err.println("FOCUS NEWT Canvas/GLWindow request");
EventCountAdapterUtil.reset(eventCountAdapters);
- Assert.assertTrue(AWTRobotUtil.requestFocusAndWait(robot, newtCanvasAWT, newtCanvasAWT.getNEWTChild()));
+ Assert.assertTrue(AWTRobotUtil.requestFocusAndWait(robot, newtCanvasAWT, newtCanvasAWT.getNEWTChild(), glWindow1FA, buttonNorthInnerFA));
+ Assert.assertTrue(AWTRobotUtil.waitForCount(0, newtCanvasAWTFA));
Assert.assertEquals(1, glWindow1FA.getCount());
Assert.assertEquals(0, newtCanvasAWTFA.getCount());
- // Assert.assertEquals(-1, buttonNorthInnerFA.getCount()); // lost focus
+ Assert.assertEquals(-1, buttonNorthInnerFA.getCount()); // lost focus
Assert.assertEquals(0, buttonNorthOuterFA.getCount());
Assert.assertEquals(0, jFrame1FA.getCount());
System.err.println("FOCUS NEWT Canvas/GLWindow sync");
diff --git a/src/junit/com/jogamp/test/junit/util/AWTRobotUtil.java b/src/junit/com/jogamp/test/junit/util/AWTRobotUtil.java
index 48563b190..4e0d4a883 100644
--- a/src/junit/com/jogamp/test/junit/util/AWTRobotUtil.java
+++ b/src/junit/com/jogamp/test/junit/util/AWTRobotUtil.java
@@ -211,6 +211,27 @@ public class AWTRobotUtil {
return wait<POLL_DIVIDER;
}
+ /**
+ *
+ * @return True if the Window became the global focused Window within TIME_OUT
+ */
+ public static boolean waitForFocus(Object obj, int gainT0, EventCountAdapter gain,
+ int lostT0, EventCountAdapter lost) throws InterruptedException {
+ if(!waitForFocus(obj)) {
+ return false;
+ }
+ int wait;
+ for (wait=0; wait<POLL_DIVIDER; wait++) {
+ int gainT1 = gain.getCount();
+ int lostT1 = (null!=lost) ? lost.getCount() : -1;
+ if(gainT1-gainT0==1 && lostT1-lostT0==-1) {
+ return true;
+ }
+ Thread.sleep(TIME_OUT/POLL_DIVIDER);
+ }
+ return false;
+ }
+
public static boolean requestFocusAndWait(Robot robot, Object requestFocus, Object waitForFocus)
throws AWTException, InterruptedException, InvocationTargetException {
@@ -218,6 +239,17 @@ public class AWTRobotUtil {
return waitForFocus(waitForFocus);
}
+ public static boolean requestFocusAndWait(Robot robot, Object requestFocus, Object waitForFocus,
+ EventCountAdapter gain, EventCountAdapter lost)
+ throws AWTException, InterruptedException, InvocationTargetException {
+
+ int gainT0 = gain.getCount();
+ int lostT0 = (null!=lost) ? lost.getCount() : 0;
+
+ requestFocus(robot, requestFocus);
+ return waitForFocus(waitForFocus, gainT0, gain, lostT0, lost);
+ }
+
/**
* @param keyTypedCounter shall return the number of keys typed (press + release)
* @return True if typeCount keys within TIME_OUT has been received
@@ -288,5 +320,19 @@ public class AWTRobotUtil {
return mouseClickCounter.getCount()-c0;
}
+ /**
+ *
+ * @return True if the EventCountAdapter became the desired value within TIME_OUT
+ */
+ public static boolean waitForCount(int desired, EventCountAdapter eca) throws InterruptedException {
+ for (int wait=0; wait<POLL_DIVIDER; wait++) {
+ if( eca.getCount() == desired ) {
+ return true;
+ }
+ Thread.sleep(TIME_OUT/POLL_DIVIDER);
+ }
+ return false;
+ }
+
}