diff options
Diffstat (limited to 'src/newt/classes/com')
-rw-r--r-- | src/newt/classes/com/jogamp/newt/swt/NewtCanvasSWT.java | 10 | ||||
-rw-r--r-- | src/newt/classes/com/jogamp/newt/swt/SWTEDTUtil.java | 217 | ||||
-rw-r--r-- | src/newt/classes/com/jogamp/newt/util/EDTUtil.java | 40 |
3 files changed, 234 insertions, 33 deletions
diff --git a/src/newt/classes/com/jogamp/newt/swt/NewtCanvasSWT.java b/src/newt/classes/com/jogamp/newt/swt/NewtCanvasSWT.java index f45b864fa..cada253bc 100644 --- a/src/newt/classes/com/jogamp/newt/swt/NewtCanvasSWT.java +++ b/src/newt/classes/com/jogamp/newt/swt/NewtCanvasSWT.java @@ -67,9 +67,6 @@ public class NewtCanvasSWT extends Canvas implements WindowClosingProtocol { private static final boolean DEBUG = Debug.debug("Window"); private static final boolean isOSX = NativeWindowFactory.TYPE_MACOSX == NativeWindowFactory.getNativeWindowType(false); - /** SWT EDTUtil associated w/ parent's SWT Display */ - private final EDTUtil swtEDTUtil; - private final AbstractGraphicsScreen screen; private WindowClosingMode newtChildCloseOp = WindowClosingMode.DISPOSE_ON_CLOSE; @@ -117,8 +114,6 @@ public class NewtCanvasSWT extends Canvas implements WindowClosingProtocol { public NewtCanvasSWT(final Composite parent, final int style, Window child) { super(parent, style | SWT.NO_BACKGROUND); - swtEDTUtil = new SWTEDTUtil(parent.getDisplay()); - SWTAccessor.setRealized(this, true); clientArea = getClientArea(); @@ -326,8 +321,9 @@ public class NewtCanvasSWT extends Canvas implements WindowClosingProtocol { updateSizeCheck(); final int w = clientArea.width; final int h = clientArea.height; - - newtChild.getScreen().getDisplay().setEDTUtil(swtEDTUtil); + + final Display newtDisplay = newtChild.getScreen().getDisplay(); + newtDisplay.setEDTUtil(new SWTEDTUtil(newtDisplay, getDisplay())); newtChild.setSize(w, h); newtChild.reparentWindow(nativeWindow); diff --git a/src/newt/classes/com/jogamp/newt/swt/SWTEDTUtil.java b/src/newt/classes/com/jogamp/newt/swt/SWTEDTUtil.java index 3538caad2..d4b83d891 100644 --- a/src/newt/classes/com/jogamp/newt/swt/SWTEDTUtil.java +++ b/src/newt/classes/com/jogamp/newt/swt/SWTEDTUtil.java @@ -27,7 +27,9 @@ */ package com.jogamp.newt.swt; -import org.eclipse.swt.widgets.Display; +import java.awt.EventQueue; + +import jogamp.newt.Debug; import com.jogamp.newt.util.EDTUtil; @@ -36,64 +38,243 @@ import com.jogamp.newt.util.EDTUtil; * of the given {@link Display}. */ public class SWTEDTUtil implements EDTUtil { - private final Display swtDisplay; + public static final boolean DEBUG = Debug.debug("EDT"); + + private final Object edtLock = new Object(); // locking the EDT start/stop state + private final ThreadGroup threadGroup; + private final String name; + private final Runnable dispatchMessages; + private final org.eclipse.swt.widgets.Display swtDisplay; + private NewtEventDispatchThread nedt = null; + private int start_iter=0; + private static long pollPeriod = EDTUtil.defaultEDTPollPeriod; - public SWTEDTUtil(Display swtDisplay) { + public SWTEDTUtil(final com.jogamp.newt.Display newtDisplay, org.eclipse.swt.widgets.Display swtDisplay) { + this.threadGroup = Thread.currentThread().getThreadGroup(); + this.name=Thread.currentThread().getName()+"-SWTDisplay-"+newtDisplay.getFQName()+"-EDT-"; + this.dispatchMessages = new Runnable() { + public void run() { + ((jogamp.newt.DisplayImpl) newtDisplay).dispatchMessages(); + } }; this.swtDisplay = swtDisplay; + this.nedt = new NewtEventDispatchThread(threadGroup, name); + this.nedt.setDaemon(true); // don't stop JVM from shutdown .. } - public final Display getDisplay() { + public final org.eclipse.swt.widgets.Display getDisplay() { return swtDisplay; } @Override public long getPollPeriod() { - return 0; + return pollPeriod; } @Override public void setPollPeriod(long ms) { + pollPeriod = ms; } @Override public void reset() { + synchronized(edtLock) { + waitUntilStopped(); + if(DEBUG) { + System.err.println(Thread.currentThread()+": EDT reset - edt: "+nedt); + } + this.nedt = new NewtEventDispatchThread(threadGroup, name); + this.nedt.setDaemon(true); // don't stop JVM from shutdown .. + } } - @Override - public void start() { + private final void startImpl() { + if(nedt.isAlive()) { + throw new RuntimeException("EDT Thread.isAlive(): true, isRunning: "+nedt.isRunning()+", edt: "+nedt); + } + start_iter++; + nedt.setName(name+start_iter); + nedt.shouldStop = false; + if(DEBUG) { + System.err.println(Thread.currentThread()+": EDT START - edt: "+nedt); + // Thread.dumpStack(); + } + nedt.start(); } - + @Override public boolean isCurrentThreadEDT() { return swtDisplay.getThread() == Thread.currentThread(); } @Override + public final boolean isCurrentThreadNEDT() { + return nedt == Thread.currentThread(); + } + + @Override + public final boolean isCurrentThreadEDTorNEDT() { + final Thread ct = Thread.currentThread(); + return ct == swtDisplay.getThread() || ct == nedt ; + } + + @Override public boolean isRunning() { - return true; + return nedt.isRunning() ; // SWT is always running } - + @Override - public void invokeStop(Runnable finalTask) { - swtDisplay.syncExec(finalTask); + public final void invokeStop(Runnable task) { + invokeImpl(true, task, true); } @Override - public void invoke(boolean wait, Runnable task) { + public final void invoke(boolean wait, Runnable task) { + invokeImpl(wait, task, false); + } + + private void invokeImpl(boolean wait, Runnable task, boolean stop) { + 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(); + } + 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(); + } + } + + // start if should not stop && not started yet + if( !stop && !nedt.isRunning() ) { + startImpl(); + } + } if(wait) { swtDisplay.syncExec(task); } else { swtDisplay.asyncExec(task); } - } + } @Override - public void waitUntilIdle() { - // all sync .. + final public void waitUntilIdle() { + final NewtEventDispatchThread _edt; + synchronized(edtLock) { + _edt = nedt; + } + if(!_edt.isRunning() || EventQueue.isDispatchThread() || _edt == Thread.currentThread()) { + return; + } + try { + swtDisplay.syncExec(new Runnable() { + public void run() { } + }); + } catch (Exception e) { } } @Override - public void waitUntilStopped() { - // all sync .. + final public void waitUntilStopped() { + synchronized(edtLock) { + if(nedt.isRunning() && nedt != Thread.currentThread() ) { + while(nedt.isRunning()) { + try { + edtLock.wait(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + } + } } + + class NewtEventDispatchThread extends Thread { + volatile boolean shouldStop = false; + volatile boolean isRunning = false; + Object sync = new Object(); + + public NewtEventDispatchThread(ThreadGroup tg, String name) { + super(tg, name); + } + + final public boolean isRunning() { + return isRunning; + } + + @Override + final public void start() throws IllegalThreadStateException { + isRunning = true; + super.start(); + } + + /** + * Utilizing locking only on tasks and its execution, + * not for event dispatching. + */ + @Override + final public void run() { + if(DEBUG) { + System.err.println(getName()+": EDT run() START "+ getName()); + } + RuntimeException error = null; + try { + do { + // event dispatch + if(!shouldStop) { + // FIXME: Determine whether we require to run the + // delivery of events (dispatch) on AWT-EDT. + // Since the WindowDriver itself delivers all Window related events, + // this shall not be required. + // AWTEDTExecutor.singleton.invoke(true, dispatchMessages); + dispatchMessages.run(); + } + // wait + synchronized(sync) { + if(!shouldStop) { + try { + sync.wait(pollPeriod); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + } + } while(!shouldStop) ; + } catch (Throwable t) { + // handle errors .. + shouldStop = true; + if(t instanceof RuntimeException) { + error = (RuntimeException) t; + } else { + error = new RuntimeException("Within EDT", t); + } + } finally { + if(DEBUG) { + System.err.println(getName()+": EDT run() END "+ getName()+", "+error); + } + synchronized(edtLock) { + isRunning = !shouldStop; + if(!isRunning) { + edtLock.notifyAll(); + } + } + if(DEBUG) { + System.err.println(getName()+": EDT run() EXIT "+ getName()+", exception: "+error); + } + if(null!=error) { + throw error; + } + } // finally + } // run() + } // EventDispatchThread + } diff --git a/src/newt/classes/com/jogamp/newt/util/EDTUtil.java b/src/newt/classes/com/jogamp/newt/util/EDTUtil.java index 4493e2781..7e19d9de5 100644 --- a/src/newt/classes/com/jogamp/newt/util/EDTUtil.java +++ b/src/newt/classes/com/jogamp/newt/util/EDTUtil.java @@ -28,6 +28,9 @@ package com.jogamp.newt.util; +import jogamp.newt.DisplayImpl; +import com.jogamp.newt.event.NEWTEvent; + /** * EDT stands for Event Dispatch Thread. * <p> @@ -63,25 +66,46 @@ public interface EDTUtil { /** * Create a new EDT. One should invoke <code>reset()</code><br> - * after <code>invokeStop(..)</code> in case another <code>start()</code> or <code>invoke(..)</code> + * after <code>invokeStop(..)</code> in case another start via <code>invoke(..)</code> * is expected. * - * @see #start() * @see #invoke(boolean, java.lang.Runnable) * @see #invokeStop(java.lang.Runnable) */ public void reset(); /** - * Start the EDT + * Returns true if the current thread is the event dispatch thread (EDT). + * <p> + * The EDT is the platform specific thread dispatching toolkit-events + * and executing toolkit-tasks enqueued via {@link #invoke(boolean, Runnable)}. + * </p> + * <p> + * Usually it is the same thread as used to dequeue informal {@link NEWTEvent}s (NEDT), see {@link #isCurrentThreadNEDT()}, + * however, this may differ, e.g. SWT and AWT implementation. + * </p> */ - public void start(); + public boolean isCurrentThreadEDT(); /** - * @return True if the current thread is the EDT thread + * Returns true if the current thread is the internal NEWT event dequeue thread (NEDT). + * <p> + * The NEDT is the NEWT thread used to dequeue informal {@link NEWTEvent}s enqueued internally + * via {@link DisplayImpl#enqueueEvent(boolean, NEWTEvent)}. + * </p> + * <p> + * Usually it is the same thread as the EDT, see {@link #isCurrentThreadEDT()}, + * however, this may differ, e.g. SWT and AWT implementation. + * </p> */ - public boolean isCurrentThreadEDT(); - + public boolean isCurrentThreadNEDT(); + + /** + * Returns <code>true</code> if either {@link #isCurrentThreadEDT()} or {@link #isCurrentThreadNEDT()} is <code>true</code>, + * otherwise <code>false</code>. + */ + public boolean isCurrentThreadEDTorNEDT(); + /** * @return True if EDT is running */ @@ -101,9 +125,9 @@ public interface EDTUtil { public void invokeStop(Runnable finalTask); /** + * Shall start the thread if not running.<br> * Append task to the EDT task queue.<br> * Wait until execution is finished if <code>wait == true</code>.<br> - * Shall start the thread if not running.<br> * Can be issued from within EDT, ie from within an enqueued task.<br> * * @throws RuntimeException in case EDT is stopped and not {@link #reset()} |