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