1 package triptracker.client.ui;
2 import javax.swing.SwingUtilities;
3
4 /***
5 * This is the 3rd version of SwingWorker (also known as
6 * SwingWorker 3), an abstract class that you subclass to
7 * perform GUI-related work in a dedicated thread. For
8 * instructions on using this class, see:
9 *
10 * http://java.sun.com/docs/books/tutorial/uiswing/misc/threads.html
11 *
12 * Note that the API changed slightly in the 3rd version:
13 * You must now invoke start() on the SwingWorker after
14 * creating it.
15 */
16 public abstract class SwingWorker {
17 private Object value;
18 private Thread thread;
19
20 /***
21 * Class to maintain reference to current worker thread
22 * under separate synchronization control.
23 */
24 private static class ThreadVar {
25 private Thread thread;
26 ThreadVar(Thread t) { thread = t; }
27 synchronized Thread get() { return thread; }
28 synchronized void clear() { thread = null; }
29 }
30
31 private ThreadVar threadVar;
32
33 /***
34 * Get the value produced by the worker thread, or null if it
35 * hasn't been constructed yet.
36 */
37 protected synchronized Object getValue() {
38 return value;
39 }
40
41 /***
42 * Set the value produced by worker thread
43 */
44 private synchronized void setValue(Object x) {
45 value = x;
46 }
47
48 /***
49 * Compute the value to be returned by the <code>get</code> method.
50 */
51 public abstract Object construct();
52
53 /***
54 * Called on the event dispatching thread (not on the worker thread)
55 * after the <code>construct</code> method has returned.
56 */
57 public void finished() {
58 }
59
60 /***
61 * A new method that interrupts the worker thread. Call this method
62 * to force the worker to stop what it's doing.
63 */
64 public void interrupt() {
65 Thread t = threadVar.get();
66 if (t != null) {
67 t.interrupt();
68 }
69 threadVar.clear();
70 }
71
72 /***
73 * Tests if this thread is alive. A thread is alive if it has been started
74 * and has not yet died.
75 *
76 * @return true if this thread is alive; false otherwise.
77 */
78 public boolean isAlive() {
79 Thread t = threadVar.get();
80 if (t != null) {
81 return t.isAlive();
82 } else {
83 return false;
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();
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 }