Changeset 39031
- Timestamp:
- 2024-05-17T22:44:25+12:00 (3 weeks ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
main/trunk/gli/src/org/greenstone/gatherer/Gatherer.java
r39030 r39031 172 172 173 173 //******************* CODE FOR IMPORTANT HELPER FUNCTIONS FOR GUI TESTING ***************** 174 174 175 175 // Changes made to GLI execute GUI code in the Event Dispatch Thread (EDT) allowing GUI 176 176 // testing with AssertJ Swing can be beneficial for GLI overall. In case it breaks GLI 177 177 // or you suspect it has, set this to true. There's still extra method invocations, but 178 178 // it's otherwise the same linear sequence and gets executed on the same thread as originally 179 static public boolean TURN_OFF_EVENTDISPATCH_CHANGES = false; 180 179 public static final boolean TURN_OFF_EVENTDISPATCH_CHANGES = false; 180 public static boolean PRINT_THREAD_NAMES = false; // verbose info for debugging, can change 181 181 182 // SYNC executes code with invokeAndWait on the EDT (waiting until termination of the runnable) 182 183 // ASYNC calls invokeLater() which is the same as calling aThread.start(), not waiting for 183 184 // any result of the code being executed. 184 static publicboolean SYNC = true;185 static publicboolean ASYNC = false;185 public static final boolean SYNC = true; 186 public static final boolean ASYNC = false; 186 187 // If you know some changes are undesirable for regular GLI, but they're needed for 187 // testing to not throw EDT exceptions, pass in DO_NOT_BYPASS_FOR_TESTING as 3rd arg 188 // to Gatherer.invokeInDispatchThread() 189 static public boolean BYPASS_IF_NOT_TESTING = true; 190 static public boolean DO_NOT_BYPASS_IF_NOT_TESTING = false; 191 192 // Idea taken from 193 // https://stackoverflow.com/questions/2684049/check-if-thread-is-edt-is-necessary 194 // TODO: Allow extra parameter if any EDT call made for testing should Never be applied 195 // to GLI in non-testing mode 196 public static void invokeInDispatchThread(boolean invokeAs, Runnable runnable) { 197 invokeInDispatchThread("", invokeAs, DO_NOT_BYPASS_IF_NOT_TESTING, runnable); 188 // testing, to not throw EDT exceptions, then pass in DO_NOT_BYPASS_FOR_TESTING as 3rd arg 189 // to Gatherer.invokeInEDT...() 190 public static final boolean BYPASS_WHEN_NOT_TESTING = true; 191 public static final boolean DO_NOT_BYPASS_WHEN_NOT_TESTING = false; 192 193 // When turning off event dispatch changes globally (with TURN_OFF_EVENTDISPATCH_CHANGES 194 // set to true) or when bypassing EDT changes on a case by case call to invokeInEDT... 195 // we need to know what the *original* behaviour of GLI was that was replaced by the 196 // invokeInEDT call, so that we return to running it in the same thread as GLI did, 197 // instead of on the EDT. 198 // So we need to know if GLI ran the Runnable code in the new Runnable Thread (passed in 199 // as param Runnable) by calling start() on it, or whether GLI ran the Runnable code in 200 // whatever the current thread was at the time/whatever the thread was before switch to EDT. 201 private static final int RUN_IN_THREAD_PARAM_WITH_START = 1; 202 private static final int PROCEED_IN_CURRENT_THREAD = 2; 203 204 /* 205 public static void invokeInEDT(boolean invokeAs, Runnable runnable) { 206 invokeInDispatchThread("", invokeAs, DO_NOT_BYPASS_WHEN_NOT_TESTING, 207 PROCEED_IN_CURRENT_THREAD, runnable); 208 } 209 public static void invokeInEDT(String callerDescription, boolean invokeAs, Runnable runnable) 210 { 211 invokeInDispatchThread(callerDescription, invokeAs, DO_NOT_BYPASS_WHEN_NOT_TESTING, PROCEED_IN_CURRENT_THREAD, runnable); 198 212 } 213 */ 199 214 // Call like: 200 215 /* 201 Gatherer.invokeIn DispatchThread("Gatherer.init()", Gatherer.<SYNC|ASYNC>, new Runnable() {216 Gatherer.invokeInEDT_replacesProceedInCurrThread("Gatherer.init()", Gatherer.<SYNC|ASYNC>, new Runnable() { 202 217 public void run() { 203 218 .... some GUI/event code that should happen on EDT … … 206 221 */ 207 222 // BEWARE: in the code you embed in run() on rewriting any existing code, 208 // change any this references to <Outerclass>.this 209 public static void invokeInDispatchThread(String callerDescription, boolean invokeAs, Runnable runnable) { 210 invokeInDispatchThread(callerDescription, invokeAs, DO_NOT_BYPASS_IF_NOT_TESTING, runnable); 223 // change any This references to <Outerclass>.this 224 225 226 // Versions that replace (new MyThreadSubclass()).start() coding pattern in GLI 227 // when it needs invoking on EDT. If EDT changes are turned off globally or bypassed on 228 // a case by case basis, the Runnable code will be run on the thread passed in as param, as 229 // happens by calling start() on the thread instead of running the code on the calling thread 230 public static void invokeInEDT_replacesThreadStart(String callerDescription, 231 boolean invokeAs, boolean bypassIfNotTesting, Thread newThread) 232 { 233 invokeInDispatchThread(callerDescription, invokeAs, bypassIfNotTesting, 234 RUN_IN_THREAD_PARAM_WITH_START, newThread); 211 235 } 212 public static void invokeInDispatchThread(String callerDescription, boolean invokeAs, 213 boolean bypassIfNotTesting, Runnable runnable) { 236 public static void invokeInEDT_replacesThreadStart(String callerDescription, 237 boolean invokeAs, Thread newThread) 238 { 239 invokeInDispatchThread(callerDescription, invokeAs, DO_NOT_BYPASS_WHEN_NOT_TESTING, 240 RUN_IN_THREAD_PARAM_WITH_START, newThread); 241 } 242 243 // The more common alternative: versions of invokeInEDT_replacesProceedInCurrThread(). 244 // This version replaces any block of code Runnable code to be run in the Event Dispatch 245 // Thread, EDT (unless changes for testing are turned off globally or bypassed on a case by 246 // basis, in which case the block of Runnable code gets run in whatever is the calling thread) 247 public static void invokeInEDT_replacesProceedInCurrThread(String callerDescription, 248 boolean invokeAs, boolean bypassIfNotTesting, Runnable runnable) 249 { 250 invokeInDispatchThread(callerDescription, invokeAs, bypassIfNotTesting, PROCEED_IN_CURRENT_THREAD, runnable); 251 } 252 public static void invokeInEDT_replacesProceedInCurrThread(String callerDescription, 253 boolean invokeAs, Runnable runnable) 254 { 255 invokeInDispatchThread(callerDescription, invokeAs, DO_NOT_BYPASS_WHEN_NOT_TESTING, 256 PROCEED_IN_CURRENT_THREAD, runnable); 257 } 258 259 // Skeleton structure and basic idea of function taken from 260 // https://stackoverflow.com/questions/2684049/check-if-thread-is-edt-is-necessary 261 // DONE: Allows extra parameter bypass... if any EDT call made for testing should 262 // Never be applied to GLI in non-testing mode 263 private static void invokeInDispatchThread(String callerDescription, boolean invokeAs, 264 boolean bypassIfNotTesting, int runVariant, Runnable runnable) 265 { 266 if(PRINT_THREAD_NAMES) { 267 // https://stackoverflow.com/questions/467224/renaming-threads-in-java 268 Map<Thread,StackTraceElement[]> threadsInfo = Thread.getAllStackTraces(); 269 Set<Thread> allActiveThreads = threadsInfo.keySet(); 270 //for(Map.Entry<Thread,StackTraceElement[]> : threadsInfo) { 271 for(Thread aThread : allActiveThreads) { 272 System.err.println("thread name: " + aThread.getName() 273 + " - class " + aThread.getClass().getName()); 274 } 275 } 276 277 // print calling thread's name 278 if(bypassIfNotTesting) { 279 System.err.println("Calling thread name: " + Thread.currentThread().getName() 280 + " - class " + Thread.currentThread().getClass().getName()); 281 if(runnable instanceof Thread) { 282 Thread t = (Thread)runnable; 283 System.err.println("\tRunnable thread name: " + t.getName() 284 + " - class " + t.getClass().getName()); 285 } 286 } 287 214 288 if(TURN_OFF_EVENTDISPATCH_CHANGES 215 289 || (bypassIfNotTesting && !TestingPreparation.TEST_MODE) 216 || EventQueue.isDispatchThread()) { 290 || EventQueue.isDispatchThread()) { 291 217 292 if (bypassIfNotTesting && !TestingPreparation.TEST_MODE) { 218 System.err.println( callerDescription + " - Bypassing EDT change");293 System.err.println("@@@@" + callerDescription + " - Bypassing EDT change"); 219 294 } 220 runnable.run(); 221 } else { 295 if(!EventQueue.isDispatchThread()) { 296 System.err.println("@@@@" + callerDescription + "\n" 297 + "\tExpected to be on the Event Dispatch Thread but not so." 298 + "\n\tThis is potentially dangerous!!!"); 299 } 300 301 if(TURN_OFF_EVENTDISPATCH_CHANGES 302 || (bypassIfNotTesting && !TestingPreparation.TEST_MODE)) { 303 304 // run it as before the EDT changes to GLI: 305 if(runVariant == RUN_IN_THREAD_PARAM_WITH_START) { 306 // start off the param thread to run the runnable in thread of param 307 // instead of whatever the current thread of the calling function is 308 Thread runInThread = (Thread)runnable; 309 runInThread.start(); // async by nature 310 } else if(runVariant == PROCEED_IN_CURRENT_THREAD) { 311 // run the Runnable code (whether Thread object or not) in 312 // whatever the current thread of the calling function is 313 runnable.run(); // synchronous by nature of runable code running on current thread 314 } 315 } else { // If we want the EDT changes to GLI active and we're in the Dispatch Thread 316 // So just run the Runnable code in the Dispatch thread, regardless of how GLI 317 // used run it. Specifically, don't call start() on any Thread param to run 318 // the code in the non-EDT thread param 319 runnable.run(); 320 } 321 322 } else { // whether the Runnable is a new Thread or other Runnable object 323 // whether GLI before EDT changes launched it with start() in its own Thread 324 // or it was code run in whatever the current thread was, we run it on the 325 // Dispatch Thread (Event Dispatch Thread, EDT) 222 326 if(invokeAs == ASYNC) { 223 327 SwingUtilities.invokeLater(runnable); // asynchronous 224 328 } else { 225 329 try { 330 System.err.println("\tXXXXX SYNC."); 226 331 SwingUtilities.invokeAndWait(runnable); // synchronous 227 332 } catch(Exception e) { … … 236 341 } 237 342 } 343 238 344 //**********************END CODE ORIGINALLY MADE FOR GUI TESTING************************ 239 345
Note:
See TracChangeset
for help on using the changeset viewer.