001: /*
002: * Gruntspud
003: *
004: * Copyright (C) 2002 Brett Smith.
005: *
006: * Written by: Brett Smith <t_magicthize@users.sourceforge.net>
007: *
008: * This program is free software; you can redistribute it and/or
009: * modify it under the terms of the GNU Library General Public License
010: * as published by the Free Software Foundation; either version 2 of
011: * the License, or (at your option) any later version.
012: * This program is distributed in the hope that it will be useful,
013: * but WITHOUT ANY WARRANTY; without even the implied warranty of
014: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
015: * GNU Library General Public License for more details.
016: *
017: * You should have received a copy of the GNU Library General Public
018: * License along with this program; if not, write to the Free Software
019: * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
020: */
021:
022: package gruntspud;
023:
024: import javax.swing.SwingUtilities;
025:
026: /**
027: * This is the 3rd version of SwingWorker (also known as
028: * SwingWorker 3), an abstract class that you subclass to
029: * perform GUI-related work in a dedicated thread. For
030: * instructions on using this class, see:
031: *
032: * http://java.sun.com/docs/books/tutorial/uiswing/misc/threads.html
033: *
034: * Note that the API changed slightly in the 3rd version:
035: * You must now invoke start() on the SwingWorker after
036: * creating it.
037: */
038: public abstract class SwingWorker {
039: private Object value; // see getValue(), setValue()
040: private Thread thread;
041: private ThreadVar threadVar;
042:
043: /**
044: * Start a thread that will call the <code>construct</code> method
045: * and then exit.
046: */
047: public SwingWorker() {
048: final Runnable doFinished = new Runnable() {
049: public void run() {
050: finished();
051: }
052: };
053:
054: Runnable doConstruct = new Runnable() {
055: public void run() {
056: try {
057: setValue(construct());
058: } finally {
059: threadVar.clear();
060: }
061:
062: SwingUtilities.invokeLater(doFinished);
063: }
064: };
065:
066: Thread t = new Thread(doConstruct);
067: threadVar = new ThreadVar(t);
068: }
069:
070: /**
071: * Get the value produced by the worker thread, or null if it
072: * hasn't been constructed yet.
073: */
074: protected synchronized Object getValue() {
075: return value;
076: }
077:
078: /**
079: * Set the value produced by worker thread
080: */
081: private synchronized void setValue(Object x) {
082: value = x;
083: }
084:
085: /**
086: * Compute the value to be returned by the <code>get</code> method.
087: */
088: public abstract Object construct();
089:
090: /**
091: * Called on the event dispatching thread (not on the worker thread)
092: * after the <code>construct</code> method has returned.
093: */
094: public void finished() {
095: }
096:
097: /**
098: * A new method that interrupts the worker thread. Call this method
099: * to force the worker to stop what it's doing.
100: */
101: public void interrupt() {
102: Thread t = threadVar.get();
103:
104: if (t != null) {
105: t.interrupt();
106:
107: }
108: threadVar.clear();
109: }
110:
111: /**
112: * Return the value created by the <code>construct</code> method.
113: * Returns null if either the constructing thread or the current
114: * thread was interrupted before a value was produced.
115: *
116: * @return the value created by the <code>construct</code> method
117: */
118: public Object get() {
119: while (true) {
120: Thread t = threadVar.get();
121:
122: if (t == null) {
123: return getValue();
124: }
125:
126: try {
127: t.join();
128: } catch (InterruptedException e) {
129: Thread.currentThread().interrupt(); // propagate
130:
131: return null;
132: }
133: }
134: }
135:
136: /**
137: * Start the worker thread.
138: */
139: public void start() {
140: Thread t = threadVar.get();
141:
142: if (t != null) {
143: t.start();
144: }
145: }
146:
147: /**
148: * Class to maintain reference to current worker thread
149: * under separate synchronization control.
150: */
151: private static class ThreadVar {
152: private Thread thread;
153:
154: ThreadVar(Thread t) {
155: thread = t;
156: }
157:
158: synchronized Thread get() {
159: return thread;
160: }
161:
162: synchronized void clear() {
163: thread = null;
164: }
165: }
166: }
|