Changeset 39031


Ignore:
Timestamp:
2024-05-17T22:44:25+12:00 (3 weeks ago)
Author:
anupama
Message:

Lots of important changes after talking to Dr Bainbridge: the public invokeOnEDT() variants are now the regaular case invokeInEDT_replacesProceedInCurrThread() and the special case where we have to start the Thread param if we've switched off the EDT changes: invokeInEDT_replacesThreadStart(). If bypassing on a case by case basis, then for each case (each instance of calling invokeInEDT variant) there's also printing of the calling thread name and any Thread param name (if a Thread was passed in). Can clean it up a little more.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • main/trunk/gli/src/org/greenstone/gatherer/Gatherer.java

    r39030 r39031  
    172172   
    173173    //******************* CODE FOR IMPORTANT HELPER FUNCTIONS FOR GUI TESTING *****************
    174    
     174
    175175    // Changes made to GLI execute GUI code in the Event Dispatch Thread (EDT) allowing GUI
    176176    // testing with AssertJ Swing can be beneficial for GLI overall. In case it breaks GLI
    177177    // or you suspect it has, set this to true. There's still extra method invocations, but
    178178    // 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   
    181182    // SYNC executes code with invokeAndWait on the EDT (waiting until termination of the runnable)
    182183    // ASYNC calls invokeLater() which is the same as calling aThread.start(), not waiting for
    183184    // any result of the code being executed.
    184     static public boolean SYNC = true;
    185     static public boolean ASYNC = false;
     185    public static final boolean SYNC = true;
     186    public static final boolean ASYNC = false;
    186187    // 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);
    198212    }
     213    */
    199214    // Call like:
    200215    /*
    201       Gatherer.invokeInDispatchThread("Gatherer.init()", Gatherer.<SYNC|ASYNC>, new Runnable() {
     216      Gatherer.invokeInEDT_replacesProceedInCurrThread("Gatherer.init()", Gatherer.<SYNC|ASYNC>, new Runnable() {
    202217         public void run() {
    203218            .... some GUI/event code that should happen on EDT
     
    206221    */
    207222    // 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);
    211235    }
    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   
    214288    if(TURN_OFF_EVENTDISPATCH_CHANGES
    215289       || (bypassIfNotTesting && !TestingPreparation.TEST_MODE)
    216        || EventQueue.isDispatchThread()) {
     290       || EventQueue.isDispatchThread()) {   
     291       
    217292        if (bypassIfNotTesting && !TestingPreparation.TEST_MODE) {
    218         System.err.println(callerDescription + " - Bypassing EDT change");
     293        System.err.println("@@@@" + callerDescription + " - Bypassing EDT change");
    219294        }
    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)
    222326        if(invokeAs == ASYNC) {
    223327        SwingUtilities.invokeLater(runnable); // asynchronous
    224328        } else {
    225329        try {
     330            System.err.println("\tXXXXX SYNC.");
    226331            SwingUtilities.invokeAndWait(runnable); // synchronous
    227332        } catch(Exception e) {
     
    236341    }
    237342    }
     343   
    238344    //**********************END CODE ORIGINALLY MADE FOR GUI TESTING************************
    239345   
Note: See TracChangeset for help on using the changeset viewer.