FutureTask.java revision 7365de1056414750d0a7d1fdd26025fd247f0d04
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
7package java.util.concurrent;
8
9import java.util.concurrent.locks.AbstractQueuedSynchronizer;
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 */
34public 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 ready to run */
165        private static final int READY     = 0;
166        /** State value representing that task is running */
167        private static final int RUNNING   = 1;
168        /** State value representing that task ran */
169        private static final int RAN       = 2;
170        /** State value representing that task was cancelled */
171        private static final int CANCELLED = 4;
172
173        /** The underlying callable */
174        private final Callable<V> callable;
175        /** The result to return from get() */
176        private V result;
177        /** The exception to throw from get() */
178        private Throwable exception;
179
180        /**
181         * The thread running task. When nulled after set/cancel, this
182         * indicates that the results are accessible.  Must be
183         * volatile, to ensure visibility upon completion.
184         */
185        private volatile Thread runner;
186
187        Sync(Callable<V> callable) {
188            this.callable = callable;
189        }
190
191        private boolean ranOrCancelled(int state) {
192            return (state & (RAN | CANCELLED)) != 0;
193        }
194
195        /**
196         * Implements AQS base acquire to succeed if ran or cancelled
197         */
198        protected int tryAcquireShared(int ignore) {
199            return innerIsDone() ? 1 : -1;
200        }
201
202        /**
203         * Implements AQS base release to always signal after setting
204         * final done status by nulling runner thread.
205         */
206        protected boolean tryReleaseShared(int ignore) {
207            runner = null;
208            return true;
209        }
210
211        boolean innerIsCancelled() {
212            return getState() == CANCELLED;
213        }
214
215        boolean innerIsDone() {
216            return ranOrCancelled(getState()) && runner == null;
217        }
218
219        V innerGet() throws InterruptedException, ExecutionException {
220            acquireSharedInterruptibly(0);
221            if (getState() == CANCELLED)
222                throw new CancellationException();
223            if (exception != null)
224                throw new ExecutionException(exception);
225            return result;
226        }
227
228        V innerGet(long nanosTimeout) throws InterruptedException, ExecutionException, TimeoutException {
229            if (!tryAcquireSharedNanos(0, nanosTimeout))
230                throw new TimeoutException();
231            if (getState() == CANCELLED)
232                throw new CancellationException();
233            if (exception != null)
234                throw new ExecutionException(exception);
235            return result;
236        }
237
238        void innerSet(V v) {
239            for (;;) {
240                int s = getState();
241                if (s == RAN)
242                    return;
243                if (s == CANCELLED) {
244                    // aggressively release to set runner to null,
245                    // in case we are racing with a cancel request
246                    // that will try to interrupt runner
247                    releaseShared(0);
248                    return;
249                }
250                if (compareAndSetState(s, RAN)) {
251                    result = v;
252                    releaseShared(0);
253                    done();
254                    return;
255                }
256            }
257        }
258
259        void innerSetException(Throwable t) {
260            for (;;) {
261                int s = getState();
262                if (s == RAN)
263                    return;
264                if (s == CANCELLED) {
265                    // aggressively release to set runner to null,
266                    // in case we are racing with a cancel request
267                    // that will try to interrupt runner
268                    releaseShared(0);
269                    return;
270                }
271                if (compareAndSetState(s, RAN)) {
272                    exception = t;
273                    releaseShared(0);
274                    done();
275                    return;
276                }
277            }
278        }
279
280        boolean innerCancel(boolean mayInterruptIfRunning) {
281            for (;;) {
282                int s = getState();
283                if (ranOrCancelled(s))
284                    return false;
285                if (compareAndSetState(s, CANCELLED))
286                    break;
287            }
288            if (mayInterruptIfRunning) {
289                Thread r = runner;
290                if (r != null)
291                    r.interrupt();
292            }
293            releaseShared(0);
294            done();
295            return true;
296        }
297
298        void innerRun() {
299            if (!compareAndSetState(READY, RUNNING))
300                return;
301
302            runner = Thread.currentThread();
303            if (getState() == RUNNING) { // recheck after setting thread
304                V result;
305                try {
306                    result = callable.call();
307                } catch (Throwable ex) {
308                    setException(ex);
309                    return;
310                }
311                set(result);
312            } else {
313                releaseShared(0); // cancel
314            }
315        }
316
317        boolean innerRunAndReset() {
318            if (!compareAndSetState(READY, RUNNING))
319                return false;
320            try {
321                runner = Thread.currentThread();
322                if (getState() == RUNNING)
323                    callable.call(); // don't set result
324                runner = null;
325                return compareAndSetState(RUNNING, READY);
326            } catch (Throwable ex) {
327                setException(ex);
328                return false;
329            }
330        }
331    }
332}
333