ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/main/java/util/concurrent/FutureTask.java
Revision: 1.32
Committed: Sat Apr 10 14:25:24 2004 UTC (20 years, 1 month ago) by dl
Branch: MAIN
Changes since 1.31: +1 -1 lines
Log Message:
Documentation improvements

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.locks.*;
9
10 /**
11 * 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 * 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 * the computation has completed, the computation cannot be restarted
18 * or cancelled.
19 *
20 * <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 *
25 * <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 * @since 1.5
30 * @author Doug Lea
31 * @param <V> The result type returned by this FutureTask's <tt>get</tt> method
32 */
33 public class FutureTask<V> implements Future<V>, Runnable {
34 /** Synchronization control for FutureTask */
35 private final Sync sync;
36
37 /**
38 * Creates a <tt>FutureTask</tt> that will upon running, execute the
39 * given <tt>Callable</tt>.
40 *
41 * @param callable the callable task
42 * @throws NullPointerException if callable is null
43 */
44 public FutureTask(Callable<V> callable) {
45 if (callable == null)
46 throw new NullPointerException();
47 sync = new Sync(callable);
48 }
49
50 /**
51 * Creates a <tt>FutureTask</tt> that will upon running, execute the
52 * 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 * you don't need a particular result, consider using
58 * constructions of the form:
59 * <tt>Future&lt;?&gt; f = new FutureTask&lt;Object&gt;(runnable, null)</tt>
60 * @throws NullPointerException if runnable is null
61 */
62 public FutureTask(Runnable runnable, V result) {
63 sync = new Sync(Executors.callable(runnable, result));
64 }
65
66 public boolean isCancelled() {
67 return sync.innerIsCancelled();
68 }
69
70 public boolean isDone() {
71 return sync.innerIsDone();
72 }
73
74 public boolean cancel(boolean mayInterruptIfRunning) {
75 return sync.innerCancel(mayInterruptIfRunning);
76 }
77
78 public V get() throws InterruptedException, ExecutionException {
79 return sync.innerGet();
80 }
81
82 public V get(long timeout, TimeUnit unit)
83 throws InterruptedException, ExecutionException, TimeoutException {
84 return sync.innerGet(unit.toNanos(timeout));
85 }
86
87 /**
88 * 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 * this future has already been set or has been cancelled.
101 * @param v the value
102 */
103 protected void set(V v) {
104 sync.innerSet(v);
105 }
106
107 /**
108 * Causes this future to report an <tt>ExecutionException</tt>
109 * with the given throwable as its cause, unless this Future has
110 * already been set or has been cancelled.
111 * @param t the cause of failure.
112 */
113 protected void setException(Throwable t) {
114 sync.innerSetException(t);
115 }
116
117 /**
118 * Sets this Future to the result of computation unless
119 * it has been cancelled.
120 */
121 public void run() {
122 sync.innerRun();
123 }
124
125 /**
126 * Executes the computation without setting its result, and then
127 * resets this Future to initial state, failing to do so if the
128 * 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 return sync.innerRunAndReset();
135 }
136
137 /**
138 * Synchronization control for FutureTask. Note that this must be
139 * a non-static inner class in order to invoke the protected
140 * <tt>done</tt> method. For clarity, all inner class support
141 * methods are same as outer, prefixed with "inner".
142 *
143 * Uses AQS sync state to represent run status
144 */
145 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 /**
161 * The thread running task. When nulled after set/cancel, this
162 * indicates that the results are accessible. Must be
163 * volatile, to ensure visibility upon completion.
164 */
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 * Implements AQS base acquire to succeed if ran or cancelled
177 */
178 protected int tryAcquireShared(int ignore) {
179 return innerIsDone()? 1 : -1;
180 }
181
182 /**
183 * Implements AQS base release to always signal after setting
184 * final done status by nulling runner thread.
185 */
186 protected boolean tryReleaseShared(int ignore) {
187 runner = null;
188 return true;
189 }
190
191 boolean innerIsCancelled() {
192 return getState() == CANCELLED;
193 }
194
195 boolean innerIsDone() {
196 return ranOrCancelled(getState()) && runner == null;
197 }
198
199 V innerGet() throws InterruptedException, ExecutionException {
200 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 V innerGet(long nanosTimeout) throws InterruptedException, ExecutionException, TimeoutException {
209 if (!tryAcquireSharedNanos(0, nanosTimeout))
210 throw new TimeoutException();
211 if (getState() == CANCELLED)
212 throw new CancellationException();
213 if (exception != null)
214 throw new ExecutionException(exception);
215 return result;
216 }
217
218 void innerSet(V v) {
219 int s = getState();
220 if (ranOrCancelled(s) || !compareAndSetState(s, RAN))
221 return;
222 result = v;
223 releaseShared(0);
224 done();
225 }
226
227 void innerSetException(Throwable t) {
228 int s = getState();
229 if (ranOrCancelled(s) || !compareAndSetState(s, RAN))
230 return;
231 exception = t;
232 result = null;
233 releaseShared(0);
234 done();
235 }
236
237 boolean innerCancel(boolean mayInterruptIfRunning) {
238 int s = getState();
239 if (ranOrCancelled(s) || !compareAndSetState(s, CANCELLED))
240 return false;
241 if (mayInterruptIfRunning) {
242 Thread r = runner;
243 if (r != null)
244 r.interrupt();
245 }
246 releaseShared(0);
247 done();
248 return true;
249 }
250
251 void innerRun() {
252 if (!compareAndSetState(0, RUNNING))
253 return;
254 try {
255 runner = Thread.currentThread();
256 innerSet(callable.call());
257 } catch(Throwable ex) {
258 innerSetException(ex);
259 }
260 }
261
262 boolean innerRunAndReset() {
263 if (!compareAndSetState(0, RUNNING))
264 return false;
265 try {
266 runner = Thread.currentThread();
267 callable.call(); // don't set result
268 runner = null;
269 return compareAndSetState(RUNNING, 0);
270 } catch(Throwable ex) {
271 innerSetException(ex);
272 return false;
273 }
274 }
275 }
276 }