ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/main/java/util/concurrent/FutureTask.java
Revision: 1.35
Committed: Mon May 2 18:38:53 2005 UTC (19 years, 1 month ago) by jsr166
Branch: MAIN
Changes since 1.34: +14 -14 lines
Log Message:
remove trailing whitespace

File Contents

# User Rev Content
1 tim 1.1 /*
2 dl 1.2 * Written by Doug Lea with assistance from members of JCP JSR-166
3 dl 1.23 * Expert Group and released to the public domain, as explained at
4     * http://creativecommons.org/licenses/publicdomain
5 tim 1.1 */
6    
7     package java.util.concurrent;
8 dl 1.13 import java.util.concurrent.locks.*;
9    
10 tim 1.1 /**
11 dl 1.8 * A cancellable asynchronous computation. This class provides a base
12     * implementation of {@link Future}, with methods to start and cancel
13     * a computation, query to see if the computation is complete, and
14 dl 1.4 * retrieve the result of the computation. The result can only be
15     * retrieved when the computation has completed; the <tt>get</tt>
16     * method will block if the computation has not yet completed. Once
17 dl 1.8 * the computation has completed, the computation cannot be restarted
18     * or cancelled.
19 tim 1.1 *
20 dl 1.8 * <p>A <tt>FutureTask</tt> can be used to wrap a {@link Callable} or
21     * {@link java.lang.Runnable} object. Because <tt>FutureTask</tt>
22     * implements <tt>Runnable</tt>, a <tt>FutureTask</tt> can be
23     * submitted to an {@link Executor} for execution.
24 tim 1.1 *
25 dl 1.14 * <p>In addition to serving as a standalone class, this class provides
26     * <tt>protected</tt> functionality that may be useful when creating
27     * customized task classes.
28     *
29 tim 1.1 * @since 1.5
30 dl 1.4 * @author Doug Lea
31 dl 1.12 * @param <V> The result type returned by this FutureTask's <tt>get</tt> method
32 tim 1.1 */
33 dl 1.13 public class FutureTask<V> implements Future<V>, Runnable {
34 dl 1.24 /** Synchronization control for FutureTask */
35     private final Sync sync;
36 dl 1.11
37 tim 1.1 /**
38 dl 1.31 * Creates a <tt>FutureTask</tt> that will upon running, execute the
39 tim 1.1 * given <tt>Callable</tt>.
40     *
41     * @param callable the callable task
42 dl 1.9 * @throws NullPointerException if callable is null
43 tim 1.1 */
44     public FutureTask(Callable<V> callable) {
45 dl 1.9 if (callable == null)
46     throw new NullPointerException();
47 dl 1.24 sync = new Sync(callable);
48 tim 1.1 }
49    
50     /**
51 dl 1.31 * Creates a <tt>FutureTask</tt> that will upon running, execute the
52 tim 1.1 * given <tt>Runnable</tt>, and arrange that <tt>get</tt> will return the
53     * given result on successful completion.
54     *
55     * @param runnable the runnable task
56     * @param result the result to return on successful completion. If
57 dl 1.9 * you don't need a particular result, consider using
58 dl 1.16 * constructions of the form:
59     * <tt>Future&lt;?&gt; f = new FutureTask&lt;Object&gt;(runnable, null)</tt>
60 dl 1.9 * @throws NullPointerException if runnable is null
61 tim 1.1 */
62 dl 1.15 public FutureTask(Runnable runnable, V result) {
63 dl 1.24 sync = new Sync(Executors.callable(runnable, result));
64 dl 1.20 }
65    
66     public boolean isCancelled() {
67 dl 1.27 return sync.innerIsCancelled();
68 dl 1.20 }
69 jsr166 1.35
70 dl 1.20 public boolean isDone() {
71 dl 1.27 return sync.innerIsDone();
72 dl 1.13 }
73    
74     public boolean cancel(boolean mayInterruptIfRunning) {
75 dl 1.27 return sync.innerCancel(mayInterruptIfRunning);
76 dl 1.13 }
77 jsr166 1.35
78 dl 1.2 public V get() throws InterruptedException, ExecutionException {
79 dl 1.27 return sync.innerGet();
80 tim 1.1 }
81    
82 dl 1.2 public V get(long timeout, TimeUnit unit)
83 tim 1.1 throws InterruptedException, ExecutionException, TimeoutException {
84 dl 1.27 return sync.innerGet(unit.toNanos(timeout));
85 tim 1.1 }
86    
87     /**
88 dl 1.20 * Protected method invoked when this task transitions to state
89     * <tt>isDone</tt> (whether normally or via cancellation). The
90     * default implementation does nothing. Subclasses may override
91     * this method to invoke completion callbacks or perform
92     * bookkeeping. Note that you can query status inside the
93     * implementation of this method to determine whether this task
94     * has been cancelled.
95     */
96     protected void done() { }
97    
98     /**
99     * Sets the result of this Future to the given value unless
100 dl 1.29 * this future has already been set or has been cancelled.
101 tim 1.1 * @param v the value
102 jsr166 1.35 */
103 dl 1.2 protected void set(V v) {
104 dl 1.27 sync.innerSet(v);
105 tim 1.1 }
106    
107     /**
108 dl 1.13 * Causes this future to report an <tt>ExecutionException</tt>
109 dl 1.20 * with the given throwable as its cause, unless this Future has
110 dl 1.24 * already been set or has been cancelled.
111 dl 1.13 * @param t the cause of failure.
112 jsr166 1.35 */
113 dl 1.2 protected void setException(Throwable t) {
114 dl 1.27 sync.innerSetException(t);
115 tim 1.1 }
116 jsr166 1.35
117 dl 1.14 /**
118 dl 1.24 * Sets this Future to the result of computation unless
119     * it has been cancelled.
120     */
121     public void run() {
122 dl 1.27 sync.innerRun();
123 dl 1.24 }
124    
125     /**
126 dl 1.30 * Executes the computation without setting its result, and then
127     * resets this Future to initial state, failing to do so if the
128 dl 1.24 * computation encounters an exception or is cancelled. This is
129     * designed for use with tasks that intrinsically execute more
130     * than once.
131     * @return true if successfully run and reset
132     */
133     protected boolean runAndReset() {
134 dl 1.27 return sync.innerRunAndReset();
135 dl 1.14 }
136 dl 1.3
137 dl 1.14 /**
138 dl 1.24 * Synchronization control for FutureTask. Note that this must be
139 dl 1.30 * a non-static inner class in order to invoke the protected
140 dl 1.24 * <tt>done</tt> method. For clarity, all inner class support
141 dl 1.27 * methods are same as outer, prefixed with "inner".
142 dl 1.24 *
143     * Uses AQS sync state to represent run status
144 dl 1.20 */
145 dl 1.24 private final class Sync extends AbstractQueuedSynchronizer {
146     /** State value representing that task is running */
147     private static final int RUNNING = 1;
148     /** State value representing that task ran */
149     private static final int RAN = 2;
150     /** State value representing that task was cancelled */
151     private static final int CANCELLED = 4;
152    
153     /** The underlying callable */
154     private final Callable<V> callable;
155     /** The result to return from get() */
156     private V result;
157     /** The exception to throw from get() */
158     private Throwable exception;
159    
160 jsr166 1.35 /**
161 dl 1.24 * The thread running task. When nulled after set/cancel, this
162     * indicates that the results are accessible. Must be
163 dl 1.32 * volatile, to ensure visibility upon completion.
164 dl 1.24 */
165     private volatile Thread runner;
166    
167     Sync(Callable<V> callable) {
168     this.callable = callable;
169     }
170    
171     private boolean ranOrCancelled(int state) {
172     return (state & (RAN | CANCELLED)) != 0;
173     }
174    
175     /**
176 dl 1.26 * Implements AQS base acquire to succeed if ran or cancelled
177 dl 1.24 */
178 dl 1.26 protected int tryAcquireShared(int ignore) {
179 dl 1.27 return innerIsDone()? 1 : -1;
180 dl 1.24 }
181    
182     /**
183     * Implements AQS base release to always signal after setting
184     * final done status by nulling runner thread.
185     */
186 dl 1.25 protected boolean tryReleaseShared(int ignore) {
187 dl 1.24 runner = null;
188 jsr166 1.35 return true;
189 dl 1.24 }
190    
191 dl 1.27 boolean innerIsCancelled() {
192 dl 1.24 return getState() == CANCELLED;
193     }
194 jsr166 1.35
195 dl 1.27 boolean innerIsDone() {
196 dl 1.24 return ranOrCancelled(getState()) && runner == null;
197     }
198    
199 dl 1.27 V innerGet() throws InterruptedException, ExecutionException {
200 dl 1.24 acquireSharedInterruptibly(0);
201     if (getState() == CANCELLED)
202     throw new CancellationException();
203     if (exception != null)
204     throw new ExecutionException(exception);
205     return result;
206     }
207    
208 dl 1.27 V innerGet(long nanosTimeout) throws InterruptedException, ExecutionException, TimeoutException {
209 dl 1.28 if (!tryAcquireSharedNanos(0, nanosTimeout))
210 jsr166 1.35 throw new TimeoutException();
211 dl 1.24 if (getState() == CANCELLED)
212     throw new CancellationException();
213     if (exception != null)
214     throw new ExecutionException(exception);
215     return result;
216     }
217    
218 dl 1.27 void innerSet(V v) {
219 dl 1.33 for (;;) {
220     int s = getState();
221     if (ranOrCancelled(s))
222     return;
223     if (compareAndSetState(s, RAN))
224     break;
225     }
226 dl 1.24 result = v;
227     releaseShared(0);
228     done();
229     }
230    
231 dl 1.27 void innerSetException(Throwable t) {
232 dl 1.33 for (;;) {
233     int s = getState();
234     if (ranOrCancelled(s))
235     return;
236     if (compareAndSetState(s, RAN))
237     break;
238     }
239 dl 1.24 exception = t;
240     result = null;
241     releaseShared(0);
242     done();
243     }
244    
245 dl 1.27 boolean innerCancel(boolean mayInterruptIfRunning) {
246 dl 1.33 for (;;) {
247     int s = getState();
248     if (ranOrCancelled(s))
249     return false;
250 jsr166 1.35 if (compareAndSetState(s, CANCELLED))
251 dl 1.33 break;
252     }
253 dl 1.24 if (mayInterruptIfRunning) {
254     Thread r = runner;
255     if (r != null)
256     r.interrupt();
257     }
258     releaseShared(0);
259     done();
260 dl 1.14 return true;
261     }
262    
263 dl 1.27 void innerRun() {
264 jsr166 1.35 if (!compareAndSetState(0, RUNNING))
265 dl 1.24 return;
266 dl 1.14 try {
267 dl 1.24 runner = Thread.currentThread();
268 dl 1.27 innerSet(callable.call());
269 jsr166 1.34 } catch (Throwable ex) {
270 dl 1.27 innerSetException(ex);
271 jsr166 1.35 }
272 dl 1.14 }
273    
274 dl 1.27 boolean innerRunAndReset() {
275 jsr166 1.35 if (!compareAndSetState(0, RUNNING))
276 dl 1.24 return false;
277 dl 1.15 try {
278 dl 1.24 runner = Thread.currentThread();
279     callable.call(); // don't set result
280     runner = null;
281     return compareAndSetState(RUNNING, 0);
282 jsr166 1.34 } catch (Throwable ex) {
283 dl 1.27 innerSetException(ex);
284 dl 1.24 return false;
285 jsr166 1.35 }
286 dl 1.14 }
287 dl 1.15 }
288     }