summaryrefslogtreecommitdiffstats
path: root/src/newt/classes/com
diff options
context:
space:
mode:
authorSven Gothel <[email protected]>2012-09-07 08:32:31 +0200
committerSven Gothel <[email protected]>2012-09-07 08:32:31 +0200
commit1b6593f973970ad00a0a0f08b56cc83501a55ad2 (patch)
tree18b2498161e255d82e80f4f639dc54bfa89a7ace /src/newt/classes/com
parentf2cfb6119a3663715ed2d572643949b3bef58662 (diff)
NEWT EDTUtil: Complete AWT and SWT impl. w/ Newt event dequeue thread (NEDT)
AWT and SWT impl. use the toolkit thread to deliver toolkit events and to execute task. However, NEWT dispatches event using its own queue for NEWT events. Adding a simple thread to dequeue those. Remove 'EDTUtil.start()', since this is implicit @ invoke().
Diffstat (limited to 'src/newt/classes/com')
-rw-r--r--src/newt/classes/com/jogamp/newt/swt/NewtCanvasSWT.java10
-rw-r--r--src/newt/classes/com/jogamp/newt/swt/SWTEDTUtil.java217
-rw-r--r--src/newt/classes/com/jogamp/newt/util/EDTUtil.java40
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()}