aboutsummaryrefslogtreecommitdiffstats
path: root/src/jogl/classes/jogamp/opengl
diff options
context:
space:
mode:
authorSven Gothel <[email protected]>2011-12-11 04:47:27 +0100
committerSven Gothel <[email protected]>2011-12-11 04:47:27 +0100
commit9291731fec7103301ba36511ceb4375f63170e5c (patch)
treeec7f0d9c9ce611833840971206d2c591a94653b4 /src/jogl/classes/jogamp/opengl
parentd9bbbbad1130bbe74856ecedb7cf1d2cc124b352 (diff)
Fix concurrency bug of GLProfile initialization ; Fix SharedResourceRunner 'dead' thread (Applets)
GLDrawableFactory: - clarify: public getWasSharedContextCreated(..) -> protected createSharedResource(..) - add: getSharesResourceThread() GLProfile: - proper locking of initSingletion(..) path: - Use RecursiveThreadGroupLock and add/remove GLDrawableFactory's sharesResourceThread while creating it's the sharedResource. This simplifies and fixes GLProfile's locking code. - Fix and simplify initSingleton(boolean) API doc - mark it deprecated. - Add initSingleton() for controlled initialization only, pairing w/ shutdown(..) Remove initSingleton(boolean) calls in code and test! +++ Fix SharedResourceRunner 'dead' thread (Applets) In Applets, stopping an Applet makes the browser Java plugin interrupting and killing all related threads, including our SharedResourceRunner thread. - Validate whether the shared resource thread is alive - Catch interruption in shared resource thread and assume it's a kill signal - releaseSharedResource: clear devicesTried set
Diffstat (limited to 'src/jogl/classes/jogamp/opengl')
-rw-r--r--src/jogl/classes/jogamp/opengl/GLContextImpl.java2
-rw-r--r--src/jogl/classes/jogamp/opengl/SharedResourceRunner.java149
-rw-r--r--src/jogl/classes/jogamp/opengl/awt/VersionApplet.java2
-rw-r--r--src/jogl/classes/jogamp/opengl/egl/EGLDrawableFactory.java6
-rw-r--r--src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDrawableFactory.java8
-rw-r--r--src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLDrawableFactory.java17
-rw-r--r--src/jogl/classes/jogamp/opengl/x11/glx/X11GLXDrawableFactory.java17
7 files changed, 134 insertions, 67 deletions
diff --git a/src/jogl/classes/jogamp/opengl/GLContextImpl.java b/src/jogl/classes/jogamp/opengl/GLContextImpl.java
index 5ea1a9bac..0d372587e 100644
--- a/src/jogl/classes/jogamp/opengl/GLContextImpl.java
+++ b/src/jogl/classes/jogamp/opengl/GLContextImpl.java
@@ -459,8 +459,6 @@ public abstract class GLContextImpl extends GLContext {
throw new GLException("drawable has invalid handle: "+drawable);
}
if (!isCreated()) {
- GLProfile.initProfiles(
- getGLDrawable().getNativeSurface().getGraphicsConfiguration().getScreen().getDevice());
final GLContextImpl shareWith = (GLContextImpl) GLContextShareSet.getShareContext(this);
if (null != shareWith) {
shareWith.getDrawableImpl().lockSurface();
diff --git a/src/jogl/classes/jogamp/opengl/SharedResourceRunner.java b/src/jogl/classes/jogamp/opengl/SharedResourceRunner.java
index e24a9f8ed..a33e03a1a 100644
--- a/src/jogl/classes/jogamp/opengl/SharedResourceRunner.java
+++ b/src/jogl/classes/jogamp/opengl/SharedResourceRunner.java
@@ -44,6 +44,10 @@ public class SharedResourceRunner implements Runnable {
}
public static interface Implementation {
+ /**
+ * @param connection for creation a {@link AbstractGraphicsDevice} instance.
+ * @return A new shared resource instance
+ */
Resource createSharedResource(String connection);
void releaseSharedResource(Resource shared);
void clear();
@@ -53,15 +57,15 @@ public class SharedResourceRunner implements Runnable {
Collection<Resource> mapValues();
}
- Implementation impl = null;
+ final HashSet<String> devicesTried = new HashSet<String>();
+ final Implementation impl;
- boolean ready = false;
- boolean released = false;
- boolean shouldRelease = false;
- String initConnection = null;
- String releaseConnection = null;
-
- HashSet<String> devicesTried = new HashSet<String>();
+ Thread thread;
+ boolean ready;
+ boolean released;
+ boolean shouldRelease;
+ String initConnection;
+ String releaseConnection;
private boolean getDeviceTried(String connection) {
synchronized (devicesTried) {
@@ -81,22 +85,82 @@ public class SharedResourceRunner implements Runnable {
public SharedResourceRunner(Implementation impl) {
this.impl = impl;
+ resetState();
+ }
+
+ private void resetState() {
+ devicesTried.clear();
+ thread = null;
+ ready = false;
+ released = false;
+ shouldRelease = false;
+ initConnection = null;
+ releaseConnection = null;
}
+ /**
+ * Start the shared resource runner thread, if not running.
+ * <p>
+ * Validate the thread upfront and release all related resource if it was killed.
+ * </p>
+ *
+ * @return the shared resource runner thread.
+ */
+ public Thread start() {
+ if(null != thread && !thread.isAlive()) {
+ // thread was killed unrecognized ..
+ if (DEBUG) {
+ System.err.println("SharedResourceRunner.start() - dead-old-thread cleanup - "+Thread.currentThread().getName());
+ }
+ releaseSharedResources();
+ thread = null;
+ }
+ if(null == thread) {
+ if (DEBUG) {
+ System.err.println("SharedResourceRunner.start() - start new Thread - "+Thread.currentThread().getName());
+ }
+ resetState();
+ thread = new Thread(this, Thread.currentThread().getName()+"-SharedResourceRunner");
+ thread.setDaemon(true); // Allow JVM to exit, even if this one is running
+ thread.start();
+ }
+ return thread;
+ }
+
+ public void stop() {
+ if(null != thread) {
+ if (DEBUG) {
+ System.err.println("SharedResourceRunner.stop() - "+Thread.currentThread().getName());
+ }
+ synchronized (this) {
+ shouldRelease = true;
+ this.notifyAll();
+
+ while (!released) {
+ try {
+ this.wait();
+ } catch (InterruptedException ex) {
+ }
+ }
+ }
+ }
+ }
+
public SharedResourceRunner.Resource getOrCreateShared(AbstractGraphicsDevice device) {
SharedResourceRunner.Resource sr = null;
if(null != device) {
+ start();
final String connection = device.getConnection();
sr = impl.mapGet(connection);
if (null == sr && !getDeviceTried(connection)) {
addDeviceTried(connection);
if (DEBUG) {
- System.err.println("getOrCreateShared() " + connection + ": trying");
+ System.err.println("SharedResourceRunner.getOrCreateShared() " + connection + ": trying - "+Thread.currentThread().getName());
}
doAndWait(connection, null);
sr = impl.mapGet(connection);
if (DEBUG) {
- System.err.println("getOrCreateShared() " + connection + ": "+ ( ( null != sr ) ? "success" : "failed" ) );
+ System.err.println("SharedResourceRunner.getOrCreateShared() " + connection + ": "+ ( ( null != sr ) ? "success" : "failed" ) +" - "+Thread.currentThread().getName());
}
}
}
@@ -111,11 +175,11 @@ public class SharedResourceRunner implements Runnable {
if (null != sr) {
removeDeviceTried(connection);
if (DEBUG) {
- System.err.println("releaseShared() " + connection + ": trying");
+ System.err.println("SharedResourceRunner.releaseShared() " + connection + ": trying - "+Thread.currentThread().getName());
}
doAndWait(null, connection);
if (DEBUG) {
- System.err.println("releaseShared() " + connection + ": done");
+ System.err.println("SharedResourceRunner.releaseShared() " + connection + ": done - "+Thread.currentThread().getName());
}
}
}
@@ -125,9 +189,9 @@ public class SharedResourceRunner implements Runnable {
private final void doAndWait(String initConnection, String releaseConnection) {
// wait until thread becomes ready to init new device,
// pass the device and release the sync
- String threadName = Thread.currentThread().getName();
+ final String threadName = Thread.currentThread().getName();
if (DEBUG) {
- System.err.println(threadName + " doAndWait START init: " + initConnection + ", release: "+releaseConnection);
+ System.err.println("SharedResourceRunner.doAndWait() START init: " + initConnection + ", release: "+releaseConnection+" - "+threadName);
}
synchronized (this) {
while (!ready) {
@@ -137,7 +201,7 @@ public class SharedResourceRunner implements Runnable {
}
}
if (DEBUG) {
- System.err.println(threadName + " initializeAndWait set command init: " + initConnection + ", release: "+releaseConnection);
+ System.err.println("SharedResourceRunner.doAndWait() set command: " + initConnection + ", release: "+releaseConnection+" - "+threadName);
}
this.initConnection = initConnection;
this.releaseConnection = releaseConnection;
@@ -151,31 +215,17 @@ public class SharedResourceRunner implements Runnable {
}
}
if (DEBUG) {
- System.err.println(threadName + " initializeAndWait END init: " + initConnection + ", release: "+releaseConnection);
+ System.err.println("SharedResourceRunner.initializeAndWait END init: " + initConnection + ", release: "+releaseConnection+" - "+threadName);
}
}
// done
}
- public final void releaseAndWait() {
- synchronized (this) {
- shouldRelease = true;
- this.notifyAll();
-
- while (!released) {
- try {
- this.wait();
- } catch (InterruptedException ex) {
- }
- }
- }
- }
-
public final void run() {
- String threadName = Thread.currentThread().getName();
+ final String threadName = Thread.currentThread().getName();
if (DEBUG) {
- System.err.println(threadName + " STARTED");
+ System.err.println("SharedResourceRunner.run(): STARTED - " + threadName);
}
synchronized (this) {
@@ -184,21 +234,27 @@ public class SharedResourceRunner implements Runnable {
// wait for stop or init
ready = true;
if (DEBUG) {
- System.err.println(threadName + " -> ready");
+ System.err.println("SharedResourceRunner.run(): READY - " + threadName);
}
notifyAll();
this.wait();
- } catch (InterruptedException ex) { }
+ } catch (InterruptedException ex) {
+ shouldRelease = true;
+ if(DEBUG) {
+ System.err.println("SharedResourceRunner.run(): INTERRUPTED - "+Thread.currentThread().getName());
+ ex.printStackTrace();
+ }
+ }
ready = false;
if (!shouldRelease) {
if (DEBUG) {
- System.err.println(threadName + " woke up for device connection init: " + initConnection +
- ", release: " + releaseConnection);
+ System.err.println("SharedResourceRunner.run(): WOKE UP for device connection init: " + initConnection +
+ ", release: " + releaseConnection + " - " + threadName);
}
if(null != initConnection) {
if (DEBUG) {
- System.err.println(threadName + " create Shared for: " + initConnection);
+ System.err.println("SharedResourceRunner.run(): create Shared for: " + initConnection + " - " + threadName);
}
Resource sr = null;
try {
@@ -212,7 +268,7 @@ public class SharedResourceRunner implements Runnable {
}
if(null != releaseConnection) {
if (DEBUG) {
- System.err.println(threadName + " release Shared for: " + releaseConnection);
+ System.err.println("SharedResourceRunner.run(): release Shared for: " + releaseConnection + " - " + threadName);
}
Resource sr = impl.mapGet(releaseConnection);
if (null != sr) {
@@ -230,25 +286,34 @@ public class SharedResourceRunner implements Runnable {
}
if (DEBUG) {
- System.err.println(threadName + " release START");
+ System.err.println("SharedResourceRunner.run(): RELEASE START - " + threadName);
}
releaseSharedResources();
if (DEBUG) {
- System.err.println(threadName + " release END");
+ System.err.println("SharedResourceRunner.run(): RELEASE END - " + threadName);
}
+ shouldRelease = false;
released = true;
- ready = false;
+ thread = null;
notifyAll();
}
}
private void releaseSharedResources() {
+ synchronized (devicesTried) {
+ devicesTried.clear();
+ }
Collection<Resource> sharedResources = impl.mapValues();
for (Iterator<Resource> iter = sharedResources.iterator(); iter.hasNext();) {
- impl.releaseSharedResource(iter.next());
+ try {
+ impl.releaseSharedResource(iter.next());
+ } catch (Throwable t) {
+ System.err.println("Catched Exception: "+t.getStackTrace()+" - "+Thread.currentThread().getName());
+ t.printStackTrace();
+ }
}
impl.clear();
}
diff --git a/src/jogl/classes/jogamp/opengl/awt/VersionApplet.java b/src/jogl/classes/jogamp/opengl/awt/VersionApplet.java
index b7c90a18b..55fb3f9a2 100644
--- a/src/jogl/classes/jogamp/opengl/awt/VersionApplet.java
+++ b/src/jogl/classes/jogamp/opengl/awt/VersionApplet.java
@@ -131,7 +131,6 @@ public class VersionApplet extends Applet {
public void init() {
System.err.println("VersionApplet: init() - begin");
- GLProfile.initSingleton(false);
my_init();
System.err.println("VersionApplet: init() - end");
}
@@ -151,7 +150,6 @@ public class VersionApplet extends Applet {
public void destroy() {
System.err.println("VersionApplet: destroy() - start");
my_release();
- GLProfile.shutdown(GLProfile.ShutdownType.SHARED_ONLY);
System.err.println("VersionApplet: destroy() - end");
}
diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLDrawableFactory.java b/src/jogl/classes/jogamp/opengl/egl/EGLDrawableFactory.java
index f6988a73f..cd6d61a22 100644
--- a/src/jogl/classes/jogamp/opengl/egl/EGLDrawableFactory.java
+++ b/src/jogl/classes/jogamp/opengl/egl/EGLDrawableFactory.java
@@ -232,7 +232,11 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl {
return sr;
}
- public final boolean getWasSharedContextCreated(AbstractGraphicsDevice device) {
+ protected final Thread getSharedResourceThread() {
+ return null;
+ }
+
+ protected final boolean createSharedResource(AbstractGraphicsDevice device) {
try {
SharedResource sr = getOrCreateEGLSharedResource(device);
if(null!=sr) {
diff --git a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDrawableFactory.java b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDrawableFactory.java
index 45445067e..ed53a9ee5 100644
--- a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDrawableFactory.java
+++ b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDrawableFactory.java
@@ -252,8 +252,12 @@ public class MacOSXCGLDrawableFactory extends GLDrawableFactoryImpl {
}
return sr;
}
-
- public final boolean getWasSharedContextCreated(AbstractGraphicsDevice device) {
+
+ protected final Thread getSharedResourceThread() {
+ return null;
+ }
+
+ protected final boolean createSharedResource(AbstractGraphicsDevice device) {
try {
SharedResource sr = getOrCreateOSXSharedResource(device);
if(null!=sr) {
diff --git a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLDrawableFactory.java b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLDrawableFactory.java
index 917402b0a..43c16240d 100644
--- a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLDrawableFactory.java
+++ b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLDrawableFactory.java
@@ -119,17 +119,14 @@ public class WindowsWGLDrawableFactory extends GLDrawableFactoryImpl {
// Init shared resources off thread
// Will be released via ShutdownHook
- sharedResourceImpl = new SharedResourceImplementation();
- sharedResourceRunner = new SharedResourceRunner(sharedResourceImpl);
- sharedResourceThread = new Thread(sharedResourceRunner, Thread.currentThread().getName()+"-SharedResourceRunner");
- sharedResourceThread.setDaemon(true); // Allow JVM to exit, even if this one is running
- sharedResourceThread.start();
+ sharedResourceRunner = new SharedResourceRunner(new SharedResourceImplementation());
+ sharedResourceRunner.start();
}
}
protected final void destroy(ShutdownType shutdownType) {
if(null != sharedResourceRunner) {
- sharedResourceRunner.releaseAndWait();
+ sharedResourceRunner.stop();
sharedResourceRunner = null;
}
if(null != sharedMap) {
@@ -153,9 +150,7 @@ public class WindowsWGLDrawableFactory extends GLDrawableFactoryImpl {
}
private WindowsGraphicsDevice defaultDevice;
- private SharedResourceImplementation sharedResourceImpl;
private SharedResourceRunner sharedResourceRunner;
- private Thread sharedResourceThread;
private HashMap<String /*connection*/, SharedResourceRunner.Resource> sharedMap;
private long processAffinityChanges = 0;
@@ -397,7 +392,11 @@ public class WindowsWGLDrawableFactory extends GLDrawableFactoryImpl {
final static String WGL_ARB_make_current_read = "WGL_ARB_make_current_read";
final static String wglMakeContextCurrent = "wglMakeContextCurrent";
- public final boolean getWasSharedContextCreated(AbstractGraphicsDevice device) {
+ protected final Thread getSharedResourceThread() {
+ return sharedResourceRunner.start();
+ }
+
+ protected final boolean createSharedResource(AbstractGraphicsDevice device) {
try {
SharedResourceRunner.Resource sr = sharedResourceRunner.getOrCreateShared(device);
if(null!=sr) {
diff --git a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXDrawableFactory.java b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXDrawableFactory.java
index 96153dd27..235aea499 100644
--- a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXDrawableFactory.java
+++ b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXDrawableFactory.java
@@ -111,17 +111,14 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl {
// Init shared resources off thread
// Will be released via ShutdownHook
- sharedResourceImpl = new SharedResourceImplementation();
- sharedResourceRunner = new SharedResourceRunner(sharedResourceImpl);
- sharedResourceThread = new Thread(sharedResourceRunner, Thread.currentThread().getName()+"-SharedResourceRunner");
- sharedResourceThread.setDaemon(true); // Allow JVM to exit, even if this one is running
- sharedResourceThread.start();
+ sharedResourceRunner = new SharedResourceRunner(new SharedResourceImplementation());
+ sharedResourceRunner.start();
}
}
protected final void destroy(ShutdownType shutdownType) {
if(null != sharedResourceRunner) {
- sharedResourceRunner.releaseAndWait();
+ sharedResourceRunner.stop();
sharedResourceRunner = null;
}
if(null != sharedMap) {
@@ -147,9 +144,7 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl {
}
private X11GraphicsDevice defaultDevice;
- private SharedResourceImplementation sharedResourceImpl;
private SharedResourceRunner sharedResourceRunner;
- private Thread sharedResourceThread;
private HashMap<String /* connection */, SharedResourceRunner.Resource> sharedMap;
static class SharedResource implements SharedResourceRunner.Resource {
@@ -322,7 +317,11 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl {
return false;
}
- public final boolean getWasSharedContextCreated(AbstractGraphicsDevice device) {
+ protected final Thread getSharedResourceThread() {
+ return sharedResourceRunner.start();
+ }
+
+ protected final boolean createSharedResource(AbstractGraphicsDevice device) {
try {
SharedResourceRunner.Resource sr = sharedResourceRunner.getOrCreateShared(device);
if(null!=sr) {