From 1c1053c6a8b669c067ae1316b9770871e213ea05 Mon Sep 17 00:00:00 2001 From: Sven Gothel Date: Tue, 13 Apr 2010 20:48:50 +0200 Subject: NEWT X11 Fix (mainly ATI and multithreading) - EventDispatchThread -> EDTUtil Since the name leads to the assumptions that an instance is the EDT. EDTUtil manages the EDT within. - EDTUtil, no more reference to Display, but use a Runnable for the pumpMessage() - Window.destroy() check if already done - X11Window: Added XErrorHandler to catch BadWindow and BadAtom while dispatching events - it is possible that the resource is already freed. Also added an XIOErrorHandler to identify the fatal Display* inaccessibility. Tests: - New junit/com/jogamp/test/junit/newt/TestWindows01NEWT.java Testing creation/destruction and double destruction (error case) - Fix: src/junit/com/jogamp/test/junit/jogl/offscreen/TestOffscreen01NEWT.java Properly holding all NEWT references .. Misc: - Reduced redundant NEWT 'toString()' output (*Capabilities, ..) - --- src/newt/classes/com/jogamp/newt/Display.java | 47 ++-- src/newt/classes/com/jogamp/newt/Window.java | 63 +++--- .../classes/com/jogamp/newt/opengl/GLWindow.java | 6 +- src/newt/classes/com/jogamp/newt/util/EDTUtil.java | 244 +++++++++++++++++++++ .../com/jogamp/newt/util/EventDispatchThread.java | 240 -------------------- 5 files changed, 306 insertions(+), 294 deletions(-) create mode 100644 src/newt/classes/com/jogamp/newt/util/EDTUtil.java delete mode 100644 src/newt/classes/com/jogamp/newt/util/EventDispatchThread.java (limited to 'src/newt/classes/com') diff --git a/src/newt/classes/com/jogamp/newt/Display.java b/src/newt/classes/com/jogamp/newt/Display.java index 88f6dd34b..2bc99475c 100755 --- a/src/newt/classes/com/jogamp/newt/Display.java +++ b/src/newt/classes/com/jogamp/newt/Display.java @@ -35,7 +35,7 @@ package com.jogamp.newt; import javax.media.nativewindow.*; import com.jogamp.newt.impl.Debug; -import com.jogamp.newt.util.EventDispatchThread; +import com.jogamp.newt.util.EDTUtil; import java.util.*; public abstract class Display { @@ -141,11 +141,16 @@ public abstract class Display { display.refCount=1; if(NewtFactory.useEDT()) { - Thread current = Thread.currentThread(); - display.eventDispatchThread = new EventDispatchThread(display, current.getThreadGroup(), current.getName()); - display.eventDispatchThread.start(); final Display f_dpy = display; - display.eventDispatchThread.invokeAndWait(new Runnable() { + Thread current = Thread.currentThread(); + display.edtUtil = new EDTUtil(current.getThreadGroup(), + "Display_"+display.getName()+"-"+current.getName(), + new Runnable() { + public void run() { + f_dpy.pumpMessagesImpl(); + } } ); + display.edt = display.edtUtil.start(); + display.edtUtil.invokeAndWait(new Runnable() { public void run() { f_dpy.createNative(); } @@ -189,7 +194,7 @@ public abstract class Display { } } - public EventDispatchThread getEDT() { return eventDispatchThread; } + public EDTUtil getEDTUtil() { return edtUtil; } public synchronized void destroy() { if(DEBUG) { @@ -201,10 +206,10 @@ public abstract class Display { if(DEBUG) { System.err.println("Display.destroy("+name+") REMOVE: "+this+" "+Thread.currentThread()); } - if(null!=eventDispatchThread) { + if(null!=edtUtil) { final Display f_dpy = this; - final EventDispatchThread f_edt = eventDispatchThread; - eventDispatchThread.invokeAndWait(new Runnable() { + final EDTUtil f_edt = edtUtil; + edtUtil.invokeAndWait(new Runnable() { public void run() { f_dpy.closeNative(); f_edt.stop(); @@ -213,9 +218,9 @@ public abstract class Display { } else { closeNative(); } - if(null!=eventDispatchThread) { - eventDispatchThread.waitUntilStopped(); - eventDispatchThread=null; + if(null!=edtUtil) { + edtUtil.waitUntilStopped(); + edtUtil=null; } aDevice = null; } else { @@ -246,14 +251,13 @@ public abstract class Display { return aDevice; } - public void pumpMessages() { - if(null!=eventDispatchThread) { - dispatchMessages(); - } else { - synchronized(this) { - dispatchMessages(); - } - } + public synchronized void pumpMessages() { + pumpMessagesImpl(); + } + + private void pumpMessagesImpl() { + if(0==refCount) return; + dispatchMessages(); } public String toString() { @@ -268,7 +272,8 @@ public abstract class Display { /** Default impl. nop - Currently only X11 needs a Display lock */ protected void unlockDisplay() { } - protected EventDispatchThread eventDispatchThread = null; + protected EDTUtil edtUtil = null; + protected Thread edt = null; protected String name; protected int refCount; protected AbstractGraphicsDevice aDevice; diff --git a/src/newt/classes/com/jogamp/newt/Window.java b/src/newt/classes/com/jogamp/newt/Window.java index 171bb2468..8f09ae364 100755 --- a/src/newt/classes/com/jogamp/newt/Window.java +++ b/src/newt/classes/com/jogamp/newt/Window.java @@ -34,7 +34,7 @@ package com.jogamp.newt; import com.jogamp.newt.impl.Debug; -import com.jogamp.newt.util.EventDispatchThread; +import com.jogamp.newt.util.EDTUtil; import javax.media.nativewindow.*; import com.jogamp.nativewindow.impl.NWReflection; @@ -98,10 +98,10 @@ public abstract class Window implements NativeWindow window.invalidate(); window.screen = screen; window.setUndecorated(undecorated||0!=parentWindowHandle); - EventDispatchThread edt = screen.getDisplay().getEDT(); - if(null!=edt) { + EDTUtil edtUtil = screen.getDisplay().getEDTUtil(); + if(null!=edtUtil) { final Window f_win = window; - edt.invokeAndWait(new Runnable() { + edtUtil.invokeAndWait(new Runnable() { public void run() { f_win.createNative(parentWindowHandle, caps); } @@ -131,10 +131,10 @@ public abstract class Window implements NativeWindow window.invalidate(); window.screen = screen; window.setUndecorated(undecorated); - EventDispatchThread edt = screen.getDisplay().getEDT(); - if(null!=edt) { + EDTUtil edtUtil = screen.getDisplay().getEDTUtil(); + if(null!=edtUtil) { final Window f_win = window; - edt.invokeAndWait(new Runnable() { + edtUtil.invokeAndWait(new Runnable() { public void run() { f_win.createNative(0, caps); } @@ -212,15 +212,15 @@ public abstract class Window implements NativeWindow public String toString() { StringBuffer sb = new StringBuffer(); - sb.append(getClass().getName()+"[config "+config+ - ", windowHandle "+toHexString(getWindowHandle())+ - ", surfaceHandle "+toHexString(getSurfaceHandle())+ - ", pos "+getX()+"/"+getY()+", size "+getWidth()+"x"+getHeight()+ - ", visible "+isVisible()+ - ", undecorated "+undecorated+ - ", fullscreen "+fullscreen+ + sb.append(getClass().getName()+"[Config "+config+ + ", WindowHandle "+toHexString(getWindowHandle())+ + ", SurfaceHandle "+toHexString(getSurfaceHandle())+ + ", Pos "+getX()+"/"+getY()+", size "+getWidth()+"x"+getHeight()+ + ", Visible "+isVisible()+ + ", Undecorated "+undecorated+ + ", Fullscreen "+fullscreen+ ", "+screen+ - ", wrappedWindow "+getWrappedWindow()); + ", WrappedWindow "+getWrappedWindow()); sb.append(", SurfaceUpdatedListeners num "+surfaceUpdatedListeners.size()+" ["); for (Iterator iter = surfaceUpdatedListeners.iterator(); iter.hasNext(); ) { @@ -343,25 +343,28 @@ public abstract class Window implements NativeWindow keyListeners = new ArrayList(); } synchronized(this) { - destructionLock.lock(); try { - Screen scr = screen; - Display dpy = (null!=screen) ? screen.getDisplay() : null; - EventDispatchThread edt = (null!=dpy) ? dpy.getEDT() : null; - if(null!=edt) { - final Window f_win = this; - edt.invokeAndWait(new Runnable() { - public void run() { - f_win.closeNative(); - } - } ); - } else { - closeNative(); + destructionLock.lock(); + Display dpy = null; + if( null != screen && 0 != windowHandle ) { + Screen scr = screen; + dpy = (null!=screen) ? screen.getDisplay() : null; + EDTUtil edtUtil = (null!=dpy) ? dpy.getEDTUtil() : null; + if(null!=edtUtil) { + final Window f_win = this; + edtUtil.invokeAndWait(new Runnable() { + public void run() { + f_win.closeNative(); + } + } ); + } else { + closeNative(); + } } invalidate(); if(deep) { - if(null!=scr) { - scr.destroy(); + if(null!=screen) { + screen.destroy(); } if(null!=dpy) { dpy.destroy(); diff --git a/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java b/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java index 4a7f27f3a..fec70c99c 100644 --- a/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java +++ b/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java @@ -65,7 +65,7 @@ public class GLWindow extends Window implements GLAutoDrawable { this.ownerOfWinScrDpy = ownerOfWinScrDpy; this.window = window; this.window.setAutoDrawableClient(true); - this.runPumpMessages = ( null == getScreen().getDisplay().getEDT() ) ; + this.runPumpMessages = ( null == getScreen().getDisplay().getEDTUtil() ) ; window.addWindowListener(new WindowListener() { public void windowResized(WindowEvent e) { sendReshape = true; @@ -152,7 +152,7 @@ public class GLWindow extends Window implements GLAutoDrawable { * @deprecated EXPERIMENTAL, semantic is about to be removed after further verification. */ public void setRunPumpMessages(boolean onoff) { - if( onoff && null!=getScreen().getDisplay().getEDT() ) { + if( onoff && null!=getScreen().getDisplay().getEDTUtil() ) { throw new GLException("GLWindow.setRunPumpMessages(true) - Can't do with EDT on"); } runPumpMessages = onoff; @@ -382,7 +382,7 @@ public class GLWindow extends Window implements GLAutoDrawable { } public String toString() { - return "NEWT-GLWindow[ \n\tDrawable: "+drawable+", \n\tWindow: "+window+", \n\tHelper: "+helper+", \n\tFactory: "+factory+"]"; + return "NEWT-GLWindow[ \n\tHelper: "+helper+", \n\tDrawable: "+drawable + /** ", \n\tWindow: "+window+", \n\tFactory: "+factory+ */ "]"; } //---------------------------------------------------------------------- diff --git a/src/newt/classes/com/jogamp/newt/util/EDTUtil.java b/src/newt/classes/com/jogamp/newt/util/EDTUtil.java new file mode 100644 index 000000000..f852bcf5c --- /dev/null +++ b/src/newt/classes/com/jogamp/newt/util/EDTUtil.java @@ -0,0 +1,244 @@ +/* + * Copyright (c) 2009 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + */ + +package com.jogamp.newt.util; + +import com.jogamp.newt.Display; +import com.jogamp.newt.impl.Debug; +import java.util.*; + +public class EDTUtil { + public static final boolean DEBUG = Debug.debug("EDT"); + + private ThreadGroup threadGroup; + private volatile boolean shouldStop = false; + private EventDispatchThread edt = null; + private Object edtLock = new Object(); + private ArrayList tasks = new ArrayList(); // one shot tasks + private String name; + private Runnable pumpMessages; + private long edtPollGranularity = 10; // 10ms, 1/100s + + public EDTUtil(ThreadGroup tg, String name, Runnable pumpMessages) { + this.threadGroup = tg; + this.name=new String("EDT-"+name); + this.pumpMessages=pumpMessages; + } + + public String getName() { return name; } + + public ThreadGroup getThreadGroup() { return threadGroup; } + + public Thread start() { + return start(false); + } + + /** + * @param externalStimuli true indicates that another thread stimulates, + * ie. calls this TaskManager's run() loop method. + * Hence no own thread is started in this case. + * + * @return The started Runnable, which handles the run-loop. + * Usefull in combination with externalStimuli=true, + * so an external stimuli can call it. + */ + public Thread start(boolean externalStimuli) { + synchronized(edtLock) { + if(null==edt) { + edt = new EventDispatchThread(threadGroup, name); + } + if(!edt.isRunning()) { + shouldStop = false; + edt.start(externalStimuli); + } + edtLock.notifyAll(); + } + return edt; + } + + public void stop() { + synchronized(edtLock) { + if(null!=edt && edt.isRunning()) { + shouldStop = true; + } + edtLock.notifyAll(); + if(DEBUG) { + System.out.println(Thread.currentThread()+": EDT signal STOP"); + } + } + } + + public Thread getEDT() { + return edt; + } + + public boolean isThreadEDT(Thread thread) { + return null!=edt && edt == thread; + } + + public boolean isCurrentThreadEDT() { + return null!=edt && edt == Thread.currentThread(); + } + + public boolean isRunning() { + return null!=edt && edt.isRunning() ; + } + + public void invokeLater(Runnable task) { + if(task == null) { + return; + } + synchronized(edtLock) { + if(null!=edt && edt.isRunning() && edt != Thread.currentThread() ) { + tasks.add(task); + edtLock.notifyAll(); + } else { + // if !running or isEDTThread, do it right away + task.run(); + } + } + } + + public void invokeAndWait(Runnable task) { + if(task == null) { + return; + } + invokeLater(task); + waitOnWorker(); + } + + public void waitOnWorker() { + synchronized(edtLock) { + if(null!=edt && edt.isRunning() && tasks.size()>0 && edt != Thread.currentThread() ) { + try { + edtLock.wait(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + } + } + + public void waitUntilStopped() { + synchronized(edtLock) { + while(null!=edt && edt.isRunning() && edt != Thread.currentThread() ) { + try { + edtLock.wait(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + } + } + + class EventDispatchThread extends Thread { + boolean isRunning = false; + boolean externalStimuli = false; + + public EventDispatchThread(ThreadGroup tg, String name) { + super(tg, name); + } + + public synchronized boolean isRunning() { + return isRunning; + } + + public void start(boolean externalStimuli) throws IllegalThreadStateException { + synchronized(this) { + this.externalStimuli = externalStimuli; + isRunning = true; + } + if(!externalStimuli) { + super.start(); + } + } + + /** + * Utilizing edtLock only for local resources and task execution, + * not for event dispatching. + */ + public void run() { + if(DEBUG) { + System.out.println(Thread.currentThread()+": EDT run() START"); + } + while(!shouldStop) { + try { + // wait for something todo + while(!shouldStop && tasks.size()==0) { + synchronized(edtLock) { + if(!shouldStop && tasks.size()==0) { + try { + edtLock.wait(edtPollGranularity); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + } + pumpMessages.run(); // event dispatch + } + if(!shouldStop && tasks.size()>0) { + synchronized(edtLock) { + if(!shouldStop && tasks.size()>0) { + Runnable task = (Runnable) tasks.remove(0); + task.run(); + edtLock.notifyAll(); + } + } + pumpMessages.run(); // event dispatch + } + } catch (Throwable t) { + // handle errors .. + t.printStackTrace(); + } finally { + // epilog - unlock locked stuff + } + if(externalStimuli) break; // no loop if called by external stimuli + } + synchronized(this) { + isRunning = !shouldStop; + } + if(!isRunning) { + synchronized(edtLock) { + edtLock.notifyAll(); + } + } + if(DEBUG) { + System.out.println(Thread.currentThread()+": EDT run() EXIT"); + } + } + } +} + diff --git a/src/newt/classes/com/jogamp/newt/util/EventDispatchThread.java b/src/newt/classes/com/jogamp/newt/util/EventDispatchThread.java deleted file mode 100644 index 675c6f322..000000000 --- a/src/newt/classes/com/jogamp/newt/util/EventDispatchThread.java +++ /dev/null @@ -1,240 +0,0 @@ -/* - * Copyright (c) 2009 Sun Microsystems, Inc. All Rights Reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * - Redistribution of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * - Redistribution in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * Neither the name of Sun Microsystems, Inc. or the names of - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * This software is provided "AS IS," without a warranty of any kind. ALL - * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, - * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A - * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN - * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR - * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR - * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR - * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR - * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE - * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, - * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF - * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. - * - * You acknowledge that this software is not designed or intended for use - * in the design, construction, operation or maintenance of any nuclear - * facility. - */ - -package com.jogamp.newt.util; - -import com.jogamp.newt.Display; -import com.jogamp.newt.impl.Debug; -import java.util.*; - -public class EventDispatchThread { - public static final boolean DEBUG = Debug.debug("EDT"); - - private ThreadGroup threadGroup; - private volatile boolean shouldStop = false; - private TaskWorker taskWorker = null; - private Object taskWorkerLock = new Object(); - private ArrayList tasks = new ArrayList(); // one shot tasks - private Display display = null; - private String name; - private long edtPollGranularity = 10; - - public EventDispatchThread(Display display, ThreadGroup tg, String name) { - this.display = display; - this.threadGroup = tg; - this.name=new String("EDT-Display_"+display.getName()+"-"+name); - } - - public String getName() { return name; } - - public ThreadGroup getThreadGroup() { return threadGroup; } - - public void start() { - start(false); - } - - /** - * @param externalStimuli true indicates that another thread stimulates, - * ie. calls this TaskManager's run() loop method. - * Hence no own thread is started in this case. - * - * @return The started Runnable, which handles the run-loop. - * Usefull in combination with externalStimuli=true, - * so an external stimuli can call it. - */ - public Runnable start(boolean externalStimuli) { - synchronized(taskWorkerLock) { - if(null==taskWorker) { - taskWorker = new TaskWorker(threadGroup, name); - } - if(!taskWorker.isRunning()) { - shouldStop = false; - taskWorker.start(externalStimuli); - } - taskWorkerLock.notifyAll(); - } - return taskWorker; - } - - public void stop() { - synchronized(taskWorkerLock) { - if(null!=taskWorker && taskWorker.isRunning()) { - shouldStop = true; - } - taskWorkerLock.notifyAll(); - if(DEBUG) { - System.out.println(Thread.currentThread()+": EDT signal STOP"); - } - } - } - - public boolean isThreadEDT(Thread thread) { - return null!=taskWorker && taskWorker == thread; - } - - public boolean isCurrentThreadEDT() { - return null!=taskWorker && taskWorker == Thread.currentThread(); - } - - public boolean isRunning() { - return null!=taskWorker && taskWorker.isRunning() ; - } - - public void invokeLater(Runnable task) { - if(task == null) { - return; - } - synchronized(taskWorkerLock) { - if(null!=taskWorker && taskWorker.isRunning() && taskWorker != Thread.currentThread() ) { - tasks.add(task); - taskWorkerLock.notifyAll(); - } else { - // if !running or isEDTThread, do it right away - task.run(); - } - } - } - - public void invokeAndWait(Runnable task) { - if(task == null) { - return; - } - invokeLater(task); - waitOnWorker(); - } - - public void waitOnWorker() { - synchronized(taskWorkerLock) { - if(null!=taskWorker && taskWorker.isRunning() && tasks.size()>0 && taskWorker != Thread.currentThread() ) { - try { - taskWorkerLock.wait(); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - } - } - - public void waitUntilStopped() { - synchronized(taskWorkerLock) { - while(null!=taskWorker && taskWorker.isRunning() && taskWorker != Thread.currentThread() ) { - try { - taskWorkerLock.wait(); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - } - } - - class TaskWorker extends Thread { - boolean isRunning = false; - boolean externalStimuli = false; - - public TaskWorker(ThreadGroup tg, String name) { - super(tg, name); - } - - public synchronized boolean isRunning() { - return isRunning; - } - - public void start(boolean externalStimuli) throws IllegalThreadStateException { - synchronized(this) { - this.externalStimuli = externalStimuli; - isRunning = true; - } - if(!externalStimuli) { - super.start(); - } - } - - /** - * Utilizing taskWorkerLock only for local resources and task execution, - * not for event dispatching. - */ - public void run() { - if(DEBUG) { - System.out.println(Thread.currentThread()+": EDT run() START"); - } - while(!shouldStop) { - try { - // wait for something todo - while(!shouldStop && tasks.size()==0) { - synchronized(taskWorkerLock) { - if(!shouldStop && tasks.size()==0) { - try { - taskWorkerLock.wait(edtPollGranularity); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - } - display.pumpMessages(); // event dispatch - } - if(!shouldStop && tasks.size()>0) { - synchronized(taskWorkerLock) { - if(!shouldStop && tasks.size()>0) { - Runnable task = (Runnable) tasks.remove(0); - task.run(); - taskWorkerLock.notifyAll(); - } - } - display.pumpMessages(); // event dispatch - } - } catch (Throwable t) { - // handle errors .. - t.printStackTrace(); - } finally { - // epilog - unlock locked stuff - } - if(externalStimuli) break; // no loop if called by external stimuli - } - synchronized(this) { - isRunning = !shouldStop; - } - if(!isRunning) { - synchronized(taskWorkerLock) { - taskWorkerLock.notifyAll(); - } - } - if(DEBUG) { - System.out.println(Thread.currentThread()+": EDT run() EXIT"); - } - } - } -} - -- cgit v1.2.3