aboutsummaryrefslogtreecommitdiffstats
path: root/src/newt/classes/com/jogamp
diff options
context:
space:
mode:
Diffstat (limited to 'src/newt/classes/com/jogamp')
-rw-r--r--src/newt/classes/com/jogamp/newt/util/MainThread.java331
1 files changed, 57 insertions, 274 deletions
diff --git a/src/newt/classes/com/jogamp/newt/util/MainThread.java b/src/newt/classes/com/jogamp/newt/util/MainThread.java
index 07c58d731..f74845afc 100644
--- a/src/newt/classes/com/jogamp/newt/util/MainThread.java
+++ b/src/newt/classes/com/jogamp/newt/util/MainThread.java
@@ -41,22 +41,19 @@ import java.lang.reflect.Method;
import java.lang.reflect.InvocationTargetException;
import java.security.AccessControlContext;
import java.security.AccessController;
-import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
-import java.util.Timer;
-import java.util.TimerTask;
-import javax.media.nativewindow.NativeWindowException;
import javax.media.nativewindow.NativeWindowFactory;
+import com.jogamp.common.os.Platform;
import com.jogamp.common.util.ReflectionUtil;
-import com.jogamp.common.util.RunnableTask;
import com.jogamp.newt.Display;
+
import jogamp.newt.Debug;
+import jogamp.newt.DefaultEDTUtil;
import jogamp.newt.NEWTJNILibLoader;
-import jogamp.newt.driver.awt.AWTEDTUtil;
/**
* NEWT Utility class MainThread<P>
@@ -92,26 +89,26 @@ import jogamp.newt.driver.awt.AWTEDTUtil;
* Which starts 4 threads, each with a window and OpenGL rendering.<br>
*/
public class MainThread implements EDTUtil {
- private static final AccessControlContext localACC = AccessController.getContext();
+ private static final String MACOSXDisplayClassName = "jogamp.newt.driver.macosx.MacDisplay";
/** if true, use the main thread EDT, otherwise AWT's EDT */
- public static final boolean HINT_USE_MAIN_THREAD = !NativeWindowFactory.isAWTAvailable() ||
- Debug.getBooleanProperty("newt.MainThread.force", true, localACC);
+ public static final boolean HINT_USE_MAIN_THREAD;
+
+ static {
+ final AccessControlContext localACC = AccessController.getContext();
+ Platform.initSingleton();
+ NativeWindowFactory.initSingleton(true);
+ NEWTJNILibLoader.loadNEWT();
+ HINT_USE_MAIN_THREAD = !NativeWindowFactory.isAWTAvailable() ||
+ Debug.getBooleanProperty("newt.MainThread.force", true, localACC);
+ }
+
public static boolean useMainThread = false;
protected static final boolean DEBUG = Debug.debug("MainThread");
private static final MainThread singletonMainThread = new MainThread(); // one singleton MainThread
- private static boolean isExit=false;
- private static volatile boolean isRunning=false;
- private static final Object edtLock=new Object();
- private static boolean shouldStop;
- private static ArrayList<RunnableTask> tasks;
- private static Thread mainThread;
-
- private static Timer pumpMessagesTimer=null;
- private static TimerTask pumpMessagesTimerTask=null;
private static final Map<Display, Runnable> pumpMessageDisplayMap = new HashMap<Display, Runnable>();
static class MainAction extends Thread {
@@ -127,11 +124,7 @@ public class MainThread implements EDTUtil {
@Override
public void run() {
- if ( useMainThread ) {
- // we have to start first to provide the service ..
- singletonMainThread.waitUntilRunning();
- }
-
+ if(DEBUG) System.err.println("MainAction.run(): "+Thread.currentThread().getName()+" start");
// start user app ..
try {
Class<?> mainClass = ReflectionUtil.getClass(mainClassName, true, getClass().getClassLoader());
@@ -166,15 +159,20 @@ 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;
+ final Platform.OSType osType = Platform.getOSType();
+ final boolean isMacOSX = osType == Platform.OSType.MACOS;
+
if(DEBUG) {
System.err.println("MainThread.main(): "+Thread.currentThread().getName()+
", useMainThread "+ useMainThread +
", HINT_USE_MAIN_THREAD "+ HINT_USE_MAIN_THREAD +
- ", isAWTAvailable " + NativeWindowFactory.isAWTAvailable());
+ ", isAWTAvailable " + NativeWindowFactory.isAWTAvailable() + ", ostype "+osType+", isMacOSX "+isMacOSX);
}
if(!useMainThread && !NativeWindowFactory.isAWTAvailable()) {
@@ -191,25 +189,34 @@ public class MainThread implements EDTUtil {
System.arraycopy(args, 1, mainClassArgs, 0, args.length-1);
}
- NEWTJNILibLoader.loadNEWT();
-
mainAction = new MainAction(mainClassName, mainClassArgs);
- if(NativeWindowFactory.TYPE_MACOSX.equals(NativeWindowFactory.getNativeWindowType(false))) {
- ReflectionUtil.callStaticMethod("jogamp.newt.macosx.MacDisplay", "initSingleton",
+ if(isMacOSX) {
+ ReflectionUtil.callStaticMethod(MACOSXDisplayClassName, "initSingleton",
null, null, MainThread.class.getClassLoader());
}
if ( useMainThread ) {
- shouldStop = false;
- tasks = new ArrayList<RunnableTask>();
- mainThread = Thread.currentThread();
+ 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();
-
- // do our main thread task scheduling
- singletonMainThread.run();
+
+ if(isMacOSX) {
+ try {
+ if(DEBUG) System.err.println("MainThread - 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 ...");
} else {
// run user's main in this thread
mainAction.run();
@@ -227,273 +234,49 @@ public class MainThread implements EDTUtil {
}
public static void addPumpMessage(Display dpy, Runnable pumpMessage) {
- if(DEBUG) {
- System.err.println("MainThread.addPumpMessage(): "+Thread.currentThread().getName()+
- " - dpy "+dpy+", USE_MAIN_THREAD " + useMainThread +
- " - hasAWT " + NativeWindowFactory.isAWTAvailable() );
- }
- if(!useMainThread && !NativeWindowFactory.isAWTAvailable()) {
- throw new RuntimeException("!USE_MAIN_THREAD and no AWT available");
- }
-
synchronized (pumpMessageDisplayMap) {
- if(!useMainThread && null == pumpMessagesTimer) {
- // AWT pump messages .. MAIN_THREAD uses main thread
- pumpMessagesTimer = new Timer();
- pumpMessagesTimerTask = new TimerTask() {
- public void run() {
- synchronized(pumpMessageDisplayMap) {
- for(Iterator<Runnable> i = pumpMessageDisplayMap.values().iterator(); i.hasNext(); ) {
- i.next().run();
- }
- }
- }
- };
- pumpMessagesTimer.scheduleAtFixedRate(pumpMessagesTimerTask, 0, defaultEDTPollGranularity);
- }
pumpMessageDisplayMap.put(dpy, pumpMessage);
}
}
- final public void reset() {
- if(NativeWindowFactory.isAWTAvailable()) {
- AWTEDTUtil.getSingleton().reset();
+ private static void dispatchMessages() {
+ synchronized(pumpMessageDisplayMap) {
+ for(Iterator<Runnable> i = pumpMessageDisplayMap.values().iterator(); i.hasNext(); ) {
+ i.next().run();
+ }
}
- // nop
+ }
+
+ final public void reset() {
+ // nop: ALWAYS RUNNING
}
final public void start() {
- if(NativeWindowFactory.isAWTAvailable()) {
- AWTEDTUtil.getSingleton().start();
- }
- // nop
+ // nop: ALWAYS RUNNING
}
final public boolean isCurrentThreadEDT() {
- if(NativeWindowFactory.isAWTAvailable()) {
- return AWTEDTUtil.getSingleton().isCurrentThreadEDT();
- }
- return isRunning() && mainThread == Thread.currentThread() ;
+ return internalEDT.isCurrentThreadEDT();
}
final public boolean isRunning() {
- if( useMainThread ) {
- return isRunning;
- }
- return true; // AWT is always running
+ return true; // ALWAYS RUNNING
}
final public void invokeStop(Runnable r) {
- invokeImpl(true, r, true);
+ internalEDT.invoke(true, r); // ALWAYS RUNNING
}
final public void invoke(boolean wait, Runnable r) {
- invokeImpl(wait, r, false);
- }
-
- private void invokeImpl(boolean wait, Runnable task, boolean stop) {
- if(task == null) {
- return;
- }
-
- if(NativeWindowFactory.isAWTAvailable()) {
- AWTEDTUtil.getSingleton().invokeImpl(wait, task, stop);
- return;
- }
-
- // if this main thread is not being used or
- // if this is already the main thread .. just execute.
- // FIXME: start if not started .. sync logic with DefaultEDTUtil!!!
- if( !isRunning() || mainThread == Thread.currentThread() ) {
- task.run();
- return;
- }
-
- Throwable throwable = null;
- RunnableTask rTask = null;
- Object rTaskLock = new Object();
- synchronized(rTaskLock) {
- synchronized(edtLock) {
- if( shouldStop ) {
- // drop task ..
- if(DEBUG) {
- System.err.println("Warning: EDT about (1) to stop, won't enqueue new task: "+this);
- Thread.dumpStack();
- }
- return;
- }
- // System.err.println(Thread.currentThread()+" XXX stop: "+stop+", tasks: "+tasks.size()+", task: "+task);
- // Thread.dumpStack();
- if(stop) {
- shouldStop = true;
- if(DEBUG) System.err.println("MainThread.stop(): "+Thread.currentThread().getName()+" start");
- }
- if( isCurrentThreadEDT() ) {
- task.run();
- wait = false; // running in same thread (EDT) -> no wait
- if(stop && tasks.size()>0) {
- System.err.println("Warning: EDT about (2) to stop, having remaining tasks: "+tasks.size()+" - "+this);
- if(DEBUG) {
- Thread.dumpStack();
- }
- }
- } else {
- synchronized(tasks) {
- start(); // start if not started yet and !shouldStop
- wait = wait && isRunning();
- rTask = new RunnableTask(task,
- wait ? rTaskLock : null,
- true /* always catch and report Exceptions, don't disturb EDT */);
- if(stop) {
- rTask.setAttachment(new Boolean(true)); // mark final task
- }
- // append task ..
- tasks.add(rTask);
- tasks.notifyAll();
- }
- }
- }
- if( wait ) {
- try {
- rTaskLock.wait(); // free lock, allow execution of rTask
- } catch (InterruptedException ie) {
- throwable = ie;
- }
- if(null==throwable) {
- throwable = rTask.getThrowable();
- }
- if(null!=throwable) {
- if(throwable instanceof NativeWindowException) {
- throw (NativeWindowException)throwable;
- }
- throw new RuntimeException(throwable);
- }
- }
- }
- if(DEBUG && stop) {
- System.err.println(Thread.currentThread()+": EDT signal STOP X edt: "+this);
- }
+ internalEDT.invoke(wait, r);
}
final public void waitUntilIdle() {
- if(NativeWindowFactory.isAWTAvailable()) {
- AWTEDTUtil.getSingleton().waitUntilIdle();
- }
+ internalEDT.waitUntilIdle();
}
final public void waitUntilStopped() {
- if(NativeWindowFactory.isAWTAvailable()) {
- AWTEDTUtil.getSingleton().waitUntilStopped();
- }
- }
-
- private void waitUntilRunning() {
- synchronized(edtLock) {
- if(isExit) return;
-
- while(!isRunning) {
- try {
- edtLock.wait();
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- }
- }
-
- public void run() {
- if(DEBUG) System.err.println("MainThread.run(): "+Thread.currentThread().getName());
- synchronized(edtLock) {
- isRunning = true;
- edtLock.notifyAll();
- }
-
- RuntimeException error = null;
- try {
- do {
- // event dispatch
- if(!shouldStop) {
- synchronized(pumpMessageDisplayMap) {
- for(Iterator<Runnable> i = pumpMessageDisplayMap.values().iterator(); i.hasNext(); ) {
- i.next().run();
- }
- }
- }
- // wait for something todo ..
- Runnable task = null;
- synchronized(tasks) {
- // wait for tasks
- if(!shouldStop && tasks.size()==0) {
- try {
- tasks.wait(defaultEDTPollGranularity);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- // execute one task, if available
- if(tasks.size()>0) {
- task = tasks.remove(0);
- tasks.notifyAll();
- }
- }
- if(null!=task) {
- // Exceptions are always catched, see Runnable creation above
- task.run();
- }
- } 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) {
- RunnableTask rt = ( tasks.size() > 0 ) ? tasks.get(0) : null ;
- System.err.println(/* getName()+*/"EDT run() END, tasks: "+tasks.size()+", "+rt+", "+error);
- }
- synchronized(edtLock) {
- if(null==error) {
- synchronized(tasks) {
- // drain remaining tasks (stop not on EDT),
- // while having tasks and no previous-task, or previous-task is non final
- RunnableTask task = null;
- while ( ( null == task || task.getAttachment() == null ) && tasks.size() > 0 ) {
- task = tasks.remove(0);
- task.run();
- tasks.notifyAll();
- }
- if(DEBUG) {
- if(null!=task && task.getAttachment()==null) {
- System.err.println("Warning: EDT exit: Last task Not Final: "+tasks.size()+", "+task);
- } else if(tasks.size()>0) {
- System.err.println("Warning: EDT exit: Remaining tasks Post Final: "+tasks.size());
- }
- Thread.dumpStack();
- }
- }
- }
- isRunning = !shouldStop;
- if(!isRunning) {
- edtLock.notifyAll();
- }
- }
- if(DEBUG) {
- System.err.println("EDT run() EXIT "+ error);
- }
- if(null!=error) {
- throw error;
- }
- } // finally
-
- if(DEBUG) System.err.println("MainThread.run(): "+Thread.currentThread().getName()+" fin");
- synchronized(edtLock) {
- isRunning = false;
- isExit = true;
- edtLock.notifyAll();
- }
+ // nop: ALWAYS RUNNING
}
}