diff options
author | Sven Gothel <[email protected]> | 2015-09-15 07:50:50 +0200 |
---|---|---|
committer | Sven Gothel <[email protected]> | 2015-09-15 07:50:50 +0200 |
commit | 68c8e39fa8d6e700f0a99241c1a01a435b7f6284 (patch) | |
tree | d02cf789a06514da205f6da8a45f55538b019a0b /src/newt | |
parent | cf9b31c30de3768447b20d6aa31ec1df00595871 (diff) |
Bug 1211: Hardening Condition-Wait from Spurious-Wakeups and unintended InterruptedException(s)
Below is an updated list of Condition-Wait classifications
as described in Bug 1211.
This list includes recent changes on GlueGen
regarding this Bug 1211.
A followup commit will address the unit tests.
- Noncancelable + Persistent-Wait
- GLMediaPlayerImpl.StreamWorker thread (changed)
- pauses thread in case of intr
- Cancelable + Persistent-Wait:
- LFRingbuffer.getImpl(..)
- LFRingbuffer.waitForFreeSlots(int)
- SyncedRingbuffer.getImpl(..)
- SyncedRingbuffer.waitForFreeSlots(int)
- FunctionTask.invokeOnNewThread(..) (changed)
- RunnableTask.invokeOnNewThread(..) (changed)
- SharedResourceRunner.run()
- SharedResourceRunner.doAndWait() (changed)
- SharedResourceRunner.start() (changed)
- SharedResourceRunner.stop() (changed)
- GLMediaPlayerImpl.StreamWorker ctor (changed)
- GLMediaPlayerImpl caller thread actions do*() (changed)
- AndroidGLMediaPlayerAPI14.getNextTextureImpl(..) (changed)
- DisplayImpl.enqueueEvent(..) (changed)
-> Persistent-Wait
-> Cancels wait and NEWTEvent
-> dispatchMessage(NEWTEventTask): always notifyCaller!
- GLDrawableHelper.invoke(..) (changed)
- DefaultEDTUtil.waitUntilIdle() (changed)
- DefaultEDTUtil.waitUntilStopped() (changed)
- DefaultEDTUtil.invokeImpl(..) (changed)
- DefaultEDTUtil.NEDT.run(..) (changed)
- AWTEDTUtil.waitUntilStopped(..) (changed)
- AWTEDTUtil.invokeImpl(..) (changed)
- AWTEDTUtil.NEDT.run(..) (changed)
- SWTEDTUtil.invokeImpl(..) (changed)
- SWTEDTUtil.waitUntilStopped(..) (changed)
- SWTEDTUtil.NEDT.run(..) (changed)
- GLWorkerThread.invokeAndWait(..)
- GLWorkerThread.start() (changed)
- GLWorkerThread.WorkerRunnable.run() (changed)
- Animator.run() (changed)
- AnimatorBase.finishLifecycleAction() (changed)
- OSXUtil.RunOnMainThread(..) (changed)
- SingletonInstanceServerSocket.Server.shutdown() (changed)
- SingletonInstanceServerSocket.Server.start() (changed)
- com.jogamp.audio.windows.waveout.Mixer.shutdown() (changed)
- Extending/Using InterruptSource.Thread (changed)
- DefaultEDTUtil.NEDT
- AWTEDTUtil.NEDT
- SWTEDTUtil.NEDT
- GLWorkerThread.thread
- Mixer.FillerThread
- Mixer.MixerThread
- Using InterruptSource.Thread (changed)
- TempFileCache
- LauncherTempFileCache
- Animator.thread
- SingletonInstanceServerSocket.Server.serverThread
Deprecated:
- FunctionTask.invoke(..) (changed)
-> on current thread, no wait -> deprecated
- RunnableTask.invoke(..) (changed)
-> on current thread, no wait -> deprecated
Diffstat (limited to 'src/newt')
11 files changed, 604 insertions, 154 deletions
diff --git a/src/newt/classes/com/jogamp/newt/opengl/util/NEWTDemoListener.java b/src/newt/classes/com/jogamp/newt/opengl/util/NEWTDemoListener.java new file mode 100644 index 000000000..ca4b51192 --- /dev/null +++ b/src/newt/classes/com/jogamp/newt/opengl/util/NEWTDemoListener.java @@ -0,0 +1,499 @@ +/** + * Copyright 2015 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 met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ +package com.jogamp.newt.opengl.util; + +import java.net.URLConnection; + +import com.jogamp.common.util.IOUtil; +import com.jogamp.nativewindow.CapabilitiesImmutable; +import com.jogamp.nativewindow.ScalableSurface; +import com.jogamp.newt.Display; +import com.jogamp.newt.Display.PointerIcon; +import com.jogamp.newt.event.KeyEvent; +import com.jogamp.newt.event.KeyListener; +import com.jogamp.newt.event.MouseEvent; +import com.jogamp.newt.event.MouseListener; +import com.jogamp.newt.event.WindowAdapter; +import com.jogamp.newt.event.WindowEvent; +import com.jogamp.newt.opengl.GLWindow; +import com.jogamp.opengl.FPSCounter; +import com.jogamp.opengl.GL; +import com.jogamp.opengl.GLAnimatorControl; +import com.jogamp.opengl.GLAutoDrawable; +import com.jogamp.opengl.GLRunnable; +import com.jogamp.opengl.util.Gamma; +import com.jogamp.opengl.util.PNGPixelRect; + +import jogamp.newt.driver.PNGIcon; + +public class NEWTDemoListener extends WindowAdapter implements KeyListener, MouseListener { + protected final GLWindow glWindow; + final PointerIcon[] pointerIcons; + int pointerIconIdx = 0; + float gamma = 1f; + float brightness = 0f; + float contrast = 1f; + boolean confinedFixedCenter = false; + + public NEWTDemoListener(final GLWindow glWin, final PointerIcon[] pointerIcons) { + this.glWindow = glWin; + if( null != pointerIcons ) { + this.pointerIcons = pointerIcons; + } else { + this.pointerIcons = createPointerIcons(glWindow); + } + } + public NEWTDemoListener(final GLWindow glWin) { + this(glWin, null); + } + + protected void printlnState(final String prelude) { + System.err.println(prelude+": "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getSurfaceWidth()+"x"+glWindow.getSurfaceHeight()+", f "+glWindow.isFullscreen()+", a "+glWindow.isAlwaysOnTop()+", "+glWindow.getInsets()+", state "+glWindow.getStateMaskString()); + } + protected void printlnState(final String prelude, final String post) { + System.err.println(prelude+": "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getSurfaceWidth()+"x"+glWindow.getSurfaceHeight()+", f "+glWindow.isFullscreen()+", a "+glWindow.isAlwaysOnTop()+", "+glWindow.getInsets()+", state "+glWindow.getStateMaskString()+", "+post); + } + + @Override + public void keyPressed(final KeyEvent e) { + if( e.isAutoRepeat() || e.isConsumed() ) { + return; + } + final int keySymbol = e.getKeySymbol(); + switch(keySymbol) { + case KeyEvent.VK_SPACE: + e.setConsumed(true); + glWindow.invokeOnCurrentThread(new Runnable() { + public void run() { + if(glWindow.getAnimator().isPaused()) { + glWindow.getAnimator().resume(); + } else { + glWindow.getAnimator().pause(); + } + } } ); + break; + case KeyEvent.VK_A: + e.setConsumed(true); + glWindow.invokeOnNewThread(null, false, new Runnable() { + public void run() { + printlnState("[set alwaysontop pre]"); + glWindow.setAlwaysOnTop(!glWindow.isAlwaysOnTop()); + printlnState("[set alwaysontop post]"); + } } ); + break; + case KeyEvent.VK_B: + e.setConsumed(true); + glWindow.invokeOnNewThread(null, false, new Runnable() { + public void run() { + printlnState("[set alwaysonbottom pre]"); + glWindow.setAlwaysOnBottom(!glWindow.isAlwaysOnBottom()); + printlnState("[set alwaysonbottom post]"); + } } ); + break; + case KeyEvent.VK_C: + e.setConsumed(true); + glWindow.invokeOnNewThread(null, false, new Runnable() { + public void run() { + if( null != pointerIcons ) { + printlnState("[set pointer-icon pre]"); + final PointerIcon currentPI = glWindow.getPointerIcon(); + final PointerIcon newPI; + if( pointerIconIdx >= pointerIcons.length ) { + newPI=null; + pointerIconIdx=0; + } else { + newPI=pointerIcons[pointerIconIdx++]; + } + glWindow.setPointerIcon( newPI ); + printlnState("[set pointer-icon post]", currentPI+" -> "+glWindow.getPointerIcon()); + } + } } ); + break; + case KeyEvent.VK_D: + e.setConsumed(true); + glWindow.invokeOnNewThread(null, false, new Runnable() { + public void run() { + printlnState("[set undecorated pre]"); + glWindow.setUndecorated(!glWindow.isUndecorated()); + printlnState("[set undecorated post]"); + } } ); + break; + case KeyEvent.VK_F: + e.setConsumed(true); + quitAdapterOff(); + glWindow.invokeOnNewThread(null, false, new Runnable() { + public void run() { + printlnState("[set fullscreen pre]"); + if( glWindow.isFullscreen() ) { + glWindow.setFullscreen( false ); + } else { + if( e.isAltDown() ) { + glWindow.setFullscreen( null ); + } else { + glWindow.setFullscreen( true ); + } + } + printlnState("[set fullscreen post]"); + quitAdapterOn(); + } } ); + break; + case KeyEvent.VK_G: + e.setConsumed(true); + glWindow.invokeOnNewThread(null, false, new Runnable() { + public void run() { + final float newGamma = gamma + ( e.isShiftDown() ? -0.1f : 0.1f ); + System.err.println("[set gamma]: "+gamma+" -> "+newGamma); + if( Gamma.setDisplayGamma(glWindow, newGamma, brightness, contrast) ) { + gamma = newGamma; + } + } } ); + break; + case KeyEvent.VK_I: + e.setConsumed(true); + glWindow.invokeOnNewThread(null, false, new Runnable() { + public void run() { + printlnState("[set pointer-visible pre]"); + glWindow.setPointerVisible(!glWindow.isPointerVisible()); + printlnState("[set pointer-visible post]"); + } } ); + break; + case KeyEvent.VK_J: + e.setConsumed(true); + glWindow.invokeOnNewThread(null, false, new Runnable() { + public void run() { + printlnState("[set pointer-confined pre]", "warp-center: "+e.isShiftDown()); + final boolean confine = !glWindow.isPointerConfined(); + glWindow.confinePointer(confine); + printlnState("[set pointer-confined post]", "warp-center: "+e.isShiftDown()); + if( e.isShiftDown() ) { + setConfinedFixedCenter(confine); + } else if( !confine ) { + setConfinedFixedCenter(false); + } + } } ); + break; + case KeyEvent.VK_M: + e.setConsumed(true); + glWindow.invokeOnNewThread(null, false, new Runnable() { + public void run() { + // none: max-v + // alt: max-h + // shift: max-hv + // ctrl: max-off + final boolean horz, vert; + if( e.isControlDown() ) { + horz = false; + vert = false; + } else if( e.isShiftDown() ) { + final boolean bothMax = glWindow.isMaximizedHorz() && glWindow.isMaximizedVert(); + horz = !bothMax; + vert = !bothMax; + } else if( !e.isAltDown() ) { + horz = glWindow.isMaximizedHorz(); + vert = !glWindow.isMaximizedVert(); + } else if( e.isAltDown() ) { + horz = !glWindow.isMaximizedHorz(); + vert = glWindow.isMaximizedVert(); + } else { + vert = glWindow.isMaximizedVert(); + horz = glWindow.isMaximizedHorz(); + } + printlnState("[set maximize pre]", "max[vert "+vert+", horz "+horz+"]"); + glWindow.setMaximized(horz, vert); + printlnState("[set maximize post]", "max[vert "+vert+", horz "+horz+"]"); + } } ); + break; + case KeyEvent.VK_Q: + if( quitAdapterEnabled && 0 == e.getModifiers() ) { + System.err.println("QUIT Key "+Thread.currentThread()); + quitAdapterShouldQuit = true; + } + break; + case KeyEvent.VK_P: + e.setConsumed(true); + glWindow.invokeOnNewThread(null, false, new Runnable() { + public void run() { + printlnState("[set position pre]"); + glWindow.setPosition(100, 100); + printlnState("[set position post]"); + } } ); + break; + case KeyEvent.VK_R: + e.setConsumed(true); + glWindow.invokeOnNewThread(null, false, new Runnable() { + public void run() { + printlnState("[set resizable pre]"); + glWindow.setResizable(!glWindow.isResizable()); + printlnState("[set resizable post]"); + } } ); + break; + case KeyEvent.VK_S: + e.setConsumed(true); + glWindow.invokeOnNewThread(null, false, new Runnable() { + public void run() { + printlnState("[set sticky pre]"); + glWindow.setSticky(!glWindow.isSticky()); + printlnState("[set sticky post]"); + } } ); + break; + case KeyEvent.VK_V: + e.setConsumed(true); + if( e.isControlDown() ) { + glWindow.invoke(false, new GLRunnable() { + @Override + public boolean run(final GLAutoDrawable drawable) { + final GL gl = drawable.getGL(); + final int _i = gl.getSwapInterval(); + final int i; + switch(_i) { + case 0: i = -1; break; + case -1: i = 1; break; + case 1: i = 0; break; + default: i = 1; break; + } + gl.setSwapInterval(i); + + final GLAnimatorControl a = drawable.getAnimator(); + if( null != a ) { + a.resetFPSCounter(); + } + if(drawable instanceof FPSCounter) { + ((FPSCounter)drawable).resetFPSCounter(); + } + System.err.println("Swap Interval: "+_i+" -> "+i+" -> "+gl.getSwapInterval()); + return true; + } + }); + } else { + glWindow.invokeOnNewThread(null, false, new Runnable() { + public void run() { + final boolean wasVisible = glWindow.isVisible(); + { + printlnState("[set visible pre]"); + glWindow.setVisible(!wasVisible); + printlnState("[set visible post]"); + } + if( wasVisible && !e.isControlDown() ) { + try { + java.lang.Thread.sleep(5000); + } catch (final InterruptedException e) { + e.printStackTrace(); + } + printlnState("[reset visible pre]"); + glWindow.setVisible(true); + printlnState("[reset visible post]"); + } + } } ); + } + break; + case KeyEvent.VK_W: + e.setConsumed(true); + glWindow.invokeOnNewThread(null, false, new Runnable() { + public void run() { + printlnState("[set pointer-pos pre]"); + glWindow.warpPointer(glWindow.getSurfaceWidth()/2, glWindow.getSurfaceHeight()/2); + printlnState("[set pointer-pos post]"); + } } ); + break; + case KeyEvent.VK_X: + e.setConsumed(true); + final float[] hadSurfacePixelScale = glWindow.getCurrentSurfaceScale(new float[2]); + final float[] reqSurfacePixelScale; + if( hadSurfacePixelScale[0] == ScalableSurface.IDENTITY_PIXELSCALE ) { + reqSurfacePixelScale = new float[] { ScalableSurface.AUTOMAX_PIXELSCALE, ScalableSurface.AUTOMAX_PIXELSCALE }; + } else { + reqSurfacePixelScale = new float[] { ScalableSurface.IDENTITY_PIXELSCALE, ScalableSurface.IDENTITY_PIXELSCALE }; + } + System.err.println("[set PixelScale pre]: had "+hadSurfacePixelScale[0]+"x"+hadSurfacePixelScale[1]+" -> req "+reqSurfacePixelScale[0]+"x"+reqSurfacePixelScale[1]); + glWindow.setSurfaceScale(reqSurfacePixelScale); + final float[] valReqSurfacePixelScale = glWindow.getRequestedSurfaceScale(new float[2]); + final float[] hasSurfacePixelScale1 = glWindow.getCurrentSurfaceScale(new float[2]); + System.err.println("[set PixelScale post]: "+hadSurfacePixelScale[0]+"x"+hadSurfacePixelScale[1]+" (had) -> "+ + reqSurfacePixelScale[0]+"x"+reqSurfacePixelScale[1]+" (req) -> "+ + valReqSurfacePixelScale[0]+"x"+valReqSurfacePixelScale[1]+" (val) -> "+ + hasSurfacePixelScale1[0]+"x"+hasSurfacePixelScale1[1]+" (has)"); + setTitle(); + } + } + @Override + public void keyReleased(final KeyEvent e) { } + + public void setConfinedFixedCenter(final boolean v) { + confinedFixedCenter = v; + } + @Override + public void mouseMoved(final MouseEvent e) { + if( e.isConfined() ) { + mouseCenterWarp(e); + } + } + @Override + public void mouseDragged(final MouseEvent e) { + if( e.isConfined() ) { + mouseCenterWarp(e); + } + } + @Override + public void mouseClicked(final MouseEvent e) { + if(e.getClickCount() == 2 && e.getPointerCount() == 1) { + glWindow.setFullscreen(!glWindow.isFullscreen()); + System.err.println("setFullscreen: "+glWindow.isFullscreen()); + } + } + private void mouseCenterWarp(final MouseEvent e) { + if(e.isConfined() && confinedFixedCenter ) { + final int x=glWindow.getSurfaceWidth()/2; + final int y=glWindow.getSurfaceHeight()/2; + glWindow.warpPointer(x, y); + } + } + @Override + public void mouseEntered(final MouseEvent e) {} + @Override + public void mouseExited(final MouseEvent e) {} + @Override + public void mousePressed(final MouseEvent e) {} + @Override + public void mouseReleased(final MouseEvent e) {} + @Override + public void mouseWheelMoved(final MouseEvent e) {} + + ///////////////////////////////////////////////////////////// + + private boolean quitAdapterShouldQuit = false; + private boolean quitAdapterEnabled = false; + private boolean quitAdapterEnabled2 = true; + + protected void quitAdapterOff() { + quitAdapterEnabled2 = false; + } + protected void quitAdapterOn() { + clearQuitAdapter(); + quitAdapterEnabled2 = true; + } + public void quitAdapterEnable(final boolean v) { quitAdapterEnabled = v; } + public void clearQuitAdapter() { quitAdapterShouldQuit = false; } + public boolean shouldQuit() { return quitAdapterShouldQuit; } + public void doQuit() { quitAdapterShouldQuit=true; } + + public void windowDestroyNotify(final WindowEvent e) { + if( quitAdapterEnabled && quitAdapterEnabled2 ) { + System.err.println("QUIT Window "+Thread.currentThread()); + quitAdapterShouldQuit = true; + } + } + + ///////////////////////////////////////////////////////////// + + public void setTitle() { + setTitle(glWindow); + } + public static void setTitle(final GLWindow win) { + final CapabilitiesImmutable chosenCaps = win.getChosenCapabilities(); + final CapabilitiesImmutable reqCaps = win.getRequestedCapabilities(); + final CapabilitiesImmutable caps = null != chosenCaps ? chosenCaps : reqCaps; + final String capsA = caps.isBackgroundOpaque() ? "opaque" : "transl"; + final float[] sDPI = win.getPixelsPerMM(new float[2]); + sDPI[0] *= 25.4f; + sDPI[1] *= 25.4f; + win.setTitle("GLWindow["+capsA+"], win: "+win.getBounds()+", pix: "+win.getSurfaceWidth()+"x"+win.getSurfaceHeight()+", sDPI "+sDPI[0]+" x "+sDPI[1]); + } + + public static PointerIcon[] createPointerIcons(final GLWindow glWindow) { + final PointerIcon[] pointerIcons = { null, null, null, null, null }; + { + final Display disp = glWindow.getScreen().getDisplay(); + disp.createNative(); + int idx = 0; + { + PointerIcon _pointerIcon = null; + final IOUtil.ClassResources res = new IOUtil.ClassResources(glWindow.getClass(), new String[] { "newt/data/cross-grey-alpha-16x16.png" } ); + try { + _pointerIcon = disp.createPointerIcon(res, 8, 8); + System.err.printf("Create PointerIcon #%02d: %s%n", idx, _pointerIcon.toString()); + } catch (final Exception e) { + e.printStackTrace(); + } + pointerIcons[idx] = _pointerIcon; + } + idx++; + { + PointerIcon _pointerIcon = null; + final IOUtil.ClassResources res = new IOUtil.ClassResources(glWindow.getClass(), new String[] { "newt/data/pointer-grey-alpha-16x24.png" } ); + try { + _pointerIcon = disp.createPointerIcon(res, 0, 0); + System.err.printf("Create PointerIcon #%02d: %s%n", idx, _pointerIcon.toString()); + } catch (final Exception e) { + e.printStackTrace(); + } + pointerIcons[idx] = _pointerIcon; + } + idx++; + { + PointerIcon _pointerIcon = null; + final IOUtil.ClassResources res = new IOUtil.ClassResources(glWindow.getClass(), new String[] { "arrow-red-alpha-64x64.png" } ); + try { + _pointerIcon = disp.createPointerIcon(res, 0, 0); + System.err.printf("Create PointerIcon #%02d: %s%n", idx, _pointerIcon.toString()); + } catch (final Exception e) { + e.printStackTrace(); + } + pointerIcons[idx] = _pointerIcon; + } + idx++; + { + PointerIcon _pointerIcon = null; + final IOUtil.ClassResources res = new IOUtil.ClassResources(glWindow.getClass(), new String[] { "arrow-blue-alpha-64x64.png" } ); + try { + _pointerIcon = disp.createPointerIcon(res, 0, 0); + System.err.printf("Create PointerIcon #%02d: %s%n", idx, _pointerIcon.toString()); + } catch (final Exception e) { + e.printStackTrace(); + } + pointerIcons[idx] = _pointerIcon; + } + idx++; + if( PNGIcon.isAvailable() ) { + PointerIcon _pointerIcon = null; + final IOUtil.ClassResources res = new IOUtil.ClassResources(glWindow.getClass(), new String[] { "jogamp-pointer-64x64.png" } ); + try { + final URLConnection urlConn = res.resolve(0); + final PNGPixelRect image = PNGPixelRect.read(urlConn.getInputStream(), null, false /* directBuffer */, 0 /* destMinStrideInBytes */, false /* destIsGLOriented */); + System.err.printf("Create PointerIcon #%02d: %s%n", idx, image.toString()); + _pointerIcon = disp.createPointerIcon(image, 32, 0); + System.err.printf("Create PointerIcon #%02d: %s%n", idx, _pointerIcon.toString()); + } catch (final Exception e) { + e.printStackTrace(); + } + pointerIcons[idx] = _pointerIcon; + } + idx++; + } + return pointerIcons; + } +}
\ No newline at end of file diff --git a/src/newt/classes/com/jogamp/newt/util/MainThread.java b/src/newt/classes/com/jogamp/newt/util/MainThread.java index 8bf4bc20f..05df63794 100644 --- a/src/newt/classes/com/jogamp/newt/util/MainThread.java +++ b/src/newt/classes/com/jogamp/newt/util/MainThread.java @@ -45,6 +45,7 @@ import java.util.List; import com.jogamp.nativewindow.NativeWindowFactory; import com.jogamp.common.os.Platform; +import com.jogamp.common.util.InterruptSource; import com.jogamp.common.util.PropertyAccess; import com.jogamp.common.util.ReflectionUtil; @@ -171,15 +172,14 @@ public class MainThread { return res; } - static class UserApp extends Thread { + static class UserApp extends InterruptSource.Thread { private final String mainClassNameShort; private final String mainClassName; private final String[] mainClassArgs; private final Method mainClassMain; - private List<Thread> nonDaemonThreadsAtStart; + private List<java.lang.Thread> nonDaemonThreadsAtStart; public UserApp(final String mainClassName, final String[] mainClassArgs) throws SecurityException, NoSuchMethodException, ClassNotFoundException { - super(); this.mainClassName=mainClassName; this.mainClassArgs=mainClassArgs; @@ -200,10 +200,10 @@ public class MainThread { @Override public void run() { nonDaemonThreadsAtStart = getNonDaemonThreads(); - if(DEBUG) System.err.println("MainAction.run(): "+Thread.currentThread().getName()+" start, nonDaemonThreadsAtStart "+nonDaemonThreadsAtStart); + if(DEBUG) System.err.println("MainAction.run(): "+java.lang.Thread.currentThread().getName()+" start, nonDaemonThreadsAtStart "+nonDaemonThreadsAtStart); // start user app .. try { - if(DEBUG) System.err.println("MainAction.run(): "+Thread.currentThread().getName()+" invoke "+mainClassName); + if(DEBUG) System.err.println("MainAction.run(): "+java.lang.Thread.currentThread().getName()+" invoke "+mainClassName); mainClassMain.invoke(null, new Object[] { mainClassArgs } ); } catch (final InvocationTargetException ite) { ite.getTargetException().printStackTrace(); @@ -219,30 +219,30 @@ public class MainThread { while( 0 < ( ndtr = getNonDaemonThreadCount(nonDaemonThreadsAtStart) ) ) { if(DEBUG) System.err.println("MainAction.run(): post user app, non daemon threads alive: "+ndtr); try { - Thread.sleep(1000); + java.lang.Thread.sleep(1000); } catch (final InterruptedException e) { e.printStackTrace(); } } - if(DEBUG) System.err.println("MainAction.run(): "+Thread.currentThread().getName()+" user app fin: "+ndtr); + if(DEBUG) System.err.println("MainAction.run(): "+java.lang.Thread.currentThread().getName()+" user app fin: "+ndtr); } if ( useMainThread ) { if(isMacOSX) { try { if(DEBUG) { - System.err.println("MainAction.main(): "+Thread.currentThread()+" MainAction fin - stopNSApp.0"); + System.err.println("MainAction.main(): "+java.lang.Thread.currentThread()+" MainAction fin - stopNSApp.0"); } ReflectionUtil.callStaticMethod(MACOSXDisplayClassName, "stopNSApplication", null, null, MainThread.class.getClassLoader()); if(DEBUG) { - System.err.println("MainAction.main(): "+Thread.currentThread()+" MainAction fin - stopNSApp.X"); + System.err.println("MainAction.main(): "+java.lang.Thread.currentThread()+" MainAction fin - stopNSApp.X"); } } catch (final Exception e) { e.printStackTrace(); } } else { - if(DEBUG) System.err.println("MainAction.run(): "+Thread.currentThread().getName()+" MainAction fin - System.exit(0)"); + if(DEBUG) System.err.println("MainAction.run(): "+java.lang.Thread.currentThread().getName()+" MainAction fin - System.exit(0)"); System.exit(0); } } diff --git a/src/newt/classes/com/jogamp/newt/util/applet/JOGLNewtAppletBase.java b/src/newt/classes/com/jogamp/newt/util/applet/JOGLNewtAppletBase.java index c2cf64da2..e02e02013 100644 --- a/src/newt/classes/com/jogamp/newt/util/applet/JOGLNewtAppletBase.java +++ b/src/newt/classes/com/jogamp/newt/util/applet/JOGLNewtAppletBase.java @@ -33,7 +33,6 @@ import java.security.PrivilegedAction; import com.jogamp.nativewindow.NativeWindow; import com.jogamp.nativewindow.WindowClosingProtocol.WindowClosingMode; -import com.jogamp.nativewindow.util.InsetsImmutable; import com.jogamp.opengl.FPSCounter; import com.jogamp.opengl.GL; import com.jogamp.opengl.GLAutoDrawable; @@ -43,16 +42,17 @@ import com.jogamp.opengl.GLPipelineFactory; import jogamp.newt.Debug; import com.jogamp.common.util.IOUtil; +import com.jogamp.common.util.InterruptSource; import com.jogamp.newt.Display; import com.jogamp.newt.Window; import com.jogamp.newt.Display.PointerIcon; -import com.jogamp.newt.event.KeyEvent; import com.jogamp.newt.event.KeyListener; import com.jogamp.newt.event.MouseListener; import com.jogamp.newt.event.WindowAdapter; import com.jogamp.newt.event.WindowEvent; import com.jogamp.newt.event.WindowListener; import com.jogamp.newt.opengl.GLWindow; +import com.jogamp.newt.opengl.util.NEWTDemoListener; import com.jogamp.opengl.util.Animator; import com.jogamp.opengl.util.AnimatorBase; @@ -60,7 +60,7 @@ import com.jogamp.opengl.util.AnimatorBase; /** Shows how to deploy an applet using JOGL. This demo must be referenced from a web page via an <applet> tag. */ -public class JOGLNewtAppletBase implements KeyListener, GLEventListener { +public class JOGLNewtAppletBase implements GLEventListener { public static final boolean DEBUG = Debug.debug("Applet"); String glEventListenerClazzName; @@ -194,7 +194,9 @@ public class JOGLNewtAppletBase implements KeyListener, GLEventListener { } if(!noDefaultKeyListener) { - glWindow.addKeyListener(this); + final NEWTDemoListener newtDemoListener = new NEWTDemoListener(glWindow); + glWindow.addKeyListener(newtDemoListener); + glWindow.addMouseListener(newtDemoListener); } glWindow.setUpdateFPSFrames(FPSCounter.DEFAULT_FRAMES_PER_INTERVAL, System.err); @@ -220,7 +222,7 @@ public class JOGLNewtAppletBase implements KeyListener, GLEventListener { null == glWindow.getParent() && null != parentWin && 0 != parentWin.getWindowHandle() ) { // we may be called directly by the native EDT - new Thread(new Runnable() { + new InterruptSource.Thread(null, new Runnable() { @Override public void run() { if( glWindow.isNativeValid() && null != parentWin && 0 != parentWin.getWindowHandle() ) { @@ -303,86 +305,5 @@ public class JOGLNewtAppletBase implements KeyListener, GLEventListener { public void dispose(final GLAutoDrawable drawable) { } - // *********************************************************************************** - // *********************************************************************************** - // *********************************************************************************** - - @Override - public void keyPressed(final KeyEvent e) { - if( !e.isPrintableKey() || e.isAutoRepeat() ) { - return; - } - if(e.getKeyChar()=='d') { - new Thread() { - public void run() { - glWindow.setUndecorated(!glWindow.isUndecorated()); - } }.start(); - } if(e.getKeyChar()=='f') { - new Thread() { - public void run() { - glWindow.setFullscreen(!glWindow.isFullscreen()); - } }.start(); - } else if(e.getKeyChar()=='a') { - new Thread() { - public void run() { - glWindow.setAlwaysOnTop(!glWindow.isAlwaysOnTop()); - } }.start(); - } else if(e.getKeyChar()=='r' && null!=parentWin) { - new Thread() { - public void run() { - if(null == glWindow.getParent()) { - glWindow.reparentWindow(parentWin, -1, -1, 0 /* hints */); - } else { - final InsetsImmutable insets = glWindow.getInsets(); - final int x, y; - if ( 0 >= insets.getTopHeight() ) { - // fail safe .. - x = 32; - y = 32; - } else { - x = insets.getLeftWidth(); - y = insets.getTopHeight(); - } - glWindow.reparentWindow(null, x, y, 0 /* hints */); - glWindow.setDefaultCloseOperation( glClosable ? WindowClosingMode.DISPOSE_ON_CLOSE : WindowClosingMode.DO_NOTHING_ON_CLOSE ); - } - } }.start(); - } else if(e.getKeyChar()=='c') { - new Thread() { - public void run() { - System.err.println("[set pointer-icon pre]"); - final PointerIcon currentPI = glWindow.getPointerIcon(); - glWindow.setPointerIcon( currentPI == pointerIconTest ? null : pointerIconTest); - System.err.println("[set pointer-icon post] "+currentPI+" -> "+glWindow.getPointerIcon()); - } }.start(); - } else if(e.getKeyChar()=='i') { - new Thread() { - public void run() { - System.err.println("[set mouse visible pre]: "+glWindow.isPointerVisible()); - glWindow.setPointerVisible(!glWindow.isPointerVisible()); - System.err.println("[set mouse visible post]: "+glWindow.isPointerVisible()); - } }.start(); - } else if(e.getKeyChar()=='j') { - new Thread() { - public void run() { - final Thread t = glWindow.setExclusiveContextThread(null); - System.err.println("[set mouse confined pre]: "+glWindow.isPointerConfined()); - glWindow.confinePointer(!glWindow.isPointerConfined()); - System.err.println("[set mouse confined post]: "+glWindow.isPointerConfined()); - glWindow.setExclusiveContextThread(t); - } }.start(); - } else if(e.getKeyChar()=='w') { - new Thread() { - public void run() { - System.err.println("[set mouse pos pre]"); - glWindow.warpPointer(glWindow.getSurfaceWidth()/2, glWindow.getSurfaceHeight()/2); - System.err.println("[set mouse pos post]"); - } }.start(); - } - } - - @Override - public void keyReleased(final KeyEvent e) { - } } diff --git a/src/newt/classes/jogamp/newt/DefaultEDTUtil.java b/src/newt/classes/jogamp/newt/DefaultEDTUtil.java index bf46ce609..ff713410b 100644 --- a/src/newt/classes/jogamp/newt/DefaultEDTUtil.java +++ b/src/newt/classes/jogamp/newt/DefaultEDTUtil.java @@ -44,6 +44,8 @@ import com.jogamp.nativewindow.NativeWindowException; import jogamp.common.util.locks.LockDebugUtil; import com.jogamp.common.ExceptionUtils; +import com.jogamp.common.util.InterruptSource; +import com.jogamp.common.util.InterruptedRuntimeException; import com.jogamp.common.util.RunnableTask; import com.jogamp.common.util.locks.Lock; import com.jogamp.newt.util.EDTUtil; @@ -68,7 +70,7 @@ public class DefaultEDTUtil implements EDTUtil { this.threadGroup = tg; this.name=Thread.currentThread().getName()+"-"+name+"-EDT-"; this.dispatchMessages=dispatchMessages; - this.edt = new NEDT(threadGroup, name); + this.edt = new NEDT(threadGroup, this.name); this.edt.setDaemon(true); // don't stop JVM from shutdown .. } @@ -169,8 +171,7 @@ public class DefaultEDTUtil implements EDTUtil { }; private final boolean invokeImpl(boolean wait, Runnable task, final boolean stop, final boolean provokeError) { - Throwable throwable = null; - RunnableTask rTask = null; + final RunnableTask rTask; final Object rTaskLock = new Object(); synchronized(rTaskLock) { // lock the optional task execution synchronized(edtLock) { // lock the EDT status @@ -187,6 +188,7 @@ public class DefaultEDTUtil implements EDTUtil { task.run(); } wait = false; // running in same thread (EDT) -> no wait + rTask = null; if( stop ) { edt.shouldStop = true; if( edt.tasks.size()>0 ) { @@ -230,18 +232,19 @@ public class DefaultEDTUtil implements EDTUtil { } } else { wait = false; + rTask = null; } } } if( wait ) { try { - rTaskLock.wait(); // free lock, allow execution of rTask + while( rTask.isInQueue() ) { + rTaskLock.wait(); // free lock, allow execution of rTask + } } catch (final InterruptedException ie) { - throwable = ie; - } - if(null==throwable) { - throwable = rTask.getThrowable(); + throw new InterruptedRuntimeException(ie); } + final Throwable throwable = rTask.getThrowable(); if(null!=throwable) { if(throwable instanceof NativeWindowException) { throw (NativeWindowException)throwable; @@ -268,13 +271,13 @@ public class DefaultEDTUtil implements EDTUtil { return false; } synchronized(_edt.tasks) { - while(_edt.isRunning && _edt.tasks.size()>0) { - try { + try { + while(_edt.isRunning && _edt.tasks.size()>0) { _edt.tasks.notifyAll(); _edt.tasks.wait(); - } catch (final InterruptedException e) { - e.printStackTrace(); } + } catch (final InterruptedException e) { + throw new InterruptedRuntimeException(e); } return true; } @@ -284,12 +287,12 @@ public class DefaultEDTUtil implements EDTUtil { final public boolean waitUntilStopped() { synchronized(edtLock) { if(edt.isRunning && edt != Thread.currentThread() ) { - while( edt.isRunning ) { - try { + try { + while( edt.isRunning ) { edtLock.wait(); - } catch (final InterruptedException e) { - e.printStackTrace(); } + } catch (final InterruptedException e) { + throw new InterruptedRuntimeException(e); } return true; } else { @@ -298,13 +301,13 @@ public class DefaultEDTUtil implements EDTUtil { } } - class NEDT extends Thread { + class NEDT extends InterruptSource.Thread { volatile boolean shouldStop = false; volatile boolean isRunning = false; final ArrayList<RunnableTask> tasks = new ArrayList<RunnableTask>(); // one shot tasks public NEDT(final ThreadGroup tg, final String name) { - super(tg, name); + super(tg, null, name); } final public boolean isRunning() { @@ -347,11 +350,11 @@ public class DefaultEDTUtil implements EDTUtil { RunnableTask task = null; synchronized(tasks) { // wait for tasks - if(!shouldStop && tasks.size()==0) { + if( !shouldStop && tasks.size()==0 ) { try { tasks.wait(pollPeriod); } catch (final InterruptedException e) { - e.printStackTrace(); + throw new InterruptedRuntimeException(e); } } // execute one task, if available @@ -375,7 +378,7 @@ public class DefaultEDTUtil implements EDTUtil { } if(!task.hasWaiter() && null != task.getThrowable()) { // at least dump stack-trace in case nobody waits for result - System.err.println("DefaultEDT.run(): Caught exception occured on thread "+Thread.currentThread().getName()+": "+task.toString()); + System.err.println("DefaultEDT.run(): Caught exception occured on thread "+java.lang.Thread.currentThread().getName()+": "+task.toString()); task.getThrowable().printStackTrace(); } } diff --git a/src/newt/classes/jogamp/newt/DisplayImpl.java b/src/newt/classes/jogamp/newt/DisplayImpl.java index cc1f3d8e0..c1cd6db32 100644 --- a/src/newt/classes/jogamp/newt/DisplayImpl.java +++ b/src/newt/classes/jogamp/newt/DisplayImpl.java @@ -37,6 +37,7 @@ package jogamp.newt; import com.jogamp.common.ExceptionUtils; import com.jogamp.common.nio.Buffers; import com.jogamp.common.util.IOUtil; +import com.jogamp.common.util.InterruptedRuntimeException; import com.jogamp.common.util.ReflectionUtil; import com.jogamp.newt.Display; import com.jogamp.newt.NewtFactory; @@ -697,8 +698,9 @@ public abstract class DisplayImpl extends Display { } else { throw re; } + } finally { + eventTask.notifyCaller(); } - eventTask.notifyCaller(); } @Override @@ -725,7 +727,10 @@ public abstract class DisplayImpl extends Display { } if( null != _events ) { for (int i=0; i < _events.size(); i++) { - dispatchMessage(_events.get(i)); + final NEWTEventTask e = _events.get(i); + if( !e.isDispatched() ) { + dispatchMessage(e); + } } } } @@ -759,11 +764,12 @@ public abstract class DisplayImpl extends Display { haveEvents = true; eventsLock.notifyAll(); } - if( wait ) { + while( wait && !eTask.isDispatched() ) { try { lock.wait(); } catch (final InterruptedException ie) { - throw new RuntimeException(ie); + eTask.setDispatched(); // Cancels NEWTEvent .. + throw new InterruptedRuntimeException(ie); } if( null != eTask.getException() ) { throw eTask.getException(); diff --git a/src/newt/classes/jogamp/newt/driver/awt/AWTEDTUtil.java b/src/newt/classes/jogamp/newt/driver/awt/AWTEDTUtil.java index 9d3121635..3d9073769 100644 --- a/src/newt/classes/jogamp/newt/driver/awt/AWTEDTUtil.java +++ b/src/newt/classes/jogamp/newt/driver/awt/AWTEDTUtil.java @@ -33,6 +33,8 @@ import java.awt.EventQueue; import com.jogamp.nativewindow.NativeWindowException; import com.jogamp.common.ExceptionUtils; +import com.jogamp.common.util.InterruptSource; +import com.jogamp.common.util.InterruptedRuntimeException; import com.jogamp.common.util.RunnableTask; import com.jogamp.common.util.awt.AWTEDTExecutor; import com.jogamp.newt.util.EDTUtil; @@ -54,7 +56,7 @@ public class AWTEDTUtil implements EDTUtil { this.threadGroup = tg; this.name=Thread.currentThread().getName()+"-"+name+"-EDT-"; this.dispatchMessages=dispatchMessages; - this.nedt = new NEDT(threadGroup, name); + this.nedt = new NEDT(threadGroup, this.name); this.nedt.setDaemon(true); // don't stop JVM from shutdown .. } @@ -132,8 +134,7 @@ public class AWTEDTUtil implements EDTUtil { } private final boolean invokeImpl(boolean wait, final Runnable task, final boolean stop) { - Throwable throwable = null; - RunnableTask rTask = null; + final RunnableTask rTask; final Object rTaskLock = new Object(); synchronized(rTaskLock) { // lock the optional task execution synchronized(edtLock) { // lock the EDT status @@ -150,6 +151,7 @@ public class AWTEDTUtil implements EDTUtil { task.run(); } wait = false; // running in same thread (EDT) -> no wait + rTask = null; if(stop) { nedt.shouldStop = true; } @@ -182,18 +184,21 @@ public class AWTEDTUtil implements EDTUtil { true /* always catch and report Exceptions, don't disturb EDT */, wait ? null : System.err); AWTEDTExecutor.singleton.invoke(false, rTask); + } else { + wait = false; + rTask = null; } } } if( wait ) { try { - rTaskLock.wait(); // free lock, allow execution of rTask + while( rTask.isInQueue() ) { + rTaskLock.wait(); // free lock, allow execution of rTask + } } catch (final InterruptedException ie) { - throwable = ie; - } - if(null==throwable) { - throwable = rTask.getThrowable(); + throw new InterruptedRuntimeException(ie); } + final Throwable throwable = rTask.getThrowable(); if(null!=throwable) { if(throwable instanceof NativeWindowException) { throw (NativeWindowException)throwable; @@ -227,12 +232,12 @@ public class AWTEDTUtil implements EDTUtil { final public boolean waitUntilStopped() { synchronized(edtLock) { if( nedt.isRunning && nedt != Thread.currentThread() && !EventQueue.isDispatchThread() ) { - while( nedt.isRunning ) { - try { + try { + while( nedt.isRunning ) { edtLock.wait(); - } catch (final InterruptedException e) { - e.printStackTrace(); } + } catch (final InterruptedException e) { + throw new InterruptedRuntimeException(e); } return true; } else { @@ -241,13 +246,13 @@ public class AWTEDTUtil implements EDTUtil { } } - class NEDT extends Thread { + class NEDT extends InterruptSource.Thread { volatile boolean shouldStop = false; volatile boolean isRunning = false; Object sync = new Object(); public NEDT(final ThreadGroup tg, final String name) { - super(tg, name); + super(tg, null, name); } final public boolean isRunning() { @@ -286,7 +291,7 @@ public class AWTEDTUtil implements EDTUtil { try { sync.wait(pollPeriod); } catch (final InterruptedException e) { - e.printStackTrace(); + throw new InterruptedRuntimeException(e); } } } diff --git a/src/newt/classes/jogamp/newt/driver/linux/LinuxEventDeviceTracker.java b/src/newt/classes/jogamp/newt/driver/linux/LinuxEventDeviceTracker.java index bc0bfaa16..c3b7bff36 100644 --- a/src/newt/classes/jogamp/newt/driver/linux/LinuxEventDeviceTracker.java +++ b/src/newt/classes/jogamp/newt/driver/linux/LinuxEventDeviceTracker.java @@ -43,6 +43,7 @@ import jogamp.newt.WindowImpl; import jogamp.newt.driver.KeyTracker; import com.jogamp.common.nio.StructAccessor; +import com.jogamp.common.util.InterruptSource; import com.jogamp.newt.Window; import com.jogamp.newt.event.InputEvent; import com.jogamp.newt.event.WindowEvent; @@ -63,7 +64,7 @@ public class LinuxEventDeviceTracker implements WindowListener, KeyTracker { static { ledt = new LinuxEventDeviceTracker(); - final Thread t = new Thread(ledt.eventDeviceManager, "NEWT-LinuxEventDeviceManager"); + final Thread t = new InterruptSource.Thread(null, ledt.eventDeviceManager, "NEWT-LinuxEventDeviceManager"); t.setDaemon(true); t.start(); } @@ -153,7 +154,7 @@ public class LinuxEventDeviceTracker implements WindowListener, KeyTracker { if(number<32&&number>=0) { if(eventDevicePollers[number]==null){ eventDevicePollers[number] = new EventDevicePoller(number); - final Thread t = new Thread(eventDevicePollers[number], "NEWT-LinuxEventDeviceTracker-event"+number); + final Thread t = new InterruptSource.Thread(null, eventDevicePollers[number], "NEWT-LinuxEventDeviceTracker-event"+number); t.setDaemon(true); t.start(); } else if(eventDevicePollers[number].stop) { diff --git a/src/newt/classes/jogamp/newt/driver/linux/LinuxMouseTracker.java b/src/newt/classes/jogamp/newt/driver/linux/LinuxMouseTracker.java index f40728da0..53bb9c3a5 100644 --- a/src/newt/classes/jogamp/newt/driver/linux/LinuxMouseTracker.java +++ b/src/newt/classes/jogamp/newt/driver/linux/LinuxMouseTracker.java @@ -37,6 +37,7 @@ import java.io.InputStream; import jogamp.newt.WindowImpl; import jogamp.newt.driver.MouseTracker; +import com.jogamp.common.util.InterruptSource; import com.jogamp.newt.Screen; import com.jogamp.newt.Window; import com.jogamp.newt.event.MouseEvent; @@ -55,7 +56,7 @@ public class LinuxMouseTracker implements WindowListener, MouseTracker { static { lmt = new LinuxMouseTracker(); - final Thread t = new Thread(lmt.mouseDevicePoller, "NEWT-LinuxMouseTracker"); + final Thread t = new InterruptSource.Thread(null, lmt.mouseDevicePoller, "NEWT-LinuxMouseTracker"); t.setDaemon(true); t.start(); } diff --git a/src/newt/classes/jogamp/newt/driver/macosx/WindowDriver.java b/src/newt/classes/jogamp/newt/driver/macosx/WindowDriver.java index a38ba4c13..2bbcdce38 100644 --- a/src/newt/classes/jogamp/newt/driver/macosx/WindowDriver.java +++ b/src/newt/classes/jogamp/newt/driver/macosx/WindowDriver.java @@ -34,6 +34,7 @@ package jogamp.newt.driver.macosx; +import com.jogamp.common.util.InterruptSource; import com.jogamp.nativewindow.AbstractGraphicsConfiguration; import com.jogamp.nativewindow.GraphicsConfigurationFactory; import com.jogamp.nativewindow.NativeWindow; @@ -378,7 +379,7 @@ public class WindowDriver extends WindowImpl implements MutableSurface, DriverCl } private void superSizeChangedOffThread(final boolean defer, final int newWidth, final int newHeight, final boolean force) { if( defer ) { - new Thread() { + new InterruptSource.Thread() { public void run() { WindowDriver.super.sizeChanged(false /* defer */, newWidth, newHeight, force); } }.start(); diff --git a/src/newt/classes/jogamp/newt/event/NEWTEventTask.java b/src/newt/classes/jogamp/newt/event/NEWTEventTask.java index 2bdab2796..260a1beb4 100644 --- a/src/newt/classes/jogamp/newt/event/NEWTEventTask.java +++ b/src/newt/classes/jogamp/newt/event/NEWTEventTask.java @@ -38,19 +38,27 @@ public class NEWTEventTask { private final NEWTEvent event; private final Object notifyObject; private RuntimeException exception; + private volatile boolean dispatched; public NEWTEventTask(final NEWTEvent event, final Object notifyObject) { this.event = event ; this.notifyObject = notifyObject ; this.exception = null; + this.dispatched = false; } public final NEWTEvent get() { return event; } public final void setException(final RuntimeException e) { exception = e; } public final RuntimeException getException() { return exception; } public final boolean isCallerWaiting() { return null != notifyObject; } + public final boolean isDispatched() { return dispatched; } + public final void setDispatched() { dispatched = true; } + /** + * Notifies caller after {@link #setDispatched()}. + */ public void notifyCaller() { + setDispatched(); if(null != notifyObject) { synchronized (notifyObject) { notifyObject.notifyAll(); diff --git a/src/newt/classes/jogamp/newt/swt/SWTEDTUtil.java b/src/newt/classes/jogamp/newt/swt/SWTEDTUtil.java index 9039b6083..9d2b41bbc 100644 --- a/src/newt/classes/jogamp/newt/swt/SWTEDTUtil.java +++ b/src/newt/classes/jogamp/newt/swt/SWTEDTUtil.java @@ -32,6 +32,8 @@ import com.jogamp.nativewindow.NativeWindowException; import jogamp.newt.Debug; import com.jogamp.common.ExceptionUtils; +import com.jogamp.common.util.InterruptSource; +import com.jogamp.common.util.InterruptedRuntimeException; import com.jogamp.common.util.RunnableTask; import com.jogamp.newt.util.EDTUtil; @@ -162,8 +164,7 @@ public class SWTEDTUtil implements EDTUtil { } private final boolean invokeImpl(boolean wait, final Runnable task, boolean stop) { - Throwable throwable = null; - RunnableTask rTask = null; + final RunnableTask rTask; final Object rTaskLock = new Object(); synchronized(rTaskLock) { // lock the optional task execution synchronized(edtLock) { // lock the EDT status @@ -184,6 +185,7 @@ public class SWTEDTUtil implements EDTUtil { task.run(); } wait = false; // running in same thread (EDT) -> no wait + rTask = null; if( stop ) { nedt.shouldStop = true; } @@ -225,18 +227,21 @@ public class SWTEDTUtil implements EDTUtil { true /* always catch and report Exceptions, don't disturb EDT */, wait ? null : System.err); swtDisplay.asyncExec(rTask); + } else { + wait = false; + rTask = null; } } } if( wait ) { try { - rTaskLock.wait(); // free lock, allow execution of rTask + while( rTask.isInQueue() ) { + rTaskLock.wait(); // free lock, allow execution of rTask + } } catch (final InterruptedException ie) { - throwable = ie; - } - if(null==throwable) { - throwable = rTask.getThrowable(); + throw new InterruptedRuntimeException(ie); } + final Throwable throwable = rTask.getThrowable(); if(null!=throwable) { if(throwable instanceof NativeWindowException) { throw (NativeWindowException)throwable; @@ -274,12 +279,12 @@ public class SWTEDTUtil implements EDTUtil { final Thread swtT = !swtDisplay.isDisposed() ? swtDisplay.getThread() : null; final boolean onSWTEDT = swtT == curT; if( nedt.isRunning && nedt != curT && !onSWTEDT ) { - while( nedt.isRunning ) { - try { + try { + while( nedt.isRunning ) { edtLock.wait(); - } catch (final InterruptedException e) { - e.printStackTrace(); } + } catch (final InterruptedException e) { + throw new InterruptedRuntimeException(e); } return true; } else { @@ -288,13 +293,13 @@ public class SWTEDTUtil implements EDTUtil { } } - class NEDT extends Thread { + class NEDT extends InterruptSource.Thread { volatile boolean shouldStop = false; volatile boolean isRunning = false; Object sync = new Object(); public NEDT(final ThreadGroup tg, final String name) { - super(tg, name); + super(tg, null, name); } final public boolean isRunning() { @@ -337,7 +342,7 @@ public class SWTEDTUtil implements EDTUtil { try { sync.wait(pollPeriod); } catch (final InterruptedException e) { - e.printStackTrace(); + throw new InterruptedRuntimeException(e); } } } |