From 1b6593f973970ad00a0a0f08b56cc83501a55ad2 Mon Sep 17 00:00:00 2001 From: Sven Gothel Date: Fri, 7 Sep 2012 08:32:31 +0200 Subject: 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(). --- src/newt/classes/jogamp/newt/DefaultEDTUtil.java | 62 ++++-- src/newt/classes/jogamp/newt/DisplayImpl.java | 9 +- .../classes/jogamp/newt/driver/awt/AWTEDTUtil.java | 221 ++++++++++++++++++--- .../jogamp/newt/driver/awt/DisplayDriver.java | 10 +- 4 files changed, 243 insertions(+), 59 deletions(-) (limited to 'src/newt/classes/jogamp') diff --git a/src/newt/classes/jogamp/newt/DefaultEDTUtil.java b/src/newt/classes/jogamp/newt/DefaultEDTUtil.java index bdbe96070..18418a8dc 100644 --- a/src/newt/classes/jogamp/newt/DefaultEDTUtil.java +++ b/src/newt/classes/jogamp/newt/DefaultEDTUtil.java @@ -49,12 +49,12 @@ import com.jogamp.newt.util.EDTUtil; public class DefaultEDTUtil implements EDTUtil { public static final boolean DEBUG = Debug.debug("EDT"); - private ThreadGroup threadGroup; + 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 EventDispatchThread edt = null; - private Object edtLock = new Object(); // locking the EDT start/stop state - private String name; - int start_iter=0; - private Runnable dispatchMessages; + private int start_iter=0; private static long pollPeriod = EDTUtil.defaultEDTPollPeriod; public DefaultEDTUtil(ThreadGroup tg, String name, Runnable dispatchMessages) { @@ -65,14 +65,17 @@ public class DefaultEDTUtil implements EDTUtil { this.edt.setDaemon(true); // don't stop JVM from shutdown .. } + @Override final public long getPollPeriod() { return pollPeriod; } + @Override final public void setPollPeriod(long ms) { pollPeriod = ms; } + @Override public final void reset() { synchronized(edtLock) { waitUntilStopped(); @@ -88,36 +91,46 @@ public class DefaultEDTUtil implements EDTUtil { } } - public final void start() { - synchronized(edtLock) { - if(!edt.isRunning() && !edt.shouldStop) { - if(edt.isAlive()) { - throw new RuntimeException("EDT Thread.isAlive(): true, isRunning: "+edt.isRunning()+", edt: "+edt+", tasks: "+edt.tasks.size()); - } - start_iter++; - edt.setName(name+start_iter); - edt.shouldStop = false; - if(DEBUG) { - System.err.println(Thread.currentThread()+": EDT START - edt: "+edt); - // Thread.dumpStack(); - } - edt.start(); - } + private final void startImpl() { + if(edt.isAlive()) { + throw new RuntimeException("EDT Thread.isAlive(): true, isRunning: "+edt.isRunning()+", edt: "+edt+", tasks: "+edt.tasks.size()); } + start_iter++; + edt.setName(name+start_iter); + edt.shouldStop = false; + if(DEBUG) { + System.err.println(Thread.currentThread()+": EDT START - edt: "+edt); + // Thread.dumpStack(); + } + edt.start(); } + @Override public final boolean isCurrentThreadEDT() { - return edt == Thread.currentThread(); + return edt == Thread.currentThread(); // EDT == NEDT + } + + @Override + public final boolean isCurrentThreadNEDT() { + return edt == Thread.currentThread(); // EDT == NEDT } + @Override + public final boolean isCurrentThreadEDTorNEDT() { + return edt == Thread.currentThread(); // EDT == NEDT + } + + @Override public final boolean isRunning() { return edt.isRunning() ; } + @Override public final void invokeStop(Runnable task) { invokeImpl(true, task, true); } + @Override public final void invoke(boolean wait, Runnable task) { invokeImpl(wait, task, false); } @@ -158,8 +171,11 @@ public class DefaultEDTUtil implements EDTUtil { } } } else { + // start if should not stop && not started yet + if( !stop && !edt.isRunning() ) { + startImpl(); + } synchronized(edt.tasks) { - start(); // start if not started yet and !shouldStop wait = wait && edt.isRunning(); rTask = new RunnableTask(task, wait ? rTaskLock : null, @@ -195,6 +211,7 @@ public class DefaultEDTUtil implements EDTUtil { } } + @Override final public void waitUntilIdle() { final EventDispatchThread _edt; synchronized(edtLock) { @@ -215,6 +232,7 @@ public class DefaultEDTUtil implements EDTUtil { } } + @Override final public void waitUntilStopped() { synchronized(edtLock) { if(edt.isRunning() && edt != Thread.currentThread() ) { diff --git a/src/newt/classes/jogamp/newt/DisplayImpl.java b/src/newt/classes/jogamp/newt/DisplayImpl.java index bac4031f0..bca7f6e5b 100644 --- a/src/newt/classes/jogamp/newt/DisplayImpl.java +++ b/src/newt/classes/jogamp/newt/DisplayImpl.java @@ -169,8 +169,7 @@ public abstract class DisplayImpl extends Display { public EDTUtil setEDTUtil(EDTUtil newEDTUtil) { if(null == newEDTUtil) { newEDTUtil = createEDTUtil(); - } - if( newEDTUtil == edtUtil ) { + } else if( newEDTUtil == edtUtil ) { if(DEBUG) { System.err.println("Display.setEDTUtil: "+newEDTUtil+" - keep!"); } @@ -366,7 +365,7 @@ public abstract class DisplayImpl extends Display { DisplayImpl.this.dispatchMessages(); } } - DispatchMessagesRunnable dispatchMessagesRunnable = new DispatchMessagesRunnable(); + protected DispatchMessagesRunnable dispatchMessagesRunnable = new DispatchMessagesRunnable(); final void dispatchMessage(final NEWTEventTask eventTask) { final NEWTEvent event = eventTask.get(); @@ -446,8 +445,8 @@ public abstract class DisplayImpl extends Display { return; } - // can't wait if we are on EDT -> consume right away - if(wait && edtUtil.isCurrentThreadEDT()) { + // can't wait if we are on EDT or NEDT -> consume right away + if(wait && edtUtil.isCurrentThreadEDTorNEDT() ) { dispatchMessage(new NEWTEventTask(e, null)); return; } diff --git a/src/newt/classes/jogamp/newt/driver/awt/AWTEDTUtil.java b/src/newt/classes/jogamp/newt/driver/awt/AWTEDTUtil.java index 942651187..8771f5c74 100644 --- a/src/newt/classes/jogamp/newt/driver/awt/AWTEDTUtil.java +++ b/src/newt/classes/jogamp/newt/driver/awt/AWTEDTUtil.java @@ -28,72 +28,239 @@ package jogamp.newt.driver.awt; -import javax.media.opengl.Threading; +import java.awt.EventQueue; import com.jogamp.newt.util.EDTUtil; + +import jogamp.common.awt.AWTEDTExecutor; import jogamp.newt.Debug; public class AWTEDTUtil implements EDTUtil { public static final boolean DEBUG = Debug.debug("EDT"); - - private static AWTEDTUtil singletonMainThread = new AWTEDTUtil(); // one singleton MainThread - public static AWTEDTUtil getSingleton() { - return singletonMainThread; - } + 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 NewtEventDispatchThread nedt = null; + private int start_iter=0; + private static long pollPeriod = EDTUtil.defaultEDTPollPeriod; - AWTEDTUtil() { - // package private access .. + public AWTEDTUtil(ThreadGroup tg, String name, Runnable dispatchMessages) { + this.threadGroup = tg; + this.name=Thread.currentThread().getName()+"-"+name+"-EDT-"; + this.dispatchMessages=dispatchMessages; + this.nedt = new NewtEventDispatchThread(threadGroup, name); + this.nedt.setDaemon(true); // don't stop JVM from shutdown .. } + @Override final public long getPollPeriod() { - return 0; + return pollPeriod; } + @Override final public void setPollPeriod(long ms) { - // nop + pollPeriod = ms; } + @Override final public void reset() { - // nop AWT is always running + 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 .. + } } - final public void start() { - // nop AWT is always running + 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 final public boolean isCurrentThreadEDT() { - return Threading.isToolkitThread(); + return EventQueue.isDispatchThread(); } + @Override + public final boolean isCurrentThreadNEDT() { + return nedt == Thread.currentThread(); + } + + @Override + public final boolean isCurrentThreadEDTorNEDT() { + return EventQueue.isDispatchThread() || nedt == Thread.currentThread(); + } + + @Override final public boolean isRunning() { - return true; // AWT is always running + return nedt.isRunning() ; // AWT is always running } - final public void invokeStop(Runnable r) { - invoke(true, r); // AWT is always running + @Override + public final void invokeStop(Runnable task) { + invokeImpl(true, task, true); } - final public void invoke(boolean wait, Runnable r) { - if(r == null) { - return; - } - - Threading.invoke(wait, r, null); + @Override + 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(); + } + } + AWTEDTExecutor.singleton.invoke(wait, task); + } + @Override final public void waitUntilIdle() { - // wait until previous events are processed, at least .. + final NewtEventDispatchThread _edt; + synchronized(edtLock) { + _edt = nedt; + } + if(!_edt.isRunning() || EventQueue.isDispatchThread() || _edt == Thread.currentThread()) { + return; + } try { - Threading.invoke(true, new Runnable() { + AWTEDTExecutor.singleton.invoke(true, new Runnable() { public void run() { } - }, null); + }); } catch (Exception e) { } } + @Override final public void waitUntilStopped() { - // nop: AWT is always running + 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/jogamp/newt/driver/awt/DisplayDriver.java b/src/newt/classes/jogamp/newt/driver/awt/DisplayDriver.java index 39d96585b..70e9ba570 100644 --- a/src/newt/classes/jogamp/newt/driver/awt/DisplayDriver.java +++ b/src/newt/classes/jogamp/newt/driver/awt/DisplayDriver.java @@ -38,6 +38,7 @@ import com.jogamp.nativewindow.awt.AWTGraphicsDevice; import com.jogamp.newt.NewtFactory; import com.jogamp.newt.util.EDTUtil; +import jogamp.newt.DefaultEDTUtil; import jogamp.newt.DisplayImpl; public class DisplayDriver extends DisplayImpl { @@ -52,15 +53,12 @@ public class DisplayDriver extends DisplayImpl { aDevice = d; } - protected void closeNativeImpl() { } - - @Override protected EDTUtil createEDTUtil() { final EDTUtil def; if(NewtFactory.useEDT()) { - def = AWTEDTUtil.getSingleton(); + def = new AWTEDTUtil(Thread.currentThread().getThreadGroup(), "AWTDisplay-"+getFQName(), dispatchMessagesRunnable); if(DEBUG) { - System.err.println("AWTDisplay.createNative("+getFQName()+") Create EDTUtil: "+def.getClass().getName()); + System.err.println("Display.createNative("+getFQName()+") Create EDTUtil: "+def.getClass().getName()); } } else { def = null; @@ -68,6 +66,8 @@ public class DisplayDriver extends DisplayImpl { return def; } + protected void closeNativeImpl() { } + protected void dispatchMessagesNative() { /* nop */ } } -- cgit v1.2.3