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&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 (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