diff options
author | Sven Gothel <[email protected]> | 2012-11-27 01:55:10 +0100 |
---|---|---|
committer | Sven Gothel <[email protected]> | 2012-11-27 01:55:10 +0100 |
commit | 17dd761d7c2b224f0505a399bf4ecb18634e9250 (patch) | |
tree | d7cf306da5cf1f27e0f43a3f4de868ad9d7afc65 /src/newt | |
parent | 8cf694c1424277e6358039a964ecd75c54cf9af9 (diff) |
SWTEDTUtil/AWTEDTUtil: Fix deadlock situations ; Cleanup TestNewtCanvasSWTBug628ResizeDeadlock
- Fix deadlock situation in waitUntilStopped/Idle(), skip if on AWT/SWT EDT
- Use RunnableTask for sync task invocation, don't block AWT/SWT EDT.
- Cleanup TestNewtCanvasSWTBug628ResizeDeadlock (works on OSX as well)
Diffstat (limited to 'src/newt')
-rw-r--r-- | src/newt/classes/com/jogamp/newt/swt/SWTEDTUtil.java | 89 | ||||
-rw-r--r-- | src/newt/classes/jogamp/newt/DisplayImpl.java | 6 | ||||
-rw-r--r-- | src/newt/classes/jogamp/newt/driver/awt/AWTEDTUtil.java | 77 |
3 files changed, 111 insertions, 61 deletions
diff --git a/src/newt/classes/com/jogamp/newt/swt/SWTEDTUtil.java b/src/newt/classes/com/jogamp/newt/swt/SWTEDTUtil.java index d08fefa29..42e1c9be5 100644 --- a/src/newt/classes/com/jogamp/newt/swt/SWTEDTUtil.java +++ b/src/newt/classes/com/jogamp/newt/swt/SWTEDTUtil.java @@ -29,8 +29,11 @@ package com.jogamp.newt.swt; import java.awt.EventQueue; +import javax.media.nativewindow.NativeWindowException; + import jogamp.newt.Debug; +import com.jogamp.common.util.RunnableTask; import com.jogamp.newt.util.EDTUtil; /** @@ -136,38 +139,58 @@ public class SWTEDTUtil implements EDTUtil { if(task == null) { throw new RuntimeException("Null Runnable"); } - synchronized(edtLock) { // lock the EDT status - if( nedt.shouldStop ) { - // drop task .. - if(DEBUG) { - System.err.println("Warning: EDT about (1) to stop, won't enqueue new task: "+nedt); - Thread.dumpStack(); + Throwable throwable = null; + RunnableTask rTask = null; + 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("Warning: EDT about (1) to stop, won't enqueue new task: "+nedt); + Thread.dumpStack(); + } + return; } - return; - } - // System.err.println(Thread.currentThread()+" XXX stop: "+stop+", tasks: "+edt.tasks.size()+", task: "+task); - // Thread.dumpStack(); - if(stop) { - nedt.shouldStop = true; - if(DEBUG) { - System.err.println(Thread.currentThread()+": EDT signal STOP (on edt: "+isCurrentThreadEDT()+") - "+nedt); - // Thread.dumpStack(); + // System.err.println(Thread.currentThread()+" XXX stop: "+stop+", tasks: "+edt.tasks.size()+", task: "+task); + // Thread.dumpStack(); + if(stop) { + nedt.shouldStop = true; + if(DEBUG) { + System.err.println(Thread.currentThread()+": EDT signal STOP (on edt: "+isCurrentThreadEDT()+") - "+nedt); + // Thread.dumpStack(); + } + } + if( isCurrentThreadEDT() ) { + task.run(); + wait = false; // running in same thread (EDT) -> no wait + } else if( swtDisplay.isDisposed() ) { + wait = false; // drop task, SWT disposed + } else { + // start if should not stop && not started yet + if( !stop && !nedt.isRunning() ) { + startImpl(); + } + rTask = new RunnableTask(task, + wait ? rTaskLock : null, + true /* always catch and report Exceptions, don't disturb EDT */); + swtDisplay.asyncExec(rTask); } } - if( isCurrentThreadEDT() ) { - task.run(); - wait = false; // running in same thread (EDT) -> no wait - } else if( swtDisplay.isDisposed() ) { - wait = false; // drop task, SWT disposed - } else { - // start if should not stop && not started yet - if( !stop && !nedt.isRunning() ) { - startImpl(); + if( wait ) { + try { + rTaskLock.wait(); // free lock, allow execution of rTask + } catch (InterruptedException ie) { + throwable = ie; } - if(wait) { - swtDisplay.syncExec(task); - } else { - swtDisplay.asyncExec(task); + if(null==throwable) { + throwable = rTask.getThrowable(); + } + if(null!=throwable) { + if(throwable instanceof NativeWindowException) { + throw (NativeWindowException)throwable; + } + throw new RuntimeException(throwable); } } } @@ -175,11 +198,12 @@ public class SWTEDTUtil implements EDTUtil { @Override final public void waitUntilIdle() { - final NewtEventDispatchThread _edt; + final NewtEventDispatchThread _nedt; synchronized(edtLock) { - _edt = nedt; + _nedt = nedt; } - if(!_edt.isRunning() || EventQueue.isDispatchThread() || _edt == Thread.currentThread()) { + final Thread ct = Thread.currentThread(); + if(!_nedt.isRunning() || _nedt == ct || swtDisplay.getThread() == ct) { return; } try { @@ -192,7 +216,8 @@ public class SWTEDTUtil implements EDTUtil { @Override final public void waitUntilStopped() { synchronized(edtLock) { - if(nedt.isRunning() && nedt != Thread.currentThread() ) { + final Thread ct = Thread.currentThread(); + if(nedt.isRunning() && nedt != ct && swtDisplay.getThread() != ct) { while(nedt.isRunning()) { try { edtLock.wait(); diff --git a/src/newt/classes/jogamp/newt/DisplayImpl.java b/src/newt/classes/jogamp/newt/DisplayImpl.java index fbccc5767..317535805 100644 --- a/src/newt/classes/jogamp/newt/DisplayImpl.java +++ b/src/newt/classes/jogamp/newt/DisplayImpl.java @@ -366,12 +366,10 @@ public abstract class DisplayImpl extends Display { private ArrayList<NEWTEventTask> events = new ArrayList<NEWTEventTask>(); private volatile boolean haveEvents = false; - class DispatchMessagesRunnable implements Runnable { + final protected Runnable dispatchMessagesRunnable = new Runnable() { public void run() { DisplayImpl.this.dispatchMessages(); - } - } - protected DispatchMessagesRunnable dispatchMessagesRunnable = new DispatchMessagesRunnable(); + } }; final void dispatchMessage(final NEWTEventTask eventTask) { final NEWTEvent event = eventTask.get(); diff --git a/src/newt/classes/jogamp/newt/driver/awt/AWTEDTUtil.java b/src/newt/classes/jogamp/newt/driver/awt/AWTEDTUtil.java index 01b5ad8a4..2175f2190 100644 --- a/src/newt/classes/jogamp/newt/driver/awt/AWTEDTUtil.java +++ b/src/newt/classes/jogamp/newt/driver/awt/AWTEDTUtil.java @@ -30,6 +30,9 @@ package jogamp.newt.driver.awt; import java.awt.EventQueue; +import javax.media.nativewindow.NativeWindowException; + +import com.jogamp.common.util.RunnableTask; import com.jogamp.newt.util.EDTUtil; import jogamp.common.awt.AWTEDTExecutor; @@ -124,33 +127,57 @@ public class AWTEDTUtil implements EDTUtil { if(task == null) { throw new RuntimeException("Null Runnable"); } - synchronized(edtLock) { // lock the EDT status - if( nedt.shouldStop ) { - // drop task .. - if(DEBUG) { - System.err.println("Warning: EDT about (1) to stop, won't enqueue new task: "+nedt); - Thread.dumpStack(); + Throwable throwable = null; + RunnableTask rTask = null; + 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("Warning: EDT about (1) to stop, won't enqueue new task: "+nedt); + Thread.dumpStack(); + } + return; } - return; - } - // System.err.println(Thread.currentThread()+" XXX stop: "+stop+", tasks: "+edt.tasks.size()+", task: "+task); - // Thread.dumpStack(); - if(stop) { - nedt.shouldStop = true; - if(DEBUG) { - System.err.println(Thread.currentThread()+": EDT signal STOP (on edt: "+isCurrentThreadEDT()+") - "+nedt); - // Thread.dumpStack(); + // System.err.println(Thread.currentThread()+" XXX stop: "+stop+", tasks: "+edt.tasks.size()+", task: "+task); + // Thread.dumpStack(); + if(stop) { + nedt.shouldStop = true; + if(DEBUG) { + System.err.println(Thread.currentThread()+": EDT signal STOP (on edt: "+isCurrentThreadEDT()+") - "+nedt); + // Thread.dumpStack(); + } + } + if( isCurrentThreadEDT() ) { + task.run(); + wait = false; // running in same thread (EDT) -> no wait + } else { + // start if should not stop && not started yet + if( !stop && !nedt.isRunning() ) { + startImpl(); + } + rTask = new RunnableTask(task, + wait ? rTaskLock : null, + true /* always catch and report Exceptions, don't disturb EDT */); + AWTEDTExecutor.singleton.invoke(false, rTask); } } - if( isCurrentThreadEDT() ) { - task.run(); - wait = false; // running in same thread (EDT) -> no wait - } else { - // start if should not stop && not started yet - if( !stop && !nedt.isRunning() ) { - startImpl(); + if( wait ) { + try { + rTaskLock.wait(); // free lock, allow execution of rTask + } catch (InterruptedException ie) { + throwable = ie; + } + if(null==throwable) { + throwable = rTask.getThrowable(); + } + if(null!=throwable) { + if(throwable instanceof NativeWindowException) { + throw (NativeWindowException)throwable; + } + throw new RuntimeException(throwable); } - AWTEDTExecutor.singleton.invoke(wait, task); } } } @@ -161,7 +188,7 @@ public class AWTEDTUtil implements EDTUtil { synchronized(edtLock) { _edt = nedt; } - if(!_edt.isRunning() || EventQueue.isDispatchThread() || _edt == Thread.currentThread()) { + if(!_edt.isRunning() || _edt == Thread.currentThread() || EventQueue.isDispatchThread()) { return; } try { @@ -174,7 +201,7 @@ public class AWTEDTUtil implements EDTUtil { @Override final public void waitUntilStopped() { synchronized(edtLock) { - if(nedt.isRunning() && nedt != Thread.currentThread() ) { + if(nedt.isRunning() && nedt != Thread.currentThread() && !EventQueue.isDispatchThread()) { while(nedt.isRunning()) { try { edtLock.wait(); |