View Javadoc

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