Source code: com/xerox/VTM/engine/SwingWorker.java
1 package com.xerox.VTM.engine;
2
3 import javax.swing.SwingUtilities;
4
5 /**
6 * This is the 3rd version of SwingWorker. (also known as
7 * SwingWorker 3), an abstract class that you subclass to
8 * perform GUI-related work in a dedicated thread. For
9 * instructions on using this class, see:
10 *
11 * http://java.sun.com/docs/books/tutorial/uiswing/misc/threads.html
12 *
13 * Note that the API changed slightly in the 3rd version:
14 * You must now invoke start() on the SwingWorker after
15 * creating it.
16 */
17
18 public abstract class SwingWorker {
19 private Object value; // see getValue(), setValue()
20 private Thread thread;
21
22 /**
23 * Class to maintain reference to current worker thread
24 * under separate synchronization control.
25 */
26 private static class ThreadVar {
27 private Thread thread;
28 ThreadVar(Thread t) { thread = t; }
29 synchronized Thread get() { return thread; }
30 synchronized void clear() { thread = null; }
31 }
32
33 private ThreadVar threadVar;
34
35 /**
36 * Get the value produced by the worker thread, or null if it
37 * hasn't been constructed yet.
38 */
39 protected synchronized Object getValue() {
40 return value;
41 }
42
43 /**
44 * Set the value produced by worker thread
45 */
46 private synchronized void setValue(Object x) {
47 value = x;
48 }
49
50 /**
51 * Compute the value to be returned by the <code>get</code> method.
52 */
53 public abstract Object construct();
54
55 /**
56 * Called on the event dispatching thread (not on the worker thread)
57 * after the <code>construct</code> method has returned.
58 */
59 public void finished() {
60 }
61
62 /**
63 * A new method that interrupts the worker thread. Call this method
64 * to force the worker to stop what it's doing.
65 */
66 public void interrupt() {
67 Thread t = threadVar.get();
68 if (t != null) {
69 t.interrupt();
70 }
71 threadVar.clear();
72 }
73
74 /**
75 * A new method that puts the thread to sleep for ms millisecs
76 */
77 public void sleep(int ms) {
78 Thread t = threadVar.get();
79 if (t != null) {
80 try {
81 t.sleep(ms);
82 }
83 catch (InterruptedException ex){ex.printStackTrace();}
84 }
85 }
86
87 /**
88 * Return the value created by the <code>construct</code> method.
89 * Returns null if either the constructing thread or the current
90 * thread was interrupted before a value was produced.
91 *
92 * @return the value created by the <code>construct</code> method
93 */
94 public Object get() {
95 while (true) {
96 Thread t = threadVar.get();
97 if (t == null) {
98 return getValue();
99 }
100 try {
101 t.join();
102 }
103 catch (InterruptedException e) {
104 Thread.currentThread().interrupt(); // propagate
105 return null;
106 }
107 }
108 }
109
110
111 /**
112 * Start a thread that will call the <code>construct</code> method
113 * and then exit.
114 */
115 public SwingWorker() {
116 final Runnable doFinished = new Runnable() {
117 public void run() { finished(); }
118 };
119
120 Runnable doConstruct = new Runnable() {
121 public void run() {
122 try {
123 setValue(construct());
124 }
125 finally {
126 threadVar.clear();
127 }
128
129 SwingUtilities.invokeLater(doFinished);
130 }
131 };
132
133 Thread t = new Thread(doConstruct);
134 threadVar = new ThreadVar(t);
135 }
136
137 /**
138 * Start the worker thread.
139 */
140 public void start() {
141 Thread t = threadVar.get();
142 if (t != null) {
143 t.start();
144 }
145 }
146 }
147