chiark / gitweb /
thread fixes: add some commentary to explain the mess
authorIan Jackson <ijackson@chiark.greenend.org.uk>
Sat, 2 Apr 2011 18:25:41 +0000 (19:25 +0100)
committerIan Jackson <ijackson@chiark.greenend.org.uk>
Sat, 2 Apr 2011 18:25:41 +0000 (19:25 +0100)
src/net/chiark/yarrg/MarketUploader.java

index c7f89426118ad9c11bf81ba350e7db1fde5e0734..14cc1b2d3861958461f7c0f6b0abbe94a400dc1b 100644 (file)
@@ -402,11 +402,45 @@ implements Runnable, TopLevelWindowListener, GUIInitializedListener {
   }
 
   /*
-   * ERROR REPORTING AND GENERAL UTILITIES
+   * THREAD HANDLING
    *
-   * Synchronous modal dialogues
-   * error and error_html may be called from any thread
-   */ 
+   * Special measures are needed because:
+   *  - it is not permitted to use any Swing UI classes or objects
+   *    other than on the Swing event thread
+   *  - we want to run our upload asynchronously
+   *  - we want to do some computation asynchronously (eg, the
+   *    arbitrage and upload data prep)
+   *
+   * So what we do is this:
+   *  1. When the user asks to upload, we spawn a new thread
+   *     to do the upload ("MarketUploader-uploader-*", see
+   *     the call to "new Thread" inside createGUI.
+   *  2. Whenever that thread needs to touch a UI object it
+   *     uses EventQueue.invokeLater or .invokeAndWait to
+   *     perform the relevant action.  We wrap these calls up
+   *     in three utility classes:
+   *        UIA  - runs code on UI thread, asynchronously
+   *        UIX  - runs code on UI thread, waits for it to finish
+   *        UIXR - as UIX but also returns a value
+   *     These hide the details of the EventQueue class and also do
+   *     some debugging and argument shuffling; the calling syntax is
+   *     still painful, unfortunately, and there is a weird constraint
+   *     on variables used inside the inner body.  For a simple
+   *     example, see the handling of "summary" and "summary_final"
+   *     for the call to UIX at the bottom of runUpload.
+   *  3. Try to put everything back when that thread exits.
+   *
+   * Additionally:
+   *  a. There is another thread spawed early to get a timestamp from
+   *     YARRG, if we are uploading there.
+   *  b. Finding the island name can involve callbacks which run in
+   *     the UI event thread.  Basically we do the work there, and use
+   *     a CountDownLatch to cause the uploader thread to wait as
+   *     appropriate.
+   */
+
+  private void on_ui_thread() { assert(EventQueue.isDispatchThread()); }
+  private void on_our_thread() { assert(!EventQueue.isDispatchThread()); }
 
   private abstract class UIA implements Runnable {
     private String what;
@@ -450,8 +484,12 @@ implements Runnable, TopLevelWindowListener, GUIInitializedListener {
     public Object bodyr() { body(); return null; }
   };
 
-  private void on_ui_thread() { assert(EventQueue.isDispatchThread()); }
-  private void on_our_thread() { assert(!EventQueue.isDispatchThread()); }
+  /*
+   * ERROR REPORTING AND GENERAL UTILITIES
+   *
+   * Synchronous modal dialogues
+   * error and error_html may be called from any thread
+   */ 
 
   private void error(final String msg) {
     try {