38package com.jogamp.newt.util;
40import java.lang.reflect.Method;
41import java.lang.reflect.InvocationTargetException;
42import java.util.ArrayList;
45import com.jogamp.nativewindow.NativeWindowFactory;
47import com.jogamp.common.os.Platform;
48import com.jogamp.common.util.InterruptSource;
49import com.jogamp.common.util.PropertyAccess;
50import com.jogamp.common.util.ReflectionUtil;
52import jogamp.newt.Debug;
53import jogamp.newt.NEWTJNILibLoader;
97 private static final String MACOSXDisplayClassName =
"jogamp.newt.driver.macosx.DisplayDriver";
98 private static final Platform.OSType osType;
99 private static final boolean isMacOSX;
100 private static final ThreadGroup rootThreadGroup;
107 NEWTJNILibLoader.loadNEWTHead();
109 PropertyAccess.getBooleanProperty(
"newt.MainThread.force",
true);
110 osType = Platform.getOSType();
111 isMacOSX = osType == Platform.OSType.MACOS;
112 rootThreadGroup = getRootThreadGroup();
117 protected static final boolean DEBUG = Debug.debug(
"MainThread");
121 private static final ThreadGroup getRootThreadGroup() {
122 ThreadGroup rootGroup = Thread.currentThread( ).getThreadGroup( );
123 ThreadGroup parentGroup;
124 while ( ( parentGroup = rootGroup.getParent() ) !=
null ) {
125 rootGroup = parentGroup;
130 private static final Thread[] getAllThreads(
final int[] count) {
132 Thread[] threads =
new Thread[ rootThreadGroup.activeCount() ];
133 while ( ( tn = rootThreadGroup.enumerate( threads,
true ) ) == threads.length ) {
134 threads =
new Thread[ threads.length * 2 ];
139 private static final List<Thread> getNonDaemonThreads() {
140 final List<Thread> res =
new ArrayList<Thread>();
141 final int[] tn = { 0 };
142 final Thread[] threads = getAllThreads(tn);
143 for(
int i = tn[0] - 1; i >= 0; i--) {
144 final Thread thread = threads[i];
146 if(thread.isAlive() && !thread.isDaemon()) {
148 if(
DEBUG) System.err.println(
"XXX0: "+thread.getName()+
", "+thread);
150 }
catch (
final Throwable t) {
156 private static final int getNonDaemonThreadCount(
final List<Thread> ignoreThreads) {
158 final int[] tn = { 0 };
159 final Thread[] threads = getAllThreads(tn);
161 for(
int i = tn[0] - 1; i >= 0; i--) {
162 final Thread thread = threads[i];
164 if(thread.isAlive() && !thread.isDaemon() && !ignoreThreads.contains(thread)) {
166 if(
DEBUG) System.err.println(
"MainAction.run(): non daemon thread: "+thread);
168 }
catch (
final Throwable t) {
175 static class UserApp
extends InterruptSource.Thread {
176 private final String mainClassNameShort;
177 private final String mainClassName;
178 private final String[] mainClassArgs;
179 private final Method mainClassMain;
180 private List<java.lang.Thread> nonDaemonThreadsAtStart;
182 public UserApp(
final String mainClassName,
final String[] mainClassArgs)
throws SecurityException, NoSuchMethodException, ClassNotFoundException {
183 this.mainClassName=mainClassName;
184 this.mainClassArgs=mainClassArgs;
186 final Class<?> mainClass = ReflectionUtil.getClass(mainClassName,
true, getClass().getClassLoader());
187 if(
null==mainClass) {
188 throw new ClassNotFoundException(
"MainAction couldn't find main class "+mainClassName);
190 mainClassNameShort = mainClass.getSimpleName();
191 mainClassMain = mainClass.getDeclaredMethod(
"main",
new Class[] { String[].class });
192 mainClassMain.setAccessible(
true);
194 setName(getName()+
"-UserApp-"+mainClassNameShort);
197 if(
DEBUG) System.err.println(
"MainAction(): instantiated: "+getName()+
", is daemon "+isDaemon()+
", main-class: "+mainClass.getName());
202 nonDaemonThreadsAtStart = getNonDaemonThreads();
203 if(
DEBUG) System.err.println(
"MainAction.run(): "+java.lang.Thread.currentThread().getName()+
" start, nonDaemonThreadsAtStart "+nonDaemonThreadsAtStart);
206 if(
DEBUG) System.err.println(
"MainAction.run(): "+java.lang.Thread.currentThread().getName()+
" invoke "+mainClassName);
207 mainClassMain.invoke(
null,
new Object[] { mainClassArgs } );
208 }
catch (
final InvocationTargetException ite) {
209 ite.getTargetException().printStackTrace();
211 }
catch (
final Throwable t) {
219 while( 0 < ( ndtr = getNonDaemonThreadCount(nonDaemonThreadsAtStart) ) ) {
220 if(
DEBUG) System.err.println(
"MainAction.run(): post user app, non daemon threads alive: "+ndtr);
222 java.lang.Thread.sleep(1000);
223 }
catch (
final InterruptedException e) {
227 if(
DEBUG) System.err.println(
"MainAction.run(): "+java.lang.Thread.currentThread().getName()+
" user app fin: "+ndtr);
234 System.err.println(
"MainAction.main(): "+java.lang.Thread.currentThread()+
" MainAction fin - stopNSApp.0");
236 ReflectionUtil.callStaticMethod(MACOSXDisplayClassName,
"stopNSApplication",
237 null,
null, MainThread.class.getClassLoader());
239 System.err.println(
"MainAction.main(): "+java.lang.Thread.currentThread()+
" MainAction fin - stopNSApp.X");
241 }
catch (
final Exception e) {
245 if(
DEBUG) System.err.println(
"MainAction.run(): "+java.lang.Thread.currentThread().getName()+
" MainAction fin - System.exit(0)");
251 private static UserApp mainAction;
257 public static void main(
final String[] args)
throws SecurityException, NoSuchMethodException, ClassNotFoundException {
258 final Thread cur = Thread.currentThread();
263 System.err.println(
"MainThread.main(): "+cur.getName()+
266 ", isAWTAvailable " +
NativeWindowFactory.isAWTAvailable() +
", ostype "+osType+
", isMacOSX "+isMacOSX);
270 throw new RuntimeException(
"!USE_MAIN_THREAD and no AWT available");
277 final String mainClassName=args[0];
278 final String[] mainClassArgs=
new String[args.length-1];
280 System.arraycopy(args, 1, mainClassArgs, 0, args.length-1);
283 mainAction =
new UserApp(mainClassName, mainClassArgs);
286 ReflectionUtil.callStaticMethod(MACOSXDisplayClassName,
"initSingleton",
287 null,
null,
MainThread.class.getClassLoader());
292 cur.setName(cur.getName()+
"-MainThread");
293 }
catch (
final Exception e) {}
301 System.err.println(
"MainThread.main(): "+cur.getName()+
"- runNSApp");
303 ReflectionUtil.callStaticMethod(MACOSXDisplayClassName,
"runNSApplication",
304 null,
null,
MainThread.class.getClassLoader());
305 }
catch (
final Exception e) {
309 if(
DEBUG) { System.err.println(
"MainThread - wait until last non daemon thread ends ..."); }
317 return singletonMainThread;
Provides a pluggable mechanism for arbitrary window toolkits to adapt their components to the NativeW...
static synchronized void initSingleton()
Static one time initialization of this factory.
NEWT Utility class MainThread.
static final boolean DEBUG
static boolean useMainThread
static final boolean HINT_USE_MAIN_THREAD
if true, use the main thread EDT, otherwise AWT's EDT
static void main(final String[] args)
Your new java application main entry, which pipelines your application.
static MainThread getSingleton()