ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/main/java/util/concurrent/FutureTask.java
Revision: 1.44
Committed: Mon Aug 15 20:40:25 2005 UTC (18 years, 9 months ago) by jsr166
Branch: MAIN
Changes since 1.43: +9 -0 lines
Log Message:
workaround for javadoc bug 6270645

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 // 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 (ranOrCancelled(s))
240 return;
241 if (compareAndSetState(s, RAN))
242 break;
243 }
244 result = v;
245 releaseShared(0);
246 done();
247 }
248
249 void innerSetException(Throwable t) {
250 for (;;) {
251 int s = getState();
252 if (ranOrCancelled(s))
253 return;
254 if (compareAndSetState(s, RAN))
255 break;
256 }
257 exception = t;
258 result = null;
259 releaseShared(0);
260 done();
261 }
262
263 boolean innerCancel(boolean mayInterruptIfRunning) {
264 for (;;) {
265 int s = getState();
266 if (ranOrCancelled(s))
267 return false;
268 if (compareAndSetState(s, CANCELLED))
269 break;
270 }
271 if (mayInterruptIfRunning) {
272 Thread r = runner;
273 if (r != null)
274 r.interrupt();
275 }
276 releaseShared(0);
277 done();
278 return true;
279 }
280
281 void innerRun() {
282 if (!compareAndSetState(0, RUNNING))
283 return;
284 try {
285 runner = Thread.currentThread();
286 if (getState() == RUNNING) // recheck after setting thread
287 innerSet(callable.call());
288 else
289 releaseShared(0); // cancel
290 } catch (Throwable ex) {
291 innerSetException(ex);
292 }
293 }
294
295 boolean innerRunAndReset() {
296 if (!compareAndSetState(0, RUNNING))
297 return false;
298 try {
299 runner = Thread.currentThread();
300 if (getState() == RUNNING)
301 callable.call(); // don't set result
302 runner = null;
303 return compareAndSetState(RUNNING, 0);
304 } catch (Throwable ex) {
305 innerSetException(ex);
306 return false;
307 }
308 }
309 }
310 }