Source code: org/dinopolis/util/gui/SwingWorker.java
1 /***********************************************************************
2 * @(#)$RCSfile: SwingWorker.java,v $ $Revision: 1.1.1.1 $$Date: 2003/01/10 15:33:38 $
3 *
4 * Copyright (c) 2002 IICM, Graz University of Technology
5 * Inffeldgasse 16c, A-8010 Graz, Austria.
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU Lesser General Public License (LGPL)
9 * as published by the Free Software Foundation; either version 2.1 of
10 * the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this program; if not, write to the
19 * Free Software Foundation, Inc.,
20 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 ***********************************************************************/
22
23
24 package org.dinopolis.util.gui;
25
26 import javax.swing.SwingUtilities;
27
28 /**
29 * This is the 3rd version of SwingWorker (also known as
30 * SwingWorker 3), an abstract class that you subclass to
31 * perform GUI-related work in a dedicated thread. For
32 * instructions on using this class, see:
33 *
34 * http://java.sun.com/docs/books/tutorial/uiswing/misc/threads.html
35 *
36 * Note that the API changed slightly in the 3rd version:
37 * You must now invoke start() on the SwingWorker after
38 * creating it.
39 */
40 public abstract class SwingWorker
41 {
42 private Object value_; // see getValue(), setValue()
43 // private Thread thread_;
44 private ThreadVar thread_var_;
45 protected String name_ = ""; // the name of the swingworker (for debugging reasons)
46
47 /**
48 * Class to maintain reference to current worker thread
49 * under separate synchronization control.
50 */
51 private static class ThreadVar
52 {
53 private Thread thread;
54 ThreadVar(Thread t)
55 {
56 thread = t;
57 }
58
59 synchronized Thread get()
60 {
61 return thread;
62 }
63
64 synchronized void clear()
65 {
66 thread = null;
67 }
68 }
69
70
71 /**
72 * Get the value produced by the worker thread, or null if it
73 * hasn't been constructed yet.
74 */
75 protected synchronized Object getValue()
76 {
77 return value_;
78 }
79
80 /**
81 * Set the value produced by worker thread
82 */
83 private synchronized void setValue(Object x)
84 {
85 value_ = x;
86 }
87
88 /**
89 * Compute the value to be returned by the <code>get</code> method.
90 */
91 public abstract Object construct();
92
93 /**
94 * Called on the event dispatching thread (not on the worker thread)
95 * after the <code>construct</code> method has returned.
96 */
97 public void finished()
98 {
99 }
100
101 /**
102 * A new method that interrupts the worker thread. Call this method
103 * to force the worker to stop what it's doing.
104 */
105 public void interrupt()
106 {
107 Thread t = thread_var_.get();
108 if (t != null)
109 {
110 t.interrupt();
111 }
112 thread_var_.clear();
113 }
114
115 /**
116 * Return the value created by the <code>construct</code> method.
117 * Returns null if either the constructing thread or the current
118 * thread was interrupted before a value was produced.
119 *
120 * @return the value created by the <code>construct</code> method
121 */
122 public Object get()
123 {
124 while (true) {
125 Thread t = thread_var_.get();
126 if (t == null)
127 {
128 return getValue();
129 }
130 try
131 {
132 t.join();
133 }
134 catch (InterruptedException e)
135 {
136 Thread.currentThread().interrupt(); // propagate
137 return null;
138 }
139 }
140 }
141
142
143 /**
144 * Start a thread that will call the <code>construct</code> method
145 * and then exit.
146 */
147 public SwingWorker()
148 {
149 final Runnable doFinished = new Runnable()
150 {
151 public void run()
152 {
153 finished();
154 }
155 };
156
157 Runnable doConstruct = new Runnable()
158 {
159 public void run()
160 {
161 try
162 {
163 setValue(construct());
164 }
165 finally
166 {
167 thread_var_.clear();
168 }
169
170 SwingUtilities.invokeLater(doFinished);
171 }
172 };
173
174 Thread t = new Thread(doConstruct);
175 thread_var_ = new ThreadVar(t);
176 }
177
178 /**
179 * Start the worker thread.
180 */
181 public void start()
182 {
183 Thread t = thread_var_.get();
184 if (t != null)
185 {
186 t.start();
187 }
188 }
189 }