diff options
author | Sven Gothel <[email protected]> | 2012-04-21 21:06:41 +0200 |
---|---|---|
committer | Sven Gothel <[email protected]> | 2012-04-21 21:06:41 +0200 |
commit | 89304ecb034b2c2778f09423cb6d66d084074e11 (patch) | |
tree | 838190edc0369f93b8e798b57ce16a987b932308 /src/newt/classes/com/jogamp | |
parent | 15d23e40badcf43a9af78de3bd699b7c74ec464a (diff) |
NEWT/MainThread: Wait for new non daemon threads after 'main' class has finished, mimics proper Java behavior.
Diffstat (limited to 'src/newt/classes/com/jogamp')
-rw-r--r-- | src/newt/classes/com/jogamp/newt/util/MainThread.java | 126 |
1 files changed, 102 insertions, 24 deletions
diff --git a/src/newt/classes/com/jogamp/newt/util/MainThread.java b/src/newt/classes/com/jogamp/newt/util/MainThread.java index 3b5e3a6fb..bbe415b2f 100644 --- a/src/newt/classes/com/jogamp/newt/util/MainThread.java +++ b/src/newt/classes/com/jogamp/newt/util/MainThread.java @@ -39,6 +39,8 @@ package com.jogamp.newt.util; import java.lang.reflect.Method; import java.lang.reflect.InvocationTargetException; +import java.util.ArrayList; +import java.util.List; import javax.media.nativewindow.NativeWindowFactory; @@ -93,7 +95,7 @@ public class MainThread { private static final String MACOSXDisplayClassName = "jogamp.newt.driver.macosx.MacDisplay"; private static final Platform.OSType osType; private static final boolean isMacOSX; - + private static final ThreadGroup rootThreadGroup; /** if true, use the main thread EDT, otherwise AWT's EDT */ public static final boolean HINT_USE_MAIN_THREAD; @@ -104,7 +106,8 @@ public class MainThread { HINT_USE_MAIN_THREAD = !NativeWindowFactory.isAWTAvailable() || Debug.getBooleanProperty("newt.MainThread.force", true); osType = Platform.getOSType(); - isMacOSX = osType == Platform.OSType.MACOS; + isMacOSX = osType == Platform.OSType.MACOS; + rootThreadGroup = getRootThreadGroup(); } public static boolean useMainThread = false; @@ -112,44 +115,116 @@ public class MainThread { protected static final boolean DEBUG = Debug.debug("MainThread"); private static final MainThread singletonMainThread = new MainThread(); // one singleton MainThread - + + private static final ThreadGroup getRootThreadGroup() { + ThreadGroup rootGroup = Thread.currentThread( ).getThreadGroup( ); + ThreadGroup parentGroup; + while ( ( parentGroup = rootGroup.getParent() ) != null ) { + rootGroup = parentGroup; + } + return rootGroup; + } + + private static final Thread[] getAllThreads(int[] count) { + int tn; + Thread[] threads = new Thread[ rootThreadGroup.activeCount() ]; + while ( ( tn = rootThreadGroup.enumerate( threads, true ) ) == threads.length ) { + threads = new Thread[ threads.length * 2 ]; + } + count[0] = tn; + return threads; + } + private static final List<Thread> getNonDaemonThreads() { + List<Thread> res = new ArrayList<Thread>(); + int[] tn = { 0 }; + Thread[] threads = getAllThreads(tn); + for(int i = tn[0] - 1; i >= 0; i--) { + final Thread thread = threads[i]; + try { + if(thread.isAlive() && !thread.isDaemon()) { + res.add(thread); + if(DEBUG) System.err.println("XXX0: "+thread.getName()+", "+thread); + } + } catch (Throwable t) { + t.printStackTrace(); + } + } + return res; + } + private static final int getNonDaemonThreadCount(List<Thread> ignoreThreads) { + int res = 0; + int[] tn = { 0 }; + Thread[] threads = getAllThreads(tn); + + for(int i = tn[0] - 1; i >= 0; i--) { + final Thread thread = threads[i]; + try { + if(thread.isAlive() && !thread.isDaemon() && !ignoreThreads.contains(thread)) { + res++; + if(DEBUG) System.err.println("MainAction.run(): non daemon thread: "+thread); + } + } catch (Throwable t) { + t.printStackTrace(); + } + } + return res; + } + static class UserApp extends Thread { - private String mainClassName; - private String[] mainClassArgs; + private final String mainClassNameShort; + private final String mainClassName; + private final String[] mainClassArgs; + private final Method mainClassMain; + private List<Thread> nonDaemonThreadsAtStart; - private Method mainClassMain; - - public UserApp(String mainClassName, String[] mainClassArgs) { + public UserApp(String mainClassName, String[] mainClassArgs) throws SecurityException, NoSuchMethodException, ClassNotFoundException { + super(); this.mainClassName=mainClassName; this.mainClassArgs=mainClassArgs; + + final Class<?> mainClass = ReflectionUtil.getClass(mainClassName, true, getClass().getClassLoader()); + if(null==mainClass) { + throw new ClassNotFoundException("MainAction couldn't find main class "+mainClassName); + } + mainClassNameShort = mainClass.getSimpleName(); + mainClassMain = mainClass.getDeclaredMethod("main", new Class[] { String[].class }); + mainClassMain.setAccessible(true); + + setName(getName()+"-UserApp-"+mainClassNameShort); + setDaemon(false); + + if(DEBUG) System.err.println("MainAction(): instantiated: "+getName()+", is daemon "+isDaemon()+", main-class: "+mainClass.getName()); } @Override public void run() { - setName(getName()+"-UserApp"); - - if(DEBUG) System.err.println("MainAction.run(): "+Thread.currentThread().getName()+" start"); + nonDaemonThreadsAtStart = getNonDaemonThreads(); + if(DEBUG) System.err.println("MainAction.run(): "+Thread.currentThread().getName()+" start, nonDaemonThreadsAtStart "+nonDaemonThreadsAtStart); // start user app .. try { - Class<?> mainClass = ReflectionUtil.getClass(mainClassName, true, getClass().getClassLoader()); - if(null==mainClass) { - throw new RuntimeException(new ClassNotFoundException("MainAction couldn't find main class "+mainClassName)); - } - try { - mainClassMain = mainClass.getDeclaredMethod("main", new Class[] { String[].class }); - mainClassMain.setAccessible(true); - } catch (Throwable t) { - throw new RuntimeException(t); - } if(DEBUG) System.err.println("MainAction.run(): "+Thread.currentThread().getName()+" invoke "+mainClassName); mainClassMain.invoke(null, new Object[] { mainClassArgs } ); } catch (InvocationTargetException ite) { ite.getTargetException().printStackTrace(); + return; } catch (Throwable t) { t.printStackTrace(); + return; } - if(DEBUG) System.err.println("MainAction.run(): "+Thread.currentThread().getName()+" user app fin"); + // wait until no more active non-daemon threads are running + { + int ndtr; + while( 0 < ( ndtr = getNonDaemonThreadCount(nonDaemonThreadsAtStart) ) ) { + if(DEBUG) System.err.println("MainAction.run(): post user app, non daemon threads alive: "+ndtr); + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + if(DEBUG) System.err.println("MainAction.run(): "+Thread.currentThread().getName()+" user app fin: "+ndtr); + } if ( useMainThread ) { if(isMacOSX) { @@ -174,8 +249,11 @@ public class MainThread { } private static UserApp mainAction; - /** Your new java application main entry, which pipelines your application */ - public static void main(String[] args) { + /** Your new java application main entry, which pipelines your application + * @throws ClassNotFoundException + * @throws NoSuchMethodException + * @throws SecurityException */ + public static void main(String[] args) throws SecurityException, NoSuchMethodException, ClassNotFoundException { final Thread cur = Thread.currentThread(); useMainThread = HINT_USE_MAIN_THREAD; |