diff options
author | Sven Gothel <[email protected]> | 2013-07-09 15:04:50 +0200 |
---|---|---|
committer | Sven Gothel <[email protected]> | 2013-07-09 15:04:50 +0200 |
commit | 453ccee8e3ce90956756d1582852b13f45cd2f38 (patch) | |
tree | 953a75b75fec41f0e77312a342976cd334928eae /src | |
parent | 433e3914324b90c910b018bb7d9d80e814c67123 (diff) |
NEWT EDTUtil: Exposed weakness of EDTUtil usage due to usage of WeakReference, i.e. higher retention of Display instances.
- WeakReference Change 99479bf3197cde8e89c5b499d135417863d521c7
- Refines commits:
feb352145af1643a57eaae99c0342e6f5e0f2a2e
dec4b02fe4b93028c85de6a56b6af79601042d6e
433e3914324b90c910b018bb7d9d80e814c67123
Reviews EDTUtil API and usage:
- less confusing / more determined EDTUtil API
- EDTUtil's thread shall only be reset and started when required (-> lazy)
- EDTUtil's instance in Display shall be handled thread safe w/o extra blocking
- EDTUtil's implementations (Default, SWT and AWT) shall be aligned / similar as much as possible
Further note: SWT's EDTUtil (NewtCanvasSWT) shall not use a reused Display instance due to it's
custom SWTEDTUtil. We may need to disable the ref. cache if custom EDTUtil (setEDTUtil)
is intended (used).
Diffstat (limited to 'src')
27 files changed, 431 insertions, 291 deletions
diff --git a/src/newt/classes/com/jogamp/newt/Display.java b/src/newt/classes/com/jogamp/newt/Display.java index 4f5df6c70..c618405c2 100644 --- a/src/newt/classes/com/jogamp/newt/Display.java +++ b/src/newt/classes/com/jogamp/newt/Display.java @@ -154,26 +154,25 @@ public abstract class Display { /** * Sets a new {@link EDTUtil} and returns the previous one. * <p> - * If <code>newEDTUtil</code> is <code>null</code>, + * If <code>usrEDTUtil</code> is <code>null</code>, * the device's default EDTUtil is created and used. * </p> * <p> - * If a previous one exists and it differs from the new one, - * it's being stopped, wait-until-idle and reset to allow a restart at a later time. + * If a previous one exists and it differs from <code>usrEDTUtil</code>, + * it's being stopped, wait-until-idle. * </p> * <p> - * If <code>newEDTUtil</code> is not null and equals the previous one, + * If <code>usrEDTUtil</code> is not null and equals the previous one, * no change is being made. * </p> - * <p> - * Note that <code>newEDTUtil</code> will be started by this method, - * if it is not running yet. - * </p> */ - public abstract EDTUtil setEDTUtil(EDTUtil newEDTUtil); + public abstract EDTUtil setEDTUtil(EDTUtil usrEDTUtil); public abstract EDTUtil getEDTUtil(); + /** + * @return true if EDT is running and not subject to be stopped, otherwise false. + */ public abstract boolean isEDTRunning(); public abstract void dispatchMessages(); diff --git a/src/newt/classes/com/jogamp/newt/swt/NewtCanvasSWT.java b/src/newt/classes/com/jogamp/newt/swt/NewtCanvasSWT.java index dbe7c0d98..47dfca0f3 100644 --- a/src/newt/classes/com/jogamp/newt/swt/NewtCanvasSWT.java +++ b/src/newt/classes/com/jogamp/newt/swt/NewtCanvasSWT.java @@ -345,7 +345,9 @@ public class NewtCanvasSWT extends Canvas implements WindowClosingProtocol { // set SWT EDT and start it { final Display newtDisplay = newtChild.getScreen().getDisplay(); - newtDisplay.setEDTUtil( new SWTEDTUtil(newtDisplay, getDisplay()) ); + final EDTUtil edtUtil = new SWTEDTUtil(newtDisplay, getDisplay()); + edtUtil.restart(); + newtDisplay.setEDTUtil( edtUtil ); } newtChild.setSize(w, h); diff --git a/src/newt/classes/com/jogamp/newt/util/EDTUtil.java b/src/newt/classes/com/jogamp/newt/util/EDTUtil.java index 75848785c..e86df2084 100644 --- a/src/newt/classes/com/jogamp/newt/util/EDTUtil.java +++ b/src/newt/classes/com/jogamp/newt/util/EDTUtil.java @@ -65,18 +65,19 @@ public interface EDTUtil { public void setPollPeriod(long ms); /** - * Resets the stopped EDT, i.e. prepares it for a restart via - * the next <code>invoke(..)</code> call. + * Starts or restarts the EDT. * <p> - * One must stop the EDT first via {@link #invokeStop(boolean, Runnable)} - * and wait until it's stopped via {@link #waitUntilStopped()}. + * If the EDT is running, it must be stopped first via {@link #invokeStop(boolean, Runnable)} + * and the caller should wait until it's stopped via {@link #waitUntilStopped()}. * </p> - * - * @see #invoke(boolean, java.lang.Runnable) + * + * @return true if EDT has been successfully restarted, otherwise false + * @throws IllegalStateException if EDT is running and not subject to be stopped, i.e. {@link #isRunning()} returns true + * * @see #invokeStop(boolean, java.lang.Runnable) - * @throws IllegalStateException if stop has not been issued, or EDT is still running (caller thread not being EDT or NEDT). + * @see #waitUntilStopped() */ - public void reset() throws IllegalStateException; + public boolean restart() throws IllegalStateException; /** * Returns true if the current thread is the event dispatch thread (EDT). @@ -111,7 +112,7 @@ public interface EDTUtil { public boolean isCurrentThreadEDTorNEDT(); /** - * @return True if EDT is running + * @return True if EDT is running and not subject to be stopped. */ public boolean isRunning(); @@ -129,27 +130,30 @@ public interface EDTUtil { * <li>All previous queued tasks will be finished.</li> * <li>No new tasks are allowed, an Exception is thrown.</li> * <li>Can be issued from within EDT, ie from within an enqueued task.</li> - * <li>{@link #reset()} may follow immediately, ie creating a new EDT</li> + * <li>{@link #restart()} may follow immediately, ie creating a new EDT</li> * </ul> * </p> + * @return true if <code>task</code> has been executed or queued for later execution, otherwise false */ - public void invokeStop(boolean wait, Runnable finalTask); + public boolean invokeStop(boolean wait, Runnable finalTask); /** - * Shall start the thread if not running, <code>task</code> maybe null for this purpose.<br> - * Append task to the EDT task queue.<br> - * Wait until execution is finished if <code>wait == true</code>.<br> + * Appends task to the EDT task queue if current thread is not EDT, + * otherwise execute task immediately. + * <p> + * Wait until execution is finished if <code>wait == true</code>. + * </p> * Can be issued from within EDT, ie from within an enqueued task.<br> - * - * @throws RuntimeException in case EDT is stopped and not {@link #reset()} + * @return true if <code>task</code> has been executed or queued for later execution, otherwise false */ - public void invoke(boolean wait, Runnable task); + public boolean invoke(boolean wait, Runnable task); /** * Wait until the EDT task queue is empty.<br> * The last task may still be in execution when this method returns. + * @return true if waited for idle, otherwise false, i.e. in case of current thread is EDT or NEDT */ - public void waitUntilIdle(); + public boolean waitUntilIdle(); /** * Wait until EDT task is stopped.<br> @@ -157,7 +161,8 @@ public interface EDTUtil { * <p> * If caller thread is EDT or NEDT, this call will not block. * </p> + * @return true if stopped, otherwise false, i.e. in case of current thread is EDT or NEDT */ - public void waitUntilStopped(); + public boolean waitUntilStopped(); } diff --git a/src/newt/classes/jogamp/newt/DefaultEDTUtil.java b/src/newt/classes/jogamp/newt/DefaultEDTUtil.java index ecd94c278..a229a0512 100644 --- a/src/newt/classes/jogamp/newt/DefaultEDTUtil.java +++ b/src/newt/classes/jogamp/newt/DefaultEDTUtil.java @@ -53,7 +53,7 @@ public class DefaultEDTUtil implements EDTUtil { private final ThreadGroup threadGroup; private final String name; private final Runnable dispatchMessages; - private EventDispatchThread edt = null; + private NEDT edt = null; private int start_iter=0; private static long pollPeriod = EDTUtil.defaultEDTPollPeriod; @@ -61,7 +61,7 @@ public class DefaultEDTUtil implements EDTUtil { this.threadGroup = tg; this.name=Thread.currentThread().getName()+"-"+name+"-EDT-"; this.dispatchMessages=dispatchMessages; - this.edt = new EventDispatchThread(threadGroup, name); + this.edt = new NEDT(threadGroup, name); this.edt.setDaemon(true); // don't stop JVM from shutdown .. } @@ -76,36 +76,34 @@ public class DefaultEDTUtil implements EDTUtil { } @Override - public final void reset() throws IllegalStateException { + public final boolean restart() throws IllegalStateException { synchronized(edtLock) { - if( isRunning() ) { - if( !edt.shouldStop ) { - throw new IllegalStateException("EDT stop not issued."); - } - throw new IllegalStateException("EDT still running"); + if( edt.isRunning() ) { + throw new IllegalStateException("EDT still running and not subject to stop. Curr "+Thread.currentThread().getName()+", EDT "+edt.getName()+", isRunning "+edt.isRunning+", shouldStop "+edt.shouldStop); } if(DEBUG) { if(edt.tasks.size()>0) { System.err.println(Thread.currentThread()+": Default-EDT reset, remaining tasks: "+edt.tasks.size()+" - "+edt); - // Thread.dumpStack(); } System.err.println(Thread.currentThread()+": Default-EDT reset - edt: "+edt); } - this.edt = new EventDispatchThread(threadGroup, name); - this.edt.setDaemon(true); // don't stop JVM from shutdown .. + if( edt.getState() != Thread.State.NEW ) { + edt = new NEDT(threadGroup, name); + edt.setDaemon(true); // don't stop JVM from shutdown .. + } + startImpl(); } + return invoke(true, nullTask); } private final void startImpl() { if(edt.isAlive()) { - throw new RuntimeException("Default-EDT Thread.isAlive(): true, isRunning: "+edt.isRunning()+", edt: "+edt+", tasks: "+edt.tasks.size()); + throw new RuntimeException("Default-EDT Thread.isAlive(): true, isRunning: "+edt.isRunning+", shouldStop "+edt.shouldStop+", edt: "+edt+", tasks: "+edt.tasks.size()); } start_iter++; edt.setName(name+start_iter); - edt.shouldStop = false; if(DEBUG) { System.err.println(Thread.currentThread()+": Default-EDT START - edt: "+edt); - // Thread.dumpStack(); } edt.start(); } @@ -131,13 +129,13 @@ public class DefaultEDTUtil implements EDTUtil { } @Override - public final void invokeStop(boolean wait, Runnable task) { - invokeImpl(wait, task, true); + public final boolean invokeStop(boolean wait, Runnable task) { + return invokeImpl(wait, task, true); } @Override - public final void invoke(boolean wait, Runnable task) { - invokeImpl(wait, task, false); + public final boolean invoke(boolean wait, Runnable task) { + return invokeImpl(wait, task, false); } private static Runnable nullTask = new Runnable() { @@ -145,28 +143,26 @@ public class DefaultEDTUtil implements EDTUtil { public void run() { } }; - private void invokeImpl(boolean wait, Runnable task, boolean stop) { + private final boolean invokeImpl(boolean wait, Runnable task, boolean stop) { Throwable throwable = null; RunnableTask rTask = null; - Object rTaskLock = new Object(); + final Object rTaskLock = new Object(); synchronized(rTaskLock) { // lock the optional task execution synchronized(edtLock) { // lock the EDT status if( edt.shouldStop ) { // drop task .. + System.err.println(Thread.currentThread()+": Warning: Default-EDT about (1) to stop, won't enqueue new task: "+edt); if(DEBUG) { - System.err.println(Thread.currentThread()+": Warning: Default-EDT about (1) to stop, won't enqueue new task: "+edt); Thread.dumpStack(); } - return; + return false; } - // System.err.println(Thread.currentThread()+" XXX stop: "+stop+", tasks: "+edt.tasks.size()+", task: "+task); - // Thread.dumpStack(); if( isCurrentThreadEDT() ) { if(null != task) { task.run(); } wait = false; // running in same thread (EDT) -> no wait - if(stop) { + if( stop ) { edt.shouldStop = true; if( edt.tasks.size()>0 ) { System.err.println(Thread.currentThread()+": Warning: Default-EDT about (2) to stop, task executed. Remaining tasks: "+edt.tasks.size()+" - "+edt); @@ -176,21 +172,19 @@ public class DefaultEDTUtil implements EDTUtil { } } } else { - if( !edt.isRunning() ) { - if( !stop ) { - startImpl(); - if( wait && null == task ) { - task = nullTask; // ensures wait until started + if( !edt.isRunning ) { + if( null != task ) { + if( stop ) { + System.err.println(Thread.currentThread()+": Warning: Default-EDT is about (3) to stop and stopped already, dropping task. Remaining tasks: "+edt.tasks.size()+" - "+edt); + } else { + System.err.println(Thread.currentThread()+": Warning: Default-EDT is not running, dropping task. NEDT "+edt); } - } else { - // drop task and don't wait - task = null; - System.err.println(Thread.currentThread()+": Warning: Default-EDT is about (3) to stop and stopped already, dropping task. Remaining tasks: "+edt.tasks.size()+" - "+edt); if(DEBUG) { Thread.dumpStack(); } } - } else if(stop && null == task) { + return false; + } else if( stop && null == task ) { task = nullTask; // ensures execution triggering stop } @@ -228,23 +222,26 @@ public class DefaultEDTUtil implements EDTUtil { throw new RuntimeException(throwable); } } - } - if(DEBUG && stop) { - System.err.println(Thread.currentThread()+": Default-EDT signal STOP X edt: "+edt); + if(DEBUG) { + if( stop) { + System.err.println(Thread.currentThread()+": Default-EDT signal STOP X edt: "+edt); + } + } + return true; } } @Override - final public void waitUntilIdle() { - final EventDispatchThread _edt; + final public boolean waitUntilIdle() { + final NEDT _edt; synchronized(edtLock) { _edt = edt; } - if(!_edt.isRunning() || _edt == Thread.currentThread()) { - return; + if(!_edt.isRunning || _edt == Thread.currentThread()) { + return false; } synchronized(_edt.tasks) { - while(_edt.isRunning() && _edt.tasks.size()>0) { + while(_edt.isRunning && _edt.tasks.size()>0) { try { _edt.tasks.notifyAll(); _edt.tasks.wait(); @@ -252,35 +249,39 @@ public class DefaultEDTUtil implements EDTUtil { e.printStackTrace(); } } + return true; } } @Override - final public void waitUntilStopped() { + final public boolean waitUntilStopped() { synchronized(edtLock) { - if(edt.isRunning() && edt != Thread.currentThread() ) { - while(edt.isRunning()) { + if(edt.isRunning && edt != Thread.currentThread() ) { + while( edt.isRunning ) { try { edtLock.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } + return true; + } else { + return false; } } } - class EventDispatchThread extends Thread { + class NEDT extends Thread { volatile boolean shouldStop = false; volatile boolean isRunning = false; ArrayList<RunnableTask> tasks = new ArrayList<RunnableTask>(); // one shot tasks - public EventDispatchThread(ThreadGroup tg, String name) { + public NEDT(ThreadGroup tg, String name) { super(tg, name); } final public boolean isRunning() { - return isRunning; + return isRunning && !shouldStop; } @Override @@ -290,11 +291,9 @@ public class DefaultEDTUtil implements EDTUtil { } private final void validateNoRecursiveLocksHold() { - if(Lock.DEBUG) { - if(LockDebugUtil.getRecursiveLockTrace().size()>0) { - LockDebugUtil.dumpRecursiveLockTrace(System.err); - throw new InternalError("XXX"); - } + if(LockDebugUtil.getRecursiveLockTrace().size()>0) { + LockDebugUtil.dumpRecursiveLockTrace(System.err); + throw new InternalError("XXX"); } } @@ -307,7 +306,9 @@ public class DefaultEDTUtil implements EDTUtil { if(DEBUG) { System.err.println(getName()+": Default-EDT run() START "+ getName()); } - validateNoRecursiveLocksHold(); + if(Lock.DEBUG) { + validateNoRecursiveLocksHold(); + } RuntimeException error = null; try { do { @@ -337,7 +338,9 @@ public class DefaultEDTUtil implements EDTUtil { } if(null!=task) { task.run(); - validateNoRecursiveLocksHold(); + if(Lock.DEBUG) { + validateNoRecursiveLocksHold(); + } if(!task.hasWaiter() && null != task.getThrowable()) { // at least dump stack-trace in case nobody waits for result System.err.println("DefaultEDT.run(): Catched exception occured on thread "+Thread.currentThread().getName()+": "+task.toString()); diff --git a/src/newt/classes/jogamp/newt/DisplayImpl.java b/src/newt/classes/jogamp/newt/DisplayImpl.java index 884ddac57..8f792b23c 100644 --- a/src/newt/classes/jogamp/newt/DisplayImpl.java +++ b/src/newt/classes/jogamp/newt/DisplayImpl.java @@ -84,7 +84,6 @@ public abstract class DisplayImpl extends Display { if(reuse) { final Display display0 = Display.getLastDisplayOf(type, name, -1, true /* shared only */); if(null != display0) { - display0.setEDTUtil(display0.getEDTUtil()); // ensures EDT is running if(DEBUG) { System.err.println("Display.create() REUSE: "+display0+" "+getThreadName()); } @@ -98,9 +97,9 @@ public abstract class DisplayImpl extends Display { display.id = serialno++; display.fqname = getFQName(display.type, display.name, display.id); display.hashCode = display.fqname.hashCode(); + display.setEDTUtil( display.edtUtil ); // device's default if EDT is used, or null Display.addDisplay2List(display); } - display.setEDTUtil(display.edtUtil); // device's default if EDT is used, or null - ensures EDT is running if(DEBUG) { System.err.println("Display.create() NEW: "+display+" "+getThreadName()); @@ -138,10 +137,10 @@ public abstract class DisplayImpl extends Display { } @Override - public synchronized final void createNative() + public synchronized final void createNative() throws NativeWindowException { - if(null==aDevice) { + if( null == aDevice ) { if(DEBUG) { System.err.println("Display.createNative() START ("+getThreadName()+", "+this+")"); } @@ -154,7 +153,7 @@ public abstract class DisplayImpl extends Display { } catch (Throwable t) { throw new NativeWindowException(t); } - if(null==aDevice) { + if( null == aDevice ) { throw new NativeWindowException("Display.createNative() failed to instanciate an AbstractGraphicsDevice"); } synchronized(displayList) { @@ -180,25 +179,23 @@ public abstract class DisplayImpl extends Display { } @Override - public EDTUtil setEDTUtil(EDTUtil newEDTUtil) { + public synchronized EDTUtil setEDTUtil(final EDTUtil usrEDTUtil) { final EDTUtil oldEDTUtil = edtUtil; - if(null == newEDTUtil) { - if(DEBUG) { - System.err.println("Display.setEDTUtil(default): "+oldEDTUtil+" -> "+newEDTUtil); + final EDTUtil newEDTUtil; + if( null != usrEDTUtil && usrEDTUtil == oldEDTUtil ) { + if( DEBUG ) { + System.err.println("Display.setEDTUtil: "+usrEDTUtil+" - keep!"); } - edtUtil = createEDTUtil(); - } else if( newEDTUtil != edtUtil ) { + newEDTUtil = oldEDTUtil; + } else { if(DEBUG) { - System.err.println("Display.setEDTUtil(custom): "+oldEDTUtil+" -> "+newEDTUtil); + final String msg = ( null == usrEDTUtil ) ? "default" : "custom"; + System.err.println("Display.setEDTUtil("+msg+"): "+oldEDTUtil+" -> "+usrEDTUtil); } - removeEDT( null ); - edtUtil = newEDTUtil; - } else if( DEBUG ) { - System.err.println("Display.setEDTUtil: "+newEDTUtil+" - keep!"); - } - if( !edtUtil.isRunning() ) { // start EDT if not running yet - edtUtil.invoke(true, null); + stopEDT( oldEDTUtil, null ); + newEDTUtil = ( null == usrEDTUtil ) ? createEDTUtil() : usrEDTUtil; } + edtUtil = newEDTUtil; return oldEDTUtil; } @@ -207,29 +204,61 @@ public abstract class DisplayImpl extends Display { return edtUtil; } - private void removeEDT(final Runnable task) { - if(null!=edtUtil) { - edtUtil.invokeStop(true, task); - // ready for restart .. + private static void stopEDT(final EDTUtil edtUtil, final Runnable task) { + if( null != edtUtil ) { + if( edtUtil.isRunning() ) { + final boolean res = edtUtil.invokeStop(true, task); + if( DEBUG ) { + if ( !res ) { + System.err.println("Warning: invokeStop() failed"); + Thread.dumpStack(); + } + } + } edtUtil.waitUntilStopped(); - edtUtil.reset(); - } else { + // ready for restart .. + } else if( null != task ) { task.run(); } } public void runOnEDTIfAvail(boolean wait, final Runnable task) { - if( null!=edtUtil && !edtUtil.isCurrentThreadEDT()) { - edtUtil.invoke(wait, task); + final EDTUtil _edtUtil = edtUtil; + if( null != _edtUtil && !_edtUtil.isCurrentThreadEDT() ) { + if( !_edtUtil.isRunning() ) { // start EDT if not running yet + synchronized( this ) { + if( !_edtUtil.isRunning() ) { // // volatile dbl-checked-locking OK + _edtUtil.restart(); + if( DEBUG ) { + System.err.println("Info: EDT started "+Thread.currentThread().getName()+", "+this); + Thread.dumpStack(); + } + } + } + } + if( !_edtUtil.invoke(wait, task) ) { + if( DEBUG ) { + System.err.println("Warning: invoke(wait "+wait+", ..) on EDT failed .. invoke on current thread "+Thread.currentThread().getName()); + Thread.dumpStack(); + } + task.run(); + } } else { task.run(); } } public boolean validateEDT() { - if(0==refCount && null==aDevice && null != edtUtil && edtUtil.isRunning()) { - removeEDT( null ); - return true; + if( 0==refCount && null == aDevice ) { + final EDTUtil _edtUtil = edtUtil; + if( null != _edtUtil && _edtUtil.isRunning() ) { + synchronized( this ) { + if( null != edtUtil && edtUtil.isRunning() ) { // // volatile dbl-checked-locking OK + stopEDT( edtUtil, null ); + return true; + } + } + } } return false; } @@ -246,17 +275,18 @@ public abstract class DisplayImpl extends Display { if(DEBUG) { System.err.println("Display.destroy(): "+this+", active "+displaysActive+" "+getThreadName()); } - } + } final DisplayImpl f_dpy = this; - removeEDT( new Runnable() { // blocks! + final AbstractGraphicsDevice f_aDevice = aDevice; + aDevice = null; + refCount=0; + stopEDT( edtUtil, new Runnable() { // blocks! public void run() { - if ( null != aDevice ) { - f_dpy.closeNativeImpl(); + if ( null != f_aDevice ) { + f_dpy.closeNativeImpl(f_aDevice); } } } ); - aDevice = null; - refCount=0; if(DEBUG) { dumpDisplayList("Display.destroy("+getFQName()+") END"); } @@ -277,25 +307,28 @@ public abstract class DisplayImpl extends Display { if(0 < displaysActive) { displaysActive--; } + final EDTUtil edtUtil = d.getEDTUtil(); + final AbstractGraphicsDevice f_aDevice = d.aDevice; + d.aDevice = null; + d.refCount=0; final Runnable closeNativeTask = new Runnable() { public void run() { if ( null != d.getGraphicsDevice() ) { - d.closeNativeImpl(); + d.closeNativeImpl(f_aDevice); } } }; - final EDTUtil edtUtil = d.getEDTUtil(); if(null != edtUtil) { final long coopSleep = edtUtil.getPollPeriod() * 2; - edtUtil.invokeStop(false, closeNativeTask); // don't block + if( edtUtil.isRunning() ) { + edtUtil.invokeStop(false, closeNativeTask); // don't block + } try { Thread.sleep( coopSleep < 50 ? coopSleep : 50 ); } catch (InterruptedException e) { } } else { closeNativeTask.run(); } - d.aDevice = null; - d.refCount=0; } } } @@ -331,7 +364,7 @@ public abstract class DisplayImpl extends Display { } protected abstract void createNativeImpl(); - protected abstract void closeNativeImpl(); + protected abstract void closeNativeImpl(AbstractGraphicsDevice aDevice); @Override public final int getId() { @@ -399,15 +432,18 @@ public abstract class DisplayImpl extends Display { @Override public boolean isEDTRunning() { - if(null!=edtUtil) { - return edtUtil.isRunning(); + final EDTUtil _edtUtil = edtUtil; + if( null != _edtUtil ) { + return _edtUtil.isRunning(); } return false; } @Override public String toString() { - return "NEWT-Display["+getFQName()+", excl "+exclusive+", refCount "+refCount+", hasEDT "+(null!=edtUtil)+", edtRunning "+isEDTRunning()+", "+aDevice+"]"; + final EDTUtil _edtUtil = edtUtil; + final boolean _edtUtilRunning = ( null != _edtUtil ) ? _edtUtil.isRunning() : false; + return "NEWT-Display["+getFQName()+", excl "+exclusive+", refCount "+refCount+", hasEDT "+(null!=_edtUtil)+", edtRunning "+_edtUtilRunning+", "+aDevice+"]"; } /** Dispatch native Toolkit messageges */ @@ -500,17 +536,18 @@ public abstract class DisplayImpl extends Display { } public void enqueueEvent(boolean wait, NEWTEvent e) { - if(!isEDTRunning()) { + final EDTUtil _edtUtil = edtUtil; + if( !_edtUtil.isRunning() ) { // oops .. we are already dead if(DEBUG) { - Throwable t = new Throwable("Warning: EDT already stopped: wait:="+wait+", "+e); - t.printStackTrace(); + System.err.println("Warning: EDT already stopped: wait:="+wait+", "+e); + Thread.dumpStack(); } return; } // can't wait if we are on EDT or NEDT -> consume right away - if(wait && edtUtil.isCurrentThreadEDTorNEDT() ) { + if(wait && _edtUtil.isCurrentThreadEDTorNEDT() ) { dispatchMessage(e); return; } @@ -557,7 +594,7 @@ public abstract class DisplayImpl extends Display { return runWithLockedDevice(device, action); } - protected EDTUtil edtUtil = null; + protected volatile EDTUtil edtUtil = null; protected int id; protected String name; protected String type; diff --git a/src/newt/classes/jogamp/newt/driver/android/DisplayDriver.java b/src/newt/classes/jogamp/newt/driver/android/DisplayDriver.java index a367462c4..a2877dba2 100644 --- a/src/newt/classes/jogamp/newt/driver/android/DisplayDriver.java +++ b/src/newt/classes/jogamp/newt/driver/android/DisplayDriver.java @@ -55,7 +55,7 @@ public class DisplayDriver extends jogamp.newt.DisplayImpl { aDevice = EGLDisplayUtil.eglCreateEGLGraphicsDevice(EGL.EGL_DEFAULT_DISPLAY, AbstractGraphicsDevice.DEFAULT_CONNECTION, AbstractGraphicsDevice.DEFAULT_UNIT); } - protected void closeNativeImpl() { + protected void closeNativeImpl(AbstractGraphicsDevice aDevice) { aDevice.close(); } diff --git a/src/newt/classes/jogamp/newt/driver/awt/AWTEDTUtil.java b/src/newt/classes/jogamp/newt/driver/awt/AWTEDTUtil.java index abd47d17e..80c72c008 100644 --- a/src/newt/classes/jogamp/newt/driver/awt/AWTEDTUtil.java +++ b/src/newt/classes/jogamp/newt/driver/awt/AWTEDTUtil.java @@ -45,7 +45,7 @@ public class AWTEDTUtil implements EDTUtil { private final ThreadGroup threadGroup; private final String name; private final Runnable dispatchMessages; - private NewtEventDispatchThread nedt = null; + private NEDT nedt = null; private int start_iter=0; private static long pollPeriod = EDTUtil.defaultEDTPollPeriod; @@ -53,7 +53,7 @@ public class AWTEDTUtil implements EDTUtil { this.threadGroup = tg; this.name=Thread.currentThread().getName()+"-"+name+"-EDT-"; this.dispatchMessages=dispatchMessages; - this.nedt = new NewtEventDispatchThread(threadGroup, name); + this.nedt = new NEDT(threadGroup, name); this.nedt.setDaemon(true); // don't stop JVM from shutdown .. } @@ -68,33 +68,29 @@ public class AWTEDTUtil implements EDTUtil { } @Override - public final void reset() throws IllegalStateException { + public final boolean restart() throws IllegalStateException { synchronized(edtLock) { - final Thread curT = Thread.currentThread(); - final boolean onAWTEDT = EventQueue.isDispatchThread(); if( nedt.isRunning() ) { - if( !nedt.shouldStop ) { - throw new IllegalStateException("EDT stop not issued."); - } - if( nedt != curT && !onAWTEDT ) { - throw new IllegalStateException("EDT still running: Curr "+curT.getName()+", NEDT "+nedt.getName()+", on AWT-EDT "+onAWTEDT); - } + throw new IllegalStateException("EDT still running and not subject to stop. Curr "+Thread.currentThread().getName()+", NEDT "+nedt.getName()+", isRunning "+nedt.isRunning+", shouldStop "+nedt.shouldStop+", on AWT-EDT "+EventQueue.isDispatchThread()); } if(DEBUG) { System.err.println(Thread.currentThread()+": AWT-EDT reset - edt: "+nedt); } - this.nedt = new NewtEventDispatchThread(threadGroup, name); - this.nedt.setDaemon(true); // don't stop JVM from shutdown .. + if( nedt.getState() != Thread.State.NEW ) { + nedt = new NEDT(threadGroup, name); + nedt.setDaemon(true); // don't stop JVM from shutdown .. + } + startImpl(); } + return invoke(true, nullTask); } private final void startImpl() { if(nedt.isAlive()) { - throw new RuntimeException("AWT-EDT Thread.isAlive(): true, isRunning: "+nedt.isRunning()+", edt: "+nedt); + throw new RuntimeException("AWT-EDT Thread.isAlive(): true, isRunning: "+nedt.isRunning+", shouldStop "+nedt.shouldStop+", edt: "+nedt); } start_iter++; nedt.setName(name+start_iter); - nedt.shouldStop = false; if(DEBUG) { System.err.println(Thread.currentThread()+": AWT-EDT START - edt: "+nedt); // Thread.dumpStack(); @@ -123,55 +119,72 @@ public class AWTEDTUtil implements EDTUtil { } @Override - public final void invokeStop(boolean wait, Runnable task) { - invokeImpl(wait, task, true); + public final boolean invokeStop(boolean wait, Runnable task) { + return invokeImpl(wait, task, true); } @Override - public final void invoke(boolean wait, Runnable task) { - invokeImpl(wait, task, false); + public final boolean invoke(boolean wait, Runnable task) { + return invokeImpl(wait, task, false); } - private void invokeImpl(boolean wait, Runnable task, boolean stop) { + private static Runnable nullTask = new Runnable() { + @Override + public void run() { } + }; + + private final boolean invokeImpl(boolean wait, Runnable task, boolean stop) { Throwable throwable = null; RunnableTask rTask = null; - Object rTaskLock = new Object(); + final Object rTaskLock = new Object(); synchronized(rTaskLock) { // lock the optional task execution synchronized(edtLock) { // lock the EDT status if( nedt.shouldStop ) { // drop task .. + System.err.println(Thread.currentThread()+": Warning: AWT-EDT about (1) to stop, won't enqueue new task: "+nedt); if(DEBUG) { - System.err.println(Thread.currentThread()+": Warning: AWT-EDT about (1) to stop, won't enqueue new task: "+nedt); Thread.dumpStack(); } - return; + return false; } - // System.err.println(Thread.currentThread()+" XXX stop: "+stop+", tasks: "+edt.tasks.size()+", task: "+task); - // Thread.dumpStack(); - if(stop) { - synchronized(nedt.sync) { + if( isCurrentThreadEDT() ) { + if(null != task) { + task.run(); + } + wait = false; // running in same thread (EDT) -> no wait + if(stop) { nedt.shouldStop = true; - nedt.sync.notifyAll(); // stop immediate if waiting (poll freq) } - if(DEBUG) { - System.err.println(Thread.currentThread()+": AWT-EDT signal STOP (on edt: "+isCurrentThreadEDT()+") - "+nedt); - // Thread.dumpStack(); + } else { + if( !nedt.isRunning ) { + if( null != task ) { + if( stop ) { + System.err.println(Thread.currentThread()+": Warning: AWT-EDT is about (3) to stop and stopped already, dropping task. NEDT "+nedt); + } else { + System.err.println(Thread.currentThread()+": Warning: AWT-EDT is not running, dropping task. NEDT "+nedt); + } + if(DEBUG) { + Thread.dumpStack(); + } + } + return false; + } else if( stop ) { + if(DEBUG) { + System.err.println(Thread.currentThread()+": AWT-EDT signal STOP (on edt: "+isCurrentThreadEDT()+") - "+nedt+", isRunning "+nedt.isRunning+", shouldStop "+nedt.shouldStop); + } + synchronized(nedt.sync) { + nedt.shouldStop = true; + nedt.sync.notifyAll(); // stop immediate if waiting (poll freq) + } + } + + if(null != task) { + rTask = new RunnableTask(task, + wait ? rTaskLock : null, + true /* always catch and report Exceptions, don't disturb EDT */, + wait ? null : System.err); + AWTEDTExecutor.singleton.invoke(false, rTask); } - } else if( !nedt.isRunning() ) { - // start if should not stop && not started yet - startImpl(); - } - if( null == task ) { - wait = false; - } else if( isCurrentThreadEDT() ) { - task.run(); - wait = false; // running in same thread (EDT) -> no wait - } else { - rTask = new RunnableTask(task, - wait ? rTaskLock : null, - true /* always catch and report Exceptions, don't disturb EDT */, - wait ? null : System.err); - AWTEDTExecutor.singleton.invoke(false, rTask); } } if( wait ) { @@ -190,51 +203,56 @@ public class AWTEDTUtil implements EDTUtil { throw new RuntimeException(throwable); } } + return true; } } @Override - final public void waitUntilIdle() { - final NewtEventDispatchThread _edt; + final public boolean waitUntilIdle() { + final NEDT _edt; synchronized(edtLock) { _edt = nedt; } - if(!_edt.isRunning() || _edt == Thread.currentThread() || EventQueue.isDispatchThread()) { - return; + if(!_edt.isRunning || _edt == Thread.currentThread() || EventQueue.isDispatchThread()) { + return false; } try { AWTEDTExecutor.singleton.invoke(true, new Runnable() { public void run() { } }); } catch (Exception e) { } + return true; } @Override - final public void waitUntilStopped() { + final public boolean waitUntilStopped() { synchronized(edtLock) { - if( nedt.isRunning() && nedt != Thread.currentThread() && !EventQueue.isDispatchThread() ) { - while(nedt.isRunning()) { + if( nedt.isRunning && nedt != Thread.currentThread() && !EventQueue.isDispatchThread() ) { + while( nedt.isRunning ) { try { edtLock.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } + return true; + } else { + return false; } } } - class NewtEventDispatchThread extends Thread { + class NEDT extends Thread { volatile boolean shouldStop = false; volatile boolean isRunning = false; Object sync = new Object(); - public NewtEventDispatchThread(ThreadGroup tg, String name) { + public NEDT(ThreadGroup tg, String name) { super(tg, name); } final public boolean isRunning() { - return isRunning; + return isRunning && !shouldStop; } @Override diff --git a/src/newt/classes/jogamp/newt/driver/awt/DisplayDriver.java b/src/newt/classes/jogamp/newt/driver/awt/DisplayDriver.java index 4139951aa..30449f9bc 100644 --- a/src/newt/classes/jogamp/newt/driver/awt/DisplayDriver.java +++ b/src/newt/classes/jogamp/newt/driver/awt/DisplayDriver.java @@ -34,6 +34,8 @@ package jogamp.newt.driver.awt; +import javax.media.nativewindow.AbstractGraphicsDevice; + import com.jogamp.nativewindow.awt.AWTGraphicsDevice; import com.jogamp.newt.NewtFactory; import com.jogamp.newt.util.EDTUtil; @@ -65,7 +67,7 @@ public class DisplayDriver extends DisplayImpl { return def; } - protected void closeNativeImpl() { + protected void closeNativeImpl(AbstractGraphicsDevice aDevice) { aDevice.close(); } diff --git a/src/newt/classes/jogamp/newt/driver/bcm/egl/DisplayDriver.java b/src/newt/classes/jogamp/newt/driver/bcm/egl/DisplayDriver.java index cc55c336e..112be2b04 100644 --- a/src/newt/classes/jogamp/newt/driver/bcm/egl/DisplayDriver.java +++ b/src/newt/classes/jogamp/newt/driver/bcm/egl/DisplayDriver.java @@ -69,7 +69,7 @@ public class DisplayDriver extends jogamp.newt.DisplayImpl { aDevice = new EGLGraphicsDevice(EGL.EGL_DEFAULT_DISPLAY, handle, AbstractGraphicsDevice.DEFAULT_CONNECTION, AbstractGraphicsDevice.DEFAULT_UNIT, null); } - protected void closeNativeImpl() { + protected void closeNativeImpl(AbstractGraphicsDevice aDevice) { if (aDevice.getHandle() != EGL.EGL_NO_DISPLAY) { DestroyDisplay(aDevice.getHandle()); } diff --git a/src/newt/classes/jogamp/newt/driver/bcm/vc/iv/DisplayDriver.java b/src/newt/classes/jogamp/newt/driver/bcm/vc/iv/DisplayDriver.java index 08c5c573c..4872a9071 100644 --- a/src/newt/classes/jogamp/newt/driver/bcm/vc/iv/DisplayDriver.java +++ b/src/newt/classes/jogamp/newt/driver/bcm/vc/iv/DisplayDriver.java @@ -64,7 +64,7 @@ public class DisplayDriver extends DisplayImpl { aDevice = EGLDisplayUtil.eglCreateEGLGraphicsDevice(EGL.EGL_DEFAULT_DISPLAY, AbstractGraphicsDevice.DEFAULT_CONNECTION, AbstractGraphicsDevice.DEFAULT_UNIT); } - protected void closeNativeImpl() { + protected void closeNativeImpl(AbstractGraphicsDevice aDevice) { aDevice.close(); } diff --git a/src/newt/classes/jogamp/newt/driver/intel/gdl/DisplayDriver.java b/src/newt/classes/jogamp/newt/driver/intel/gdl/DisplayDriver.java index e370038d9..ee93eb932 100644 --- a/src/newt/classes/jogamp/newt/driver/intel/gdl/DisplayDriver.java +++ b/src/newt/classes/jogamp/newt/driver/intel/gdl/DisplayDriver.java @@ -72,7 +72,7 @@ public class DisplayDriver extends jogamp.newt.DisplayImpl { aDevice = new DefaultGraphicsDevice(NativeWindowFactory.TYPE_DEFAULT, AbstractGraphicsDevice.DEFAULT_CONNECTION, AbstractGraphicsDevice.DEFAULT_UNIT, displayHandle); } - protected void closeNativeImpl() { + protected void closeNativeImpl(AbstractGraphicsDevice aDevice) { if(0==displayHandle) { throw new NativeWindowException("displayHandle null; initCnt "+initCounter); } diff --git a/src/newt/classes/jogamp/newt/driver/kd/DisplayDriver.java b/src/newt/classes/jogamp/newt/driver/kd/DisplayDriver.java index 745be5dae..3cd72e971 100644 --- a/src/newt/classes/jogamp/newt/driver/kd/DisplayDriver.java +++ b/src/newt/classes/jogamp/newt/driver/kd/DisplayDriver.java @@ -64,7 +64,7 @@ public class DisplayDriver extends DisplayImpl { aDevice = EGLDisplayUtil.eglCreateEGLGraphicsDevice(EGL.EGL_DEFAULT_DISPLAY, AbstractGraphicsDevice.DEFAULT_CONNECTION, AbstractGraphicsDevice.DEFAULT_UNIT); } - protected void closeNativeImpl() { + protected void closeNativeImpl(AbstractGraphicsDevice aDevice) { aDevice.close(); } diff --git a/src/newt/classes/jogamp/newt/driver/macosx/DisplayDriver.java b/src/newt/classes/jogamp/newt/driver/macosx/DisplayDriver.java index b49c6b6e0..a99bc4f23 100644 --- a/src/newt/classes/jogamp/newt/driver/macosx/DisplayDriver.java +++ b/src/newt/classes/jogamp/newt/driver/macosx/DisplayDriver.java @@ -72,7 +72,7 @@ public class DisplayDriver extends DisplayImpl { aDevice = new MacOSXGraphicsDevice(AbstractGraphicsDevice.DEFAULT_UNIT); } - protected void closeNativeImpl() { + protected void closeNativeImpl(AbstractGraphicsDevice aDevice) { aDevice.close(); } diff --git a/src/newt/classes/jogamp/newt/driver/windows/DisplayDriver.java b/src/newt/classes/jogamp/newt/driver/windows/DisplayDriver.java index 1b9ec0f25..595d5e952 100644 --- a/src/newt/classes/jogamp/newt/driver/windows/DisplayDriver.java +++ b/src/newt/classes/jogamp/newt/driver/windows/DisplayDriver.java @@ -76,7 +76,7 @@ public class DisplayDriver extends DisplayImpl { aDevice = new WindowsGraphicsDevice(AbstractGraphicsDevice.DEFAULT_UNIT); } - protected void closeNativeImpl() { + protected void closeNativeImpl(AbstractGraphicsDevice aDevice) { sharedClassFactory.releaseSharedClass(); aDevice.close(); } diff --git a/src/newt/classes/jogamp/newt/driver/x11/DisplayDriver.java b/src/newt/classes/jogamp/newt/driver/x11/DisplayDriver.java index 88d06f69c..d911483b0 100644 --- a/src/newt/classes/jogamp/newt/driver/x11/DisplayDriver.java +++ b/src/newt/classes/jogamp/newt/driver/x11/DisplayDriver.java @@ -82,13 +82,13 @@ public class DisplayDriver extends DisplayImpl { try { CompleteDisplay0(aDevice.getHandle()); } catch(RuntimeException e) { - closeNativeImpl(); + closeNativeImpl(aDevice); throw e; } } @Override - protected void closeNativeImpl() { + protected void closeNativeImpl(AbstractGraphicsDevice aDevice) { DisplayRelease0(aDevice.getHandle(), javaObjectAtom, windowDeleteAtom /*, kbdHandle */); // XKB disabled for now javaObjectAtom = 0; windowDeleteAtom = 0; diff --git a/src/newt/classes/jogamp/newt/swt/SWTEDTUtil.java b/src/newt/classes/jogamp/newt/swt/SWTEDTUtil.java index a8e03c510..d46562050 100644 --- a/src/newt/classes/jogamp/newt/swt/SWTEDTUtil.java +++ b/src/newt/classes/jogamp/newt/swt/SWTEDTUtil.java @@ -46,7 +46,7 @@ public class SWTEDTUtil implements EDTUtil { private final String name; private final Runnable dispatchMessages; private final org.eclipse.swt.widgets.Display swtDisplay; - private NewtEventDispatchThread nedt = null; + private NEDT nedt = null; private int start_iter=0; private static long pollPeriod = EDTUtil.defaultEDTPollPeriod; @@ -58,7 +58,7 @@ public class SWTEDTUtil implements EDTUtil { ((jogamp.newt.DisplayImpl) newtDisplay).dispatchMessages(); } }; this.swtDisplay = swtDisplay; - this.nedt = new NewtEventDispatchThread(threadGroup, name); + this.nedt = new NEDT(threadGroup, name); this.nedt.setDaemon(true); // don't stop JVM from shutdown .. } @@ -77,34 +77,39 @@ public class SWTEDTUtil implements EDTUtil { } @Override - public final void reset() throws IllegalStateException { + public final boolean restart() throws IllegalStateException { + final boolean swtDisposed = swtDisplay.isDisposed(); synchronized(edtLock) { - final Thread curT = Thread.currentThread(); - final Thread swtT = !swtDisplay.isDisposed() ? swtDisplay.getThread() : null; - final boolean onSWTEDT = swtT == curT; if( nedt.isRunning() ) { - if( !nedt.shouldStop ) { - throw new IllegalStateException("EDT stop not issued."); - } - if( nedt != curT && !onSWTEDT ) { - throw new IllegalStateException("EDT still running: Curr "+curT.getName()+", NEDT "+nedt.getName()+", SWT-EDT "+swtT.getName()); - } + final Thread curT = Thread.currentThread(); + final Thread swtT = !swtDisposed ? swtDisplay.getThread() : null; + final boolean onSWTEDT = swtT == curT; + throw new IllegalStateException("EDT still running and not subject to stop. Curr "+curT.getName()+", NEDT "+nedt.getName()+", isRunning "+nedt.isRunning+", shouldStop "+nedt.shouldStop+", SWT-EDT "+swtT.getName()+", on SWT-EDT "+onSWTEDT); } if(DEBUG) { - System.err.println(Thread.currentThread()+": SWT-EDT reset - edt: "+nedt); + System.err.println(Thread.currentThread()+": SWT-EDT reset - edt: "+nedt+", swtDisposed (skipping) "+swtDisposed); + } + if( !swtDisposed ) { + if( nedt.getState() != Thread.State.NEW ) { + nedt = new NEDT(threadGroup, name); + nedt.setDaemon(true); // don't stop JVM from shutdown .. + } + startImpl(); } - this.nedt = new NewtEventDispatchThread(threadGroup, name); - this.nedt.setDaemon(true); // don't stop JVM from shutdown .. + } + if( !swtDisposed ) { + return invoke(true, nullTask); + } else { + return false; } } private final void startImpl() { if(nedt.isAlive()) { - throw new RuntimeException("SWT-EDT Thread.isAlive(): true, isRunning: "+nedt.isRunning()+", edt: "+nedt); + throw new RuntimeException("SWT-EDT Thread.isAlive(): true, isRunning: "+nedt.isRunning+", shouldStop "+nedt.shouldStop+", edt: "+nedt); } start_iter++; nedt.setName(name+start_iter); - nedt.shouldStop = false; if(DEBUG) { System.err.println(Thread.currentThread()+": SWT-EDT START - edt: "+nedt); // Thread.dumpStack(); @@ -130,60 +135,89 @@ public class SWTEDTUtil implements EDTUtil { @Override public boolean isRunning() { - return nedt.isRunning() ; + return nedt.isRunning(); } @Override - public final void invokeStop(boolean wait, Runnable task) { - invokeImpl(wait, task, true); + public final boolean invokeStop(boolean wait, Runnable task) { + return invokeImpl(wait, task, true); } @Override - public final void invoke(boolean wait, Runnable task) { - invokeImpl(wait, task, false); + public final boolean invoke(boolean wait, Runnable task) { + return invokeImpl(wait, task, false); } - private void invokeImpl(boolean wait, Runnable task, boolean stop) { + private static Runnable nullTask = new Runnable() { + @Override + public void run() { } + }; + + private final boolean invokeImpl(boolean wait, Runnable task, boolean stop) { Throwable throwable = null; RunnableTask rTask = null; - Object rTaskLock = new Object(); + final Object rTaskLock = new Object(); synchronized(rTaskLock) { // lock the optional task execution synchronized(edtLock) { // lock the EDT status if( nedt.shouldStop ) { // drop task .. if(DEBUG) { - System.err.println(Thread.currentThread()+": Warning: SWT-EDT about (1) to stop, won't enqueue new task: "+nedt+", isRunning "+nedt.isRunning()); - // Thread.dumpStack(); + System.err.println(Thread.currentThread()+": Warning: SWT-EDT about (1) to stop, won't enqueue new task: "+nedt+", isRunning "+nedt.isRunning+", shouldStop "+nedt.shouldStop); + Thread.dumpStack(); } - return; + return false; } - // System.err.println(Thread.currentThread()+" XXX stop: "+stop+", tasks: "+edt.tasks.size()+", task: "+task); - // Thread.dumpStack(); - if(stop) { - if(DEBUG) { - System.err.println(Thread.currentThread()+": SWT-EDT signal STOP (on edt: "+isCurrentThreadEDT()+") - "+nedt+", isRunning "+nedt.isRunning()); + if( swtDisplay.isDisposed() ) { + stop = true; + } + + if( isCurrentThreadEDT() ) { + if(null != task) { + task.run(); } - synchronized(nedt.sync) { + wait = false; // running in same thread (EDT) -> no wait + if( stop ) { nedt.shouldStop = true; - nedt.sync.notifyAll(); // stop immediate if waiting (poll freq) } - } else if( !nedt.isRunning() && !swtDisplay.isDisposed() ) { - // start if should not stop && not started yet - startImpl(); - } - if( null == task ) { - wait = false; - } else if( swtDisplay.isDisposed() ) { - wait = false; // drop task, SWT disposed - } else if( isCurrentThreadEDT() ) { - task.run(); - wait = false; // running in same thread (EDT) -> no wait - } else { - rTask = new RunnableTask(task, - wait ? rTaskLock : null, - true /* always catch and report Exceptions, don't disturb EDT */, - wait ? null : System.err); - swtDisplay.asyncExec(rTask); + } else { + if( !nedt.isRunning && !swtDisplay.isDisposed() ) { + if( null != task ) { + if( stop ) { + System.err.println(Thread.currentThread()+": Warning: SWT-EDT is about (3) to stop and stopped already, dropping task. NEDT "+nedt); + } else { + System.err.println(Thread.currentThread()+": Warning: SWT-EDT is not running, dropping task. NEDT "+nedt); + } + if(DEBUG) { + Thread.dumpStack(); + } + } + return false; + } else if( stop ) { + if( nedt.isRunning ) { + if(DEBUG) { + System.err.println(Thread.currentThread()+": SWT-EDT signal STOP (on edt: "+isCurrentThreadEDT()+") - "+nedt+", isRunning "+nedt.isRunning+", shouldStop "+nedt.shouldStop); + } + synchronized(nedt.sync) { + nedt.shouldStop = true; + nedt.sync.notifyAll(); // stop immediate if waiting (poll freq) + } + } + if( swtDisplay.isDisposed() ) { + System.err.println(Thread.currentThread()+": Warning: SWT-EDT is about (3) to stop and stopped already, dropping task. "+nedt); + if(DEBUG) { + Thread.dumpStack(); + } + return false; + } + } + + if( null != task ) { + rTask = new RunnableTask(task, + wait ? rTaskLock : null, + true /* always catch and report Exceptions, don't disturb EDT */, + wait ? null : System.err); + swtDisplay.asyncExec(rTask); + } } } if( wait ) { @@ -202,55 +236,60 @@ public class SWTEDTUtil implements EDTUtil { throw new RuntimeException(throwable); } } + return true; } } @Override - final public void waitUntilIdle() { - final NewtEventDispatchThread _nedt; + final public boolean waitUntilIdle() { + final NEDT _nedt; synchronized(edtLock) { _nedt = nedt; } final Thread ct = Thread.currentThread(); - if( !_nedt.isRunning() || _nedt == ct || swtDisplay.isDisposed() || swtDisplay.getThread() == ct ) { - return; + if( !_nedt.isRunning || _nedt == ct || swtDisplay.isDisposed() || swtDisplay.getThread() == ct ) { + return false; } try { swtDisplay.syncExec(new Runnable() { public void run() { } }); } catch (Exception e) { } + return true; } @Override - final public void waitUntilStopped() { + final public boolean waitUntilStopped() { synchronized(edtLock) { final Thread curT = Thread.currentThread(); final Thread swtT = !swtDisplay.isDisposed() ? swtDisplay.getThread() : null; final boolean onSWTEDT = swtT == curT; - if( nedt.isRunning() && nedt != curT && !onSWTEDT ) { - while(nedt.isRunning()) { + if( nedt.isRunning && nedt != curT && !onSWTEDT ) { + while( nedt.isRunning ) { try { edtLock.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } + return true; + } else { + return false; } } } - class NewtEventDispatchThread extends Thread { + class NEDT extends Thread { volatile boolean shouldStop = false; volatile boolean isRunning = false; Object sync = new Object(); - public NewtEventDispatchThread(ThreadGroup tg, String name) { + public NEDT(ThreadGroup tg, String name) { super(tg, name); } final public boolean isRunning() { - return isRunning; + return isRunning && !shouldStop; } @Override diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/InitConcurrentBaseNEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/InitConcurrentBaseNEWT.java index f8e6ee5d3..f1bc0ab7a 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/InitConcurrentBaseNEWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/InitConcurrentBaseNEWT.java @@ -184,6 +184,7 @@ public abstract class InitConcurrentBaseNEWT extends UITestCase { } protected void runJOGLTasks(int num, boolean reuse) throws InterruptedException { + System.err.println("InitConcurrentBaseNEWT "+num+" threads, reuse display: "+reuse); final String currentThreadName = Thread.currentThread().getName(); final Object syncDone = new Object(); final JOGLTask[] tasks = new JOGLTask[num]; @@ -198,13 +199,16 @@ public abstract class InitConcurrentBaseNEWT extends UITestCase { for(i=0; i<num; i++) { threads[i].start(); } + i=0; synchronized (syncDone) { while(!done(tasks)) { try { - syncDone.wait(); + syncDone.wait(500); } catch (InterruptedException e) { throw new RuntimeException(e); } + System.err.println(i+": "+doneDump(tasks)); + i++; } } final long t1 = System.currentTimeMillis(); diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestInitConcurrent01NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestInitConcurrent01NEWT.java index 20c098f2e..f8e0affa3 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestInitConcurrent01NEWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestInitConcurrent01NEWT.java @@ -42,8 +42,7 @@ import com.jogamp.common.os.Platform; * </p> */ public class TestInitConcurrent01NEWT extends InitConcurrentBaseNEWT { - static boolean mainRun = false; - + @Test(timeout=180000) // TO 3 min public void test02TwoThreads() throws InterruptedException { runJOGLTasks(2, true); @@ -56,8 +55,7 @@ public class TestInitConcurrent01NEWT extends InitConcurrentBaseNEWT { @Test(timeout=300000) // TO 5 min public void test16SixteenThreads() throws InterruptedException { - if( !mainRun && - Platform.getCPUFamily() != Platform.CPUFamily.ARM && + if( Platform.getCPUFamily() != Platform.CPUFamily.ARM && Platform.getOSType() != Platform.OSType.WINDOWS ) { runJOGLTasks(16, true); } else { @@ -66,11 +64,8 @@ public class TestInitConcurrent01NEWT extends InitConcurrentBaseNEWT { } public static void main(String args[]) throws IOException { - mainRun = true; for(int i=0; i<args.length; i++) { - if(args[i].equals("-normalRun")) { - mainRun = false; - } else if(args[i].equals("-time")) { + if(args[i].equals("-time")) { i++; try { duration = Integer.parseInt(args[i]); diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestInitConcurrent02NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestInitConcurrent02NEWT.java index 5b754ef7d..dfb7326df 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestInitConcurrent02NEWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestInitConcurrent02NEWT.java @@ -68,8 +68,7 @@ public class TestInitConcurrent02NEWT extends InitConcurrentBaseNEWT { System.err.println("Disabled for auto unit test until further analysis - Windows/ATI driver crash"); return; } - if( !mainRun && - Platform.getCPUFamily() != Platform.CPUFamily.ARM && + if( Platform.getCPUFamily() != Platform.CPUFamily.ARM && Platform.getOSType() != Platform.OSType.WINDOWS ) { runJOGLTasks(16, false); } else { diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/newt/TestGearsES2NewtCanvasSWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/newt/TestGearsES2NewtCanvasSWT.java index eed2e1267..7a93faa1f 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/newt/TestGearsES2NewtCanvasSWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/newt/TestGearsES2NewtCanvasSWT.java @@ -103,6 +103,7 @@ public class TestGearsES2NewtCanvasSWT extends UITestCase { Display display = null; Shell shell = null; Composite composite = null; + com.jogamp.newt.Display swtNewtDisplay = null; @Before public void init() { @@ -120,6 +121,7 @@ public class TestGearsES2NewtCanvasSWT extends UITestCase { composite.setLayout( new FillLayout() ); Assert.assertNotNull( composite ); }}); + swtNewtDisplay = NewtFactory.createDisplay(null, false); // no-reuse } @After @@ -142,6 +144,7 @@ public class TestGearsES2NewtCanvasSWT extends UITestCase { throwable.printStackTrace(); Assume.assumeNoException( throwable ); } + swtNewtDisplay = null; display = null; shell = null; composite = null; @@ -149,8 +152,7 @@ public class TestGearsES2NewtCanvasSWT extends UITestCase { protected void runTestGL(GLCapabilitiesImmutable caps) throws InterruptedException, InvocationTargetException { System.err.println("requested: vsync "+swapInterval+", "+caps); - com.jogamp.newt.Display dpy = NewtFactory.createDisplay(null); - com.jogamp.newt.Screen screen = NewtFactory.createScreen(dpy, screenIdx); + com.jogamp.newt.Screen screen = NewtFactory.createScreen(swtNewtDisplay, screenIdx); final GLWindow glWindow = GLWindow.create(screen, caps); Assert.assertNotNull(glWindow); diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestNewtCanvasSWTBug628ResizeDeadlockAWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestNewtCanvasSWTBug628ResizeDeadlockAWT.java index e7037aaef..f8fbe7276 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestNewtCanvasSWTBug628ResizeDeadlockAWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestNewtCanvasSWTBug628ResizeDeadlockAWT.java @@ -52,6 +52,7 @@ import javax.media.opengl.GLProfile; import junit.framework.Assert; import com.jogamp.nativewindow.swt.SWTAccessor; +import com.jogamp.newt.NewtFactory; import com.jogamp.newt.event.KeyAdapter; import com.jogamp.newt.event.KeyEvent; import com.jogamp.newt.opengl.GLWindow ; @@ -250,6 +251,7 @@ public class TestNewtCanvasSWTBug628ResizeDeadlockAWT extends UITestCase { volatile Display display; volatile Shell shell; volatile Composite composite; + volatile com.jogamp.newt.Display swtNewtDisplay = null; public void init() { SWTAccessor.invoke(true, new Runnable() { @@ -266,7 +268,8 @@ public class TestNewtCanvasSWTBug628ResizeDeadlockAWT extends UITestCase { composite = new Composite( shell, SWT.NO_BACKGROUND ); composite.setLayout( new FillLayout() ); Assert.assertNotNull( composite ); - }}); + }}); + swtNewtDisplay = NewtFactory.createDisplay(null, false); // no-reuse } public void dispose() { @@ -288,6 +291,7 @@ public class TestNewtCanvasSWTBug628ResizeDeadlockAWT extends UITestCase { throwable.printStackTrace(); Assume.assumeNoException( throwable ); } + swtNewtDisplay = null; display = null; shell = null; composite = null; @@ -305,7 +309,8 @@ public class TestNewtCanvasSWTBug628ResizeDeadlockAWT extends UITestCase { { final GLProfile gl2Profile = GLProfile.get( GLProfile.GL2 ) ; final GLCapabilities caps = new GLCapabilities( gl2Profile ) ; - glWindow = GLWindow.create( caps ) ; + com.jogamp.newt.Screen screen = NewtFactory.createScreen(dsc.swtNewtDisplay, 0); + glWindow = GLWindow.create( screen, caps ) ; glWindow.addGLEventListener( new BigFlashingX() ) ; glWindow.addKeyListener(new KeyAdapter() { @Override diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestNewtCanvasSWTGLn.java b/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestNewtCanvasSWTGLn.java index 396d219b4..7acc6452e 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestNewtCanvasSWTGLn.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestNewtCanvasSWTGLn.java @@ -48,6 +48,8 @@ import org.junit.After; import org.junit.Test; import com.jogamp.nativewindow.swt.SWTAccessor; +import com.jogamp.newt.NewtFactory; +import com.jogamp.newt.Screen; import com.jogamp.newt.opengl.GLWindow; import com.jogamp.newt.swt.NewtCanvasSWT; import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; @@ -81,7 +83,8 @@ public class TestNewtCanvasSWTGLn extends UITestCase { Display display = null; Shell shell = null; Composite composite = null; - + com.jogamp.newt.Display swtNewtDisplay = null; + @BeforeClass public static void startup() { System.out.println( "GLProfile " + GLProfile.glAvailabilityToString() ); @@ -103,6 +106,7 @@ public class TestNewtCanvasSWTGLn extends UITestCase { composite.setLayout( new FillLayout() ); Assert.assertNotNull( composite ); }}); + swtNewtDisplay = NewtFactory.createDisplay(null, false); // no-reuse } @After @@ -125,6 +129,7 @@ public class TestNewtCanvasSWTGLn extends UITestCase { throwable.printStackTrace(); Assume.assumeNoException( throwable ); } + swtNewtDisplay = null; display = null; shell = null; composite = null; @@ -134,7 +139,8 @@ public class TestNewtCanvasSWTGLn extends UITestCase { boolean postAttach, boolean useAnimator ) throws InterruptedException { final GLReadBufferUtil screenshot = new GLReadBufferUtil(false, false); - final GLWindow glWindow1 = GLWindow.create(caps); + final Screen screen = NewtFactory.createScreen(swtNewtDisplay, 0); + final GLWindow glWindow1 = GLWindow.create(screen, caps); Assert.assertNotNull(glWindow1); Assert.assertEquals(false, glWindow1.isVisible()); Assert.assertEquals(false, glWindow1.isNativeValid()); diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestSWTBug643AsyncExec.java b/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestSWTBug643AsyncExec.java index 66911ef06..4d279b349 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestSWTBug643AsyncExec.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestSWTBug643AsyncExec.java @@ -49,6 +49,7 @@ import jogamp.newt.swt.event.SWTNewtEventFactory; import junit.framework.Assert; import com.jogamp.nativewindow.swt.SWTAccessor; +import com.jogamp.newt.NewtFactory; import com.jogamp.newt.opengl.GLWindow ; import com.jogamp.newt.swt.NewtCanvasSWT ; import com.jogamp.opengl.swt.GLCanvas; @@ -140,7 +141,9 @@ public class TestSWTBug643AsyncExec extends UITestCase { { try { - swtDisplay.asyncExec( swtAsyncAction ); + if( !swtDisplay.isDisposed() ) { + swtDisplay.asyncExec( swtAsyncAction ); + } if(null != newtDisplay && newtDisplay.isNativeValid() && newtDisplay.getEDTUtil().isRunning()) { // only perform async exec on valid and already running NEWT EDT! newtDisplay.runOnEDTIfAvail(false, newtAsyncAction); @@ -227,9 +230,10 @@ public class TestSWTBug643AsyncExec extends UITestCase { glad = glc; newtDisplay = null; } else if( useNewtCanvasSWT ) { - final GLWindow glWindow = GLWindow.create( caps ) ; + newtDisplay = NewtFactory.createDisplay(null, false); // no-reuse + com.jogamp.newt.Screen screen = NewtFactory.createScreen(newtDisplay, 0); + final GLWindow glWindow = GLWindow.create( screen, caps ) ; glWindow.addGLEventListener( new GearsES2() ) ; - newtDisplay = glWindow.getScreen().getDisplay(); if( glWindowPreVisible ) { newtDisplay.setEDTUtil(new SWTEDTUtil(newtDisplay, dsc.display)); // Especially Windows requires creation access via same thread! glWindow.setVisible(true); diff --git a/src/test/com/jogamp/opengl/test/junit/newt/TestDisplayLifecycle01NEWT.java b/src/test/com/jogamp/opengl/test/junit/newt/TestDisplayLifecycle01NEWT.java index e4867e3fe..6a248bcf6 100644 --- a/src/test/com/jogamp/opengl/test/junit/newt/TestDisplayLifecycle01NEWT.java +++ b/src/test/com/jogamp/opengl/test/junit/newt/TestDisplayLifecycle01NEWT.java @@ -37,6 +37,8 @@ import javax.media.opengl.*; import com.jogamp.newt.*; import com.jogamp.newt.event.*; import com.jogamp.newt.opengl.*; +import com.jogamp.newt.util.EDTUtil; + import java.io.IOException; import com.jogamp.opengl.test.junit.util.UITestCase; @@ -89,7 +91,7 @@ public class TestDisplayLifecycle01NEWT extends UITestCase { Assert.assertEquals(0,display.getReferenceCount()); Assert.assertEquals(false,display.isNativeValid()); Assert.assertNotNull(display.getEDTUtil()); - Assert.assertEquals(true,display.getEDTUtil().isRunning()); + Assert.assertEquals(false,display.getEDTUtil().isRunning()); Assert.assertEquals(0,screen.getReferenceCount()); Assert.assertEquals(false,screen.isNativeValid()); @@ -199,10 +201,17 @@ public class TestDisplayLifecycle01NEWT extends UITestCase { Assert.assertEquals(0,Display.getActiveDisplayNumber()); Assert.assertEquals(0,display.getReferenceCount()); Assert.assertEquals(false,display.isNativeValid()); - Assert.assertNotNull(display.getEDTUtil()); - Assert.assertEquals(false,display.getEDTUtil().isRunning()); - display.getEDTUtil().invoke(true, null); - Assert.assertEquals(true,display.getEDTUtil().isRunning()); + { + final EDTUtil edtUtil = display.getEDTUtil(); + Assert.assertNotNull(edtUtil); + Assert.assertEquals(false,edtUtil.isRunning()); + edtUtil.restart(); + edtUtil.invoke(true, null); + Assert.assertEquals(true,edtUtil.isRunning()); + edtUtil.invokeStop(true, null); + edtUtil.waitUntilStopped(); + Assert.assertEquals(false,edtUtil.isRunning()); + } Assert.assertEquals(0,screen.getReferenceCount()); Assert.assertEquals(false,screen.isNativeValid()); diff --git a/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting01NEWT.java b/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting01NEWT.java index e7fced5d9..d618d3b3c 100644 --- a/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting01NEWT.java +++ b/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting01NEWT.java @@ -74,7 +74,7 @@ public class TestParenting01NEWT extends UITestCase { Assert.assertEquals(0,display.getReferenceCount()); Assert.assertEquals(false,display.isNativeValid()); Assert.assertNotNull(display.getEDTUtil()); - Assert.assertEquals(true,display.getEDTUtil().isRunning()); + Assert.assertEquals(false,display.getEDTUtil().isRunning()); Assert.assertEquals(0,screen.getReferenceCount()); Assert.assertEquals(false,screen.isNativeValid()); Assert.assertEquals(0,Display.getActiveDisplayNumber()); diff --git a/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting01aSWT.java b/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting01aSWT.java index 11aef7c24..c95ac1985 100644 --- a/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting01aSWT.java +++ b/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting01aSWT.java @@ -47,6 +47,7 @@ import org.junit.BeforeClass; import org.junit.Test; import com.jogamp.nativewindow.swt.SWTAccessor; +import com.jogamp.newt.NewtFactory; import com.jogamp.newt.Window; import com.jogamp.newt.opengl.GLWindow; import com.jogamp.newt.swt.NewtCanvasSWT; @@ -65,6 +66,7 @@ public class TestParenting01aSWT extends UITestCase { Display display = null; Shell shell = null; Composite composite1 = null; + com.jogamp.newt.Display swtNewtDisplay = null; @BeforeClass public static void initClass() { @@ -86,6 +88,7 @@ public class TestParenting01aSWT extends UITestCase { composite1.setLayout( new FillLayout() ); Assert.assertNotNull( composite1 ); }}); + swtNewtDisplay = NewtFactory.createDisplay(null, false); // no-reuse } @After @@ -105,6 +108,7 @@ public class TestParenting01aSWT extends UITestCase { throwable.printStackTrace(); Assume.assumeNoException( throwable ); } + swtNewtDisplay = null; display = null; shell = null; composite1 = null; @@ -113,7 +117,8 @@ public class TestParenting01aSWT extends UITestCase { @Test public void testWindowParenting01CreateVisibleDestroy1() throws InterruptedException, InvocationTargetException { - GLWindow glWindow1 = GLWindow.create(glCaps); + com.jogamp.newt.Screen screen = NewtFactory.createScreen(swtNewtDisplay, 0); + GLWindow glWindow1 = GLWindow.create(screen, glCaps); Assert.assertNotNull(glWindow1); Assert.assertEquals(false, glWindow1.isVisible()); Assert.assertEquals(false, glWindow1.isNativeValid()); diff --git a/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting04SWT.java b/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting04SWT.java index 14a36c573..a4e4ace43 100644 --- a/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting04SWT.java +++ b/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting04SWT.java @@ -47,6 +47,7 @@ import org.junit.BeforeClass; import org.junit.Test; import com.jogamp.nativewindow.swt.SWTAccessor; +import com.jogamp.newt.NewtFactory; import com.jogamp.newt.Window; import com.jogamp.newt.opengl.GLWindow; import com.jogamp.newt.swt.NewtCanvasSWT; @@ -69,6 +70,7 @@ public class TestParenting04SWT extends UITestCase { Shell shell2 = null; Composite composite1 = null; Composite composite2 = null; + com.jogamp.newt.Display swtNewtDisplay = null; @BeforeClass public static void initClass() { @@ -98,6 +100,7 @@ public class TestParenting04SWT extends UITestCase { composite2.setLayout( new FillLayout() ); Assert.assertNotNull( composite2 ); }}); + swtNewtDisplay = NewtFactory.createDisplay(null, false); // no-reuse } @After @@ -121,6 +124,7 @@ public class TestParenting04SWT extends UITestCase { throwable.printStackTrace(); Assume.assumeNoException( throwable ); } + swtNewtDisplay = null; display = null; shell1 = null; shell2 = null; @@ -141,13 +145,15 @@ public class TestParenting04SWT extends UITestCase { } protected void winHopFrame2Frame(final boolean detachFirst) throws InterruptedException, InvocationTargetException { - final GLWindow glWindow1 = GLWindow.create(glCaps); + com.jogamp.newt.Screen screen = NewtFactory.createScreen(swtNewtDisplay, 0); + + final GLWindow glWindow1 = GLWindow.create(screen, glCaps); GLEventListener demo1 = new RedSquareES2(); setDemoFields(demo1, glWindow1, false); glWindow1.addGLEventListener(demo1); Animator anim1 = new Animator(glWindow1); - final GLWindow glWindow2 = GLWindow.create(glCaps); + final GLWindow glWindow2 = GLWindow.create(screen, glCaps); GLEventListener demo2 = new GearsES2(); setDemoFields(demo2, glWindow2, false); glWindow2.addGLEventListener(demo2); |