ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/main/java/util/concurrent/FutureTask.java
Revision: 1.43
Committed: Thu Jul 21 03:03:22 2005 UTC (18 years, 10 months ago) by jsr166
Branch: MAIN
Changes since 1.42: +7 -1 lines
Log Message:
CancellationException

File Contents

# Content
1 /*
2 * Written by Doug Lea with assistance from members of JCP JSR-166
3 * Expert Group and released to the public domain, as explained at
4 * http://creativecommons.org/licenses/publicdomain
5 */
6
7 package java.util.concurrent;
8 import java.util.concurrent.*; // for javadoc (till 6280605 is fixed)
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&lt;?&gt; f = new FutureTask&lt;Object&gt;(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 public void run() {
129 sync.innerRun();
130 }
131
132 /**
133 * Executes the computation without setting its result, and then
134 * resets this Future to initial state, failing to do so if the
135 * computation encounters an exception or is cancelled. This is
136 * designed for use with tasks that intrinsically execute more
137 * than once.
138 * @return true if successfully run and reset
139 */
140 protected boolean runAndReset() {
141 return sync.innerRunAndReset();
142 }
143
144 /**
145 * Synchronization control for FutureTask. Note that this must be
146 * a non-static inner class in order to invoke the protected
147 * <tt>done</tt> method. For clarity, all inner class support
148 * methods are same as outer, prefixed with "inner".
149 *
150 * Uses AQS sync state to represent run status
151 */
152 private final class Sync extends AbstractQueuedSynchronizer {
153 private static final long serialVersionUID = -7828117401763700385L;
154
155 /** State value representing that task is running */
156 private static final int RUNNING = 1;
157 /** State value representing that task ran */
158 private static final int RAN = 2;
159 /** State value representing that task was cancelled */
160 private static final int CANCELLED = 4;
161
162 /** The underlying callable */
163 private final Callable<V> callable;
164 /** The result to return from get() */
165 private V result;
166 /** The exception to throw from get() */
167 private Throwable exception;
168
169 /**
170 * The thread running task. When nulled after set/cancel, this
171 * indicates that the results are accessible. Must be
172 * volatile, to ensure visibility upon completion.
173 */
174 private volatile Thread runner;
175
176 Sync(Callable<V> callable) {
177 this.callable = callable;
178 }
179
180 private boolean ranOrCancelled(int state) {
181 return (state & (RAN | CANCELLED)) != 0;
182 }
183
184 /**
185 * Implements AQS base acquire to succeed if ran or cancelled
186 */
187 protected int tryAcquireShared(int ignore) {
188 return innerIsDone()? 1 : -1;
189 }
190
191 /**
192 * Implements AQS base release to always signal after setting
193 * final done status by nulling runner thread.
194 */
195 protected boolean tryReleaseShared(int ignore) {
196 runner = null;
197 return true;
198 }
199
200 boolean innerIsCancelled() {
201 return getState() == CANCELLED;
202 }
203
204 boolean innerIsDone() {
205 return ranOrCancelled(getState()) && runner == null;
206 }
207
208 V innerGet() throws InterruptedException, ExecutionException {
209 acquireSharedInterruptibly(0);
210 if (getState() == CANCELLED)
211 throw new CancellationException();
212 if (exception != null)
213 throw new ExecutionException(exception);
214 return result;
215 }
216
217 V innerGet(long nanosTimeout) throws InterruptedException, ExecutionException, TimeoutException {
218 if (!tryAcquireSharedNanos(0, nanosTimeout))
219 throw new TimeoutException();
220 if (getState() == CANCELLED)
221 throw new CancellationException();
222 if (exception != null)
223 throw new ExecutionException(exception);
224 return result;
225 }
226
227 void innerSet(V v) {
228 for (;;) {
229 int s = getState();
230 if (ranOrCancelled(s))
231 return;
232 if (compareAndSetState(s, RAN))
233 break;
234 }
235 result = v;
236 releaseShared(0);
237 done();
238 }
239
240 void innerSetException(Throwable t) {
241 for (;;) {
242 int s = getState();
243 if (ranOrCancelled(s))
244 return;
245 if (compareAndSetState(s, RAN))
246 break;
247 }
248 exception = t;
249 result = null;
250 releaseShared(0);
251 done();
252 }
253
254 boolean innerCancel(boolean mayInterruptIfRunning) {
255 for (;;) {
256 int s = getState();
257 if (ranOrCancelled(s))
258 return false;
259 if (compareAndSetState(s, CANCELLED))
260 break;
261 }
262 if (mayInterruptIfRunning) {
263 Thread r = runner;
264 if (r != null)
265 r.interrupt();
266 }
267 releaseShared(0);
268 done();
269 return true;
270 }
271
272 void innerRun() {
273 if (!compareAndSetState(0, RUNNING))
274 return;
275 try {
276 runner = Thread.currentThread();
277 if (getState() == RUNNING) // recheck after setting thread
278 innerSet(callable.call());
279 else
280 releaseShared(0); // cancel
281 } catch (Throwable ex) {
282 innerSetException(ex);
283 }
284 }
285
286 boolean innerRunAndReset() {
287 if (!compareAndSetState(0, RUNNING))
288 return false;
289 try {
290 runner = Thread.currentThread();
291 if (getState() == RUNNING)
292 callable.call(); // don't set result
293 runner = null;
294 return compareAndSetState(RUNNING, 0);
295 } catch (Throwable ex) {
296 innerSetException(ex);
297 return false;
298 }
299 }
300 }
301 }