diff options
author | Sven Gothel <[email protected]> | 2011-09-27 12:51:47 +0200 |
---|---|---|
committer | Sven Gothel <[email protected]> | 2011-09-27 12:51:47 +0200 |
commit | fa35bd758189051dc25b8a0d32dc52360cfbc390 (patch) | |
tree | c7e500cbf247933aab419caccc9e279a79ddf82b | |
parent | 472a9c60b5599bb01883c628339ab29628511ed5 (diff) |
NEWT/Threading: MainThread / DefaultEDTUtil
- MainThread:
This class no more implements EDTUtil!
This class just provides a main-thread utility, forking of a main java class
on another thread while being able to continue doing platform specific things
on the main-thread. The latter is essential for eg. MacOSX, where we continue
to run NSApp.run().
- DefaultEDTUtil:
- if Lock.DEBUG validate that no recursive locks are being hold,
where it shall not (EDT: startup and return from task execution)
- If task execution's result wasn't waited for (checked),
at least dump exeception's stack trace if i happened.
- MacDisplay: Just use DefaultEDTUtil
- MacWindow:
- No more need of special locking -> removed nsViewLock, since:
- using proper EDT
- capability to run from multiple threads (native Java thread attachment)
5 files changed, 94 insertions, 224 deletions
diff --git a/src/newt/classes/com/jogamp/newt/util/MainThread.java b/src/newt/classes/com/jogamp/newt/util/MainThread.java index f74845afc..8de77420f 100644 --- a/src/newt/classes/com/jogamp/newt/util/MainThread.java +++ b/src/newt/classes/com/jogamp/newt/util/MainThread.java @@ -41,23 +41,26 @@ import java.lang.reflect.Method; import java.lang.reflect.InvocationTargetException; import java.security.AccessControlContext; import java.security.AccessController; -import java.util.HashMap; -import java.util.Iterator; -import java.util.Map; import javax.media.nativewindow.NativeWindowFactory; import com.jogamp.common.os.Platform; import com.jogamp.common.util.ReflectionUtil; -import com.jogamp.newt.Display; import jogamp.newt.Debug; -import jogamp.newt.DefaultEDTUtil; import jogamp.newt.NEWTJNILibLoader; /** * NEWT Utility class MainThread<P> * + * <p> + * FIXME: Update this documentation! + * This class just provides a main-thread utility, forking of a main java class + * on another thread while being able to continue doing platform specific things + * on the main-thread. The latter is essential for eg. MacOSX, where we continue + * to run NSApp.run(). + * </p> + * * This class provides a startup singleton <i>main thread</i>, * from which a new thread with the users main class is launched.<br> * @@ -88,7 +91,7 @@ import jogamp.newt.NEWTJNILibLoader; </PRE> * Which starts 4 threads, each with a window and OpenGL rendering.<br> */ -public class MainThread implements EDTUtil { +public class MainThread { private static final String MACOSXDisplayClassName = "jogamp.newt.driver.macosx.MacDisplay"; /** if true, use the main thread EDT, otherwise AWT's EDT */ @@ -109,8 +112,6 @@ public class MainThread implements EDTUtil { private static final MainThread singletonMainThread = new MainThread(); // one singleton MainThread - private static final Map<Display, Runnable> pumpMessageDisplayMap = new HashMap<Display, Runnable>(); - static class MainAction extends Thread { private String mainClassName; private String[] mainClassArgs; @@ -148,10 +149,6 @@ public class MainThread implements EDTUtil { if(DEBUG) System.err.println("MainAction.run(): "+Thread.currentThread().getName()+" user app fin"); if ( useMainThread ) { - singletonMainThread.invokeStop(new Runnable() { - public void run() { - // nop - }}); if(DEBUG) System.err.println("MainAction.run(): "+Thread.currentThread().getName()+" MainThread fin - stop"); System.exit(0); } @@ -159,8 +156,6 @@ public class MainThread implements EDTUtil { } private static MainAction mainAction; - private static EDTUtil internalEDT; - /** Your new java application main entry, which pipelines your application */ public static void main(String[] args) { useMainThread = HINT_USE_MAIN_THREAD; @@ -197,26 +192,21 @@ public class MainThread implements EDTUtil { } if ( useMainThread ) { - final Thread current = Thread.currentThread(); - internalEDT = new DefaultEDTUtil(current.getThreadGroup(), "MainThread", new Runnable() { - public void run() { dispatchMessages(); } }); - - if(DEBUG) System.err.println("MainThread - run: "+internalEDT.toString()); - internalEDT.start(); // forever ! - // dispatch user's main thread .. mainAction.start(); if(isMacOSX) { try { - if(DEBUG) System.err.println("MainThread - runNSApp"); + if(DEBUG) { + System.err.println("MainThread.main(): "+Thread.currentThread().getName()+"- runNSApp"); + } ReflectionUtil.callStaticMethod(MACOSXDisplayClassName, "runNSApplication", null, null, MainThread.class.getClassLoader()); } catch (Exception e) { e.printStackTrace(); } } - if(DEBUG) System.err.println("MainThread - wait until last non daemon thread ends ..."); + if(DEBUG) { System.err.println("MainThread - wait until last non daemon thread ends ..."); } } else { // run user's main in this thread mainAction.run(); @@ -227,57 +217,6 @@ public class MainThread implements EDTUtil { return singletonMainThread; } - public static Runnable removePumpMessage(Display dpy) { - synchronized(pumpMessageDisplayMap) { - return pumpMessageDisplayMap.remove(dpy); - } - } - - public static void addPumpMessage(Display dpy, Runnable pumpMessage) { - synchronized (pumpMessageDisplayMap) { - pumpMessageDisplayMap.put(dpy, pumpMessage); - } - } - - private static void dispatchMessages() { - synchronized(pumpMessageDisplayMap) { - for(Iterator<Runnable> i = pumpMessageDisplayMap.values().iterator(); i.hasNext(); ) { - i.next().run(); - } - } - } - - final public void reset() { - // nop: ALWAYS RUNNING - } - - final public void start() { - // nop: ALWAYS RUNNING - } - - final public boolean isCurrentThreadEDT() { - return internalEDT.isCurrentThreadEDT(); - } - - final public boolean isRunning() { - return true; // ALWAYS RUNNING - } - - final public void invokeStop(Runnable r) { - internalEDT.invoke(true, r); // ALWAYS RUNNING - } - - final public void invoke(boolean wait, Runnable r) { - internalEDT.invoke(wait, r); - } - - final public void waitUntilIdle() { - internalEDT.waitUntilIdle(); - } - - final public void waitUntilStopped() { - // nop: ALWAYS RUNNING - } } diff --git a/src/newt/classes/jogamp/newt/DefaultEDTUtil.java b/src/newt/classes/jogamp/newt/DefaultEDTUtil.java index 3e8715364..0bcd3323c 100644 --- a/src/newt/classes/jogamp/newt/DefaultEDTUtil.java +++ b/src/newt/classes/jogamp/newt/DefaultEDTUtil.java @@ -39,7 +39,11 @@ package jogamp.newt; import java.util.ArrayList; import javax.media.nativewindow.NativeWindowException; + +import jogamp.common.util.locks.LockDebugUtil; + import com.jogamp.common.util.RunnableTask; +import com.jogamp.common.util.locks.Lock; import com.jogamp.newt.util.EDTUtil; public class DefaultEDTUtil implements EDTUtil { @@ -235,6 +239,15 @@ public class DefaultEDTUtil implements EDTUtil { super.start(); } + private final void validateNoRecursiveLocksHold() { + if(Lock.DEBUG) { + if(LockDebugUtil.getRecursiveLockTrace().size()>0) { + LockDebugUtil.dumpRecursiveLockTrace(System.err); + throw new InternalError("XXX"); + } + } + } + /** * Utilizing locking only on tasks and its execution, * not for event dispatching. @@ -244,6 +257,7 @@ public class DefaultEDTUtil implements EDTUtil { if(DEBUG) { System.err.println(getName()+": EDT run() START "+ getName()); } + validateNoRecursiveLocksHold(); RuntimeException error = null; try { do { @@ -269,8 +283,12 @@ public class DefaultEDTUtil implements EDTUtil { } } if(null!=task) { - // Exceptions are always catched, see RunnableTask creation above task.run(); + validateNoRecursiveLocksHold(); + if(!task.hasWaiter() && null != task.getThrowable()) { + // at least dump stack-trace in case nobody waits for result + task.getThrowable().printStackTrace(); + } } } while(!shouldStop) ; } catch (Throwable t) { diff --git a/src/newt/classes/jogamp/newt/DisplayImpl.java b/src/newt/classes/jogamp/newt/DisplayImpl.java index ee370029e..cfe9f0c2d 100644 --- a/src/newt/classes/jogamp/newt/DisplayImpl.java +++ b/src/newt/classes/jogamp/newt/DisplayImpl.java @@ -39,18 +39,14 @@ import com.jogamp.newt.NewtFactory; import com.jogamp.newt.event.NEWTEvent; import com.jogamp.newt.event.NEWTEventConsumer; -import jogamp.newt.driver.awt.AWTEDTUtil; import jogamp.newt.event.NEWTEventTask; import com.jogamp.newt.util.EDTUtil; -import com.jogamp.newt.util.MainThread; import java.util.ArrayList; import javax.media.nativewindow.AbstractGraphicsDevice; import javax.media.nativewindow.NativeWindowException; import javax.media.nativewindow.NativeWindowFactory; public abstract class DisplayImpl extends Display { - public static final boolean DEBUG_TEST_EDT_MAINTHREAD = Debug.isPropertyDefined("newt.test.EDTMainThread", true); // JAU EDT Test .. - private static int serialno = 1; private static Class<?> getDisplayClass(String type) @@ -171,27 +167,7 @@ public abstract class DisplayImpl extends Display { protected void createEDTUtil() { if(NewtFactory.useEDT()) { - if ( ! DEBUG_TEST_EDT_MAINTHREAD ) { - final Thread current = Thread.currentThread(); - edtUtil = new DefaultEDTUtil(current.getThreadGroup(), "Display-"+getFQName(), dispatchMessagesRunnable); - } else { - // Begin JAU EDT Test .. - final Display f_dpy = this; - final Runnable dispatchRunner = new Runnable() { - public void run() { - if(null!=f_dpy.getGraphicsDevice()) { - f_dpy.dispatchMessages(); - } } }; - - if(NativeWindowFactory.isAWTAvailable()) { - AWTEDTUtil.addPumpMessage(this, dispatchRunner); - edtUtil = AWTEDTUtil.getSingleton(); - } else { - MainThread.addPumpMessage(this, dispatchRunner); - edtUtil = MainThread.getSingleton(); - } - // End JAU EDT Test .. - } + edtUtil = new DefaultEDTUtil(Thread.currentThread().getThreadGroup(), "Display-"+getFQName(), dispatchMessagesRunnable); if(DEBUG) { System.err.println("Display.createNative("+getFQName()+") Create EDTUtil: "+edtUtil.getClass().getName()); } @@ -255,9 +231,6 @@ public abstract class DisplayImpl extends Display { } } ); if(null!=edtUtil) { - if ( DEBUG_TEST_EDT_MAINTHREAD ) { - MainThread.removePumpMessage(this); // JAU EDT Test .. - } edtUtil.waitUntilStopped(); edtUtil.reset(); } diff --git a/src/newt/classes/jogamp/newt/driver/macosx/MacDisplay.java b/src/newt/classes/jogamp/newt/driver/macosx/MacDisplay.java index 572d37efe..527fdac6d 100644 --- a/src/newt/classes/jogamp/newt/driver/macosx/MacDisplay.java +++ b/src/newt/classes/jogamp/newt/driver/macosx/MacDisplay.java @@ -35,11 +35,7 @@ package jogamp.newt.driver.macosx; import javax.media.nativewindow.*; import javax.media.nativewindow.macosx.*; -import com.jogamp.newt.*; import jogamp.newt.*; -import jogamp.newt.driver.awt.AWTEDTUtil; - -import com.jogamp.newt.util.MainThread; public class MacDisplay extends DisplayImpl { static { @@ -73,35 +69,6 @@ public class MacDisplay extends DisplayImpl { protected void closeNativeImpl() { } - /** - @Override - protected void createEDTUtil() { - if(NewtFactory.useEDT()) { - final Display f_dpy = this; - final Runnable dispatchRunner = new Runnable() { - public void run() { - if(null!=f_dpy.getGraphicsDevice()) { - f_dpy.dispatchMessages(); - } } }; - - if(NativeWindowFactory.isAWTAvailable()) { - AWTEDTUtil.addPumpMessage(this, dispatchRunner); - edtUtil = AWTEDTUtil.getSingleton(); - } else { - MainThread.addPumpMessage(this, dispatchRunner); - edtUtil = MainThread.getSingleton(); - } - } - } */ - - protected void releaseEDTUtil() { - if(null!=edtUtil) { - MainThread.removePumpMessage(this); - edtUtil.waitUntilStopped(); - edtUtil=null; - } - } - public static void runNSApplication() { runNSApplication0(); } diff --git a/src/newt/classes/jogamp/newt/driver/macosx/MacWindow.java b/src/newt/classes/jogamp/newt/driver/macosx/MacWindow.java index 3265da1c1..8fe32029c 100644 --- a/src/newt/classes/jogamp/newt/driver/macosx/MacWindow.java +++ b/src/newt/classes/jogamp/newt/driver/macosx/MacWindow.java @@ -36,8 +36,6 @@ package jogamp.newt.driver.macosx; import javax.media.nativewindow.*; -import com.jogamp.common.util.locks.RecursiveLock; - import com.jogamp.newt.event.*; import jogamp.nativewindow.macosx.OSXUtil; @@ -157,7 +155,6 @@ public class MacWindow extends WindowImpl { } protected void closeNativeImpl() { - nsViewLock.lock(); try { if(DEBUG_IMPLEMENTATION) { System.err.println("MacWindow.CloseAction "+Thread.currentThread().getName()); } if (getWindowHandle() != 0) { @@ -171,7 +168,6 @@ public class MacWindow extends WindowImpl { } } finally { setWindowHandle(0); - nsViewLock.unlock(); } } @@ -180,105 +176,82 @@ public class MacWindow extends WindowImpl { return surfaceHandle; } - private RecursiveLock nsViewLock = new RecursiveLock(); - - @Override - protected int lockSurfaceImpl() { - nsViewLock.lock(); - return LOCK_SUCCESS; - } - - @Override - protected void unlockSurfaceImpl() { - nsViewLock.unlock(); - } - @Override protected void setTitleImpl(final String title) { - // FIXME: move nsViewLock up to window lock - nsViewLock.lock(); - try { - setTitle0(getWindowHandle(), title); - } finally { - nsViewLock.unlock(); - } + setTitle0(getWindowHandle(), title); } protected void requestFocusImpl(boolean reparented) { - // FIXME: move nsViewLock up to window lock - nsViewLock.lock(); - try { - makeKeyAndOrderFront0(getWindowHandle()); - // makeKey0(getWindowHandle()); - } finally { - nsViewLock.unlock(); - } + makeKeyAndOrderFront0(getWindowHandle()); } protected boolean reconfigureWindowImpl(int x, int y, int width, int height, int flags) { - nsViewLock.lock(); - try { - int _x = x, _y = y; - if(0 == ( FLAG_IS_UNDECORATED & flags) && 0<=_x && 0<=_y) { - final InsetsImmutable i = getInsets(); - - // client position -> top-level window position - _x -= i.getLeftWidth() ; - _y -= i.getTopHeight() ; - if( 0 > _x ) { _x = 0; } - if( 0 > _y ) { _y = 0; } - } + int _x = x, _y = y; + if(0 == ( FLAG_IS_UNDECORATED & flags) && 0<=_x && 0<=_y) { + final InsetsImmutable i = getInsets(); + + // client position -> top-level window position + _x -= i.getLeftWidth() ; + _y -= i.getTopHeight() ; + if( 0 > _x ) { _x = 0; } + if( 0 > _y ) { _y = 0; } + if(DEBUG_IMPLEMENTATION) { + System.err.println("MacWindow reconfig (insets: "+i+"): "+x+"/"+y+" -> "+_x+"/"+_y); + } + } + { final NativeWindow parent = getParent(); if(null != parent) { final Point p = parent.getLocationOnScreen(null); _x += p.getX(); _y += p.getY(); + if(DEBUG_IMPLEMENTATION) { + System.err.println("MacWindow reconfig (parent abs pos: "+p+"): "+x+"/"+y+" -> "+_x+"/"+_y); + } } - - if(DEBUG_IMPLEMENTATION) { - System.err.println("MacWindow reconfig: "+x+"/"+y+" -> "+_x+"/"+_y+" - "+width+"x"+height+", "+ - getReconfigureFlagsAsString(null, flags)); - } - - if( getWindowHandle() == 0 ) { + } + + if(DEBUG_IMPLEMENTATION) { + System.err.println("MacWindow reconfig: "+x+"/"+y+" -> "+_x+"/"+_y+" - "+width+"x"+height+", "+ + getReconfigureFlagsAsString(null, flags)); + } + + if( getWindowHandle() == 0 ) { + if( 0 != ( FLAG_IS_VISIBLE & flags) ) { + createWindow(false, _x, _y, width, height, 0 != ( FLAG_IS_FULLSCREEN & flags)); + this.x = x; + this.y = y; + visibleChanged(false, true); // no native event .. + } /* else { ?? } */ + } else { + if( 0 != ( FLAG_CHANGE_VISIBILITY & flags) ) { if( 0 != ( FLAG_IS_VISIBLE & flags) ) { - createWindow(false, _x, _y, width, height, 0 != ( FLAG_IS_FULLSCREEN & flags)); - this.x = x; - this.y = y; - visibleChanged(true); // no native event .. - } /* else { ?? } */ - } else { - if( 0 != ( FLAG_CHANGE_VISIBILITY & flags) ) { - if( 0 != ( FLAG_IS_VISIBLE & flags) ) { - makeKeyAndOrderFront0(getWindowHandle()); - visibleChanged(true); // no native event .. - enqueueWindowEvent(false, WindowEvent.EVENT_WINDOW_GAINED_FOCUS); - } else { - orderOut0(getWindowHandle()); - visibleChanged(false); // no native event .. - enqueueWindowEvent(false, WindowEvent.EVENT_WINDOW_LOST_FOCUS); - } - } else if( 0 != ( FLAG_CHANGE_DECORATION & flags) || - 0 != ( FLAG_CHANGE_PARENTING & flags) || - 0 != ( FLAG_CHANGE_FULLSCREEN & flags) ) { - createWindow(true, x, y, width, height, 0 != ( FLAG_IS_FULLSCREEN & flags)); - } - if(x>=0 || y>=0) { - setFrameTopLeftPoint0(getParentWindowHandle(), getWindowHandle(), _x, _y); - this.x = x; - this.y = y; - enqueueWindowEvent(false, WindowEvent.EVENT_WINDOW_MOVED); + makeKeyAndOrderFront0(getWindowHandle()); + visibleChanged(false, true); // no native event .. + enqueueWindowEvent(false, WindowEvent.EVENT_WINDOW_GAINED_FOCUS); + } else { + orderOut0(getWindowHandle()); + visibleChanged(false, false); // no native event .. + enqueueWindowEvent(false, WindowEvent.EVENT_WINDOW_LOST_FOCUS); } - if(width>0 || height>0) { - setContentSize0(getWindowHandle(), width, height); - this.width = width; - this.height = height; - enqueueWindowEvent(false, WindowEvent.EVENT_WINDOW_RESIZED); - } - setAlwaysOnTop0(getWindowHandle(), 0 != ( FLAG_IS_ALWAYSONTOP & flags)); + } else if( 0 != ( FLAG_CHANGE_DECORATION & flags) || + 0 != ( FLAG_CHANGE_PARENTING & flags) || + 0 != ( FLAG_CHANGE_FULLSCREEN & flags) ) { + createWindow(true, x, y, width, height, 0 != ( FLAG_IS_FULLSCREEN & flags)); } - } finally { - nsViewLock.unlock(); + if(x>=0 && y>=0) { + setFrameTopLeftPoint0(getParentWindowHandle(), getWindowHandle(), _x, _y); + this.x = x; + this.y = y; + enqueueWindowEvent(false, WindowEvent.EVENT_WINDOW_MOVED); + } + if(width>0 && height>0) { + setContentSize0(getWindowHandle(), width, height); + this.width = width; + this.height = height; + enqueueWindowEvent(false, WindowEvent.EVENT_WINDOW_RESIZED); + } + setAlwaysOnTop0(getWindowHandle(), 0 != ( FLAG_IS_ALWAYSONTOP & flags)); } return true; } @@ -437,14 +410,14 @@ public class MacWindow extends WindowImpl { } @Override - protected void positionChanged(int newX, int newY) { + protected void positionChanged(boolean defer, int newX, int newY) { final NativeWindow parent = getParent(); if(null != parent) { final Point p = parent.getLocationOnScreen(null); newX -= p.getX(); newY -= p.getY(); } - super.positionChanged(newX, newY); + super.positionChanged(defer, newX, newY); } protected static native boolean initIDs0(); |