From dcaa8616a31b4f4c16ce2e9f343556f4714ebc98 Mon Sep 17 00:00:00 2001 From: Ian Jackson Date: Sat, 2 Apr 2011 19:25:41 +0100 Subject: [PATCH] thread fixes: add some commentary to explain the mess --- src/net/chiark/yarrg/MarketUploader.java | 50 +++++++++++++++++++++--- 1 file changed, 44 insertions(+), 6 deletions(-) diff --git a/src/net/chiark/yarrg/MarketUploader.java b/src/net/chiark/yarrg/MarketUploader.java index c7f8942..14cc1b2 100644 --- a/src/net/chiark/yarrg/MarketUploader.java +++ b/src/net/chiark/yarrg/MarketUploader.java @@ -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 { -- 2.30.2