diff options
author | Sven Gothel <[email protected]> | 2011-12-11 04:47:27 +0100 |
---|---|---|
committer | Sven Gothel <[email protected]> | 2011-12-11 04:47:27 +0100 |
commit | 9291731fec7103301ba36511ceb4375f63170e5c (patch) | |
tree | ec7f0d9c9ce611833840971206d2c591a94653b4 /src/jogl/classes/jogamp/opengl | |
parent | d9bbbbad1130bbe74856ecedb7cf1d2cc124b352 (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')
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) { |