1 /*
   2  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   3  *
   4  * This code is free software; you can redistribute it and/or modify it
   5  * under the terms of the GNU General Public License version 2 only, as
   6  * published by the Free Software Foundation.  Oracle designates this
   7  * particular file as subject to the "Classpath" exception as provided
   8  * by Oracle in the LICENSE file that accompanied this code.
   9  *
  10  * This code is distributed in the hope that it will be useful, but WITHOUT
  11  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  12  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  13  * version 2 for more details (a copy is included in the LICENSE file that
  14  * accompanied this code).
  15  *
  16  * You should have received a copy of the GNU General Public License version
  17  * 2 along with this work; if not, write to the Free Software Foundation,
  18  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  19  *
  20  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  21  * or visit www.oracle.com if you need additional information or have any
  22  * questions.
  23  */
  24 
  25 /*
  26  * This file is available under and governed by the GNU General Public
  27  * License version 2 only, as published by the Free Software Foundation.
  28  * However, the following notice accompanied the original version of this
  29  * file:
  30  *
  31  * Written by Doug Lea with assistance from members of JCP JSR-166
  32  * Expert Group and released to the public domain, as explained at
  33  * http://creativecommons.org/licenses/publicdomain
  34  */
  35 
  36 package java.util.concurrent;
  37 import java.util.concurrent.locks.*;
  38 
  39 /**
  40  * A cancellable asynchronous computation.  This class provides a base
  41  * implementation of {@link Future}, with methods to start and cancel
  42  * a computation, query to see if the computation is complete, and
  43  * retrieve the result of the computation.  The result can only be
  44  * retrieved when the computation has completed; the <tt>get</tt>
  45  * method will block if the computation has not yet completed.  Once
  46  * the computation has completed, the computation cannot be restarted
  47  * or cancelled.
  48  *
  49  * <p>A <tt>FutureTask</tt> can be used to wrap a {@link Callable} or
  50  * {@link java.lang.Runnable} object.  Because <tt>FutureTask</tt>
  51  * implements <tt>Runnable</tt>, a <tt>FutureTask</tt> can be
  52  * submitted to an {@link Executor} for execution.
  53  *
  54  * <p>In addition to serving as a standalone class, this class provides
  55  * <tt>protected</tt> functionality that may be useful when creating
  56  * customized task classes.
  57  *
  58  * @since 1.5
  59  * @author Doug Lea
  60  * @param <V> The result type returned by this FutureTask's <tt>get</tt> method
  61  */
  62 public class FutureTask<V> implements RunnableFuture<V> {
  63     /** Synchronization control for FutureTask */
  64     private final Sync sync;
  65 
  66     /**
  67      * Creates a <tt>FutureTask</tt> that will, upon running, execute the
  68      * given <tt>Callable</tt>.
  69      *
  70      * @param  callable the callable task
  71      * @throws NullPointerException if callable is null
  72      */
  73     public FutureTask(Callable<V> callable) {
  74         if (callable == null)
  75             throw new NullPointerException();
  76         sync = new Sync(callable);
  77     }
  78 
  79     /**
  80      * Creates a <tt>FutureTask</tt> that will, upon running, execute the
  81      * given <tt>Runnable</tt>, and arrange that <tt>get</tt> will return the
  82      * given result on successful completion.
  83      *
  84      * @param runnable the runnable task
  85      * @param result the result to return on successful completion. If
  86      * you don't need a particular result, consider using
  87      * constructions of the form:
  88      * <tt>Future&lt;?&gt; f = new FutureTask&lt;Object&gt;(runnable, null)</tt>
  89      * @throws NullPointerException if runnable is null
  90      */
  91     public FutureTask(Runnable runnable, V result) {
  92         sync = new Sync(Executors.callable(runnable, result));
  93     }
  94 
  95     public boolean isCancelled() {
  96         return sync.innerIsCancelled();
  97     }
  98 
  99     public boolean isDone() {
 100         return sync.innerIsDone();
 101     }
 102 
 103     public boolean cancel(boolean mayInterruptIfRunning) {
 104         return sync.innerCancel(mayInterruptIfRunning);
 105     }
 106 
 107     /**
 108      * @throws CancellationException {@inheritDoc}
 109      */
 110     public V get() throws InterruptedException, ExecutionException {
 111         return sync.innerGet();
 112     }
 113 
 114     /**
 115      * @throws CancellationException {@inheritDoc}
 116      */
 117     public V get(long timeout, TimeUnit unit)
 118         throws InterruptedException, ExecutionException, TimeoutException {
 119         return sync.innerGet(unit.toNanos(timeout));
 120     }
 121 
 122     /**
 123      * Protected method invoked when this task transitions to state
 124      * <tt>isDone</tt> (whether normally or via cancellation). The
 125      * default implementation does nothing.  Subclasses may override
 126      * this method to invoke completion callbacks or perform
 127      * bookkeeping. Note that you can query status inside the
 128      * implementation of this method to determine whether this task
 129      * has been cancelled.
 130      */
 131     protected void done() { }
 132 
 133     /**
 134      * Sets the result of this Future to the given value unless
 135      * this future has already been set or has been cancelled.
 136      * This method is invoked internally by the <tt>run</tt> method
 137      * upon successful completion of the computation.
 138      * @param v the value
 139      */
 140     protected void set(V v) {
 141         sync.innerSet(v);
 142     }
 143 
 144     /**
 145      * Causes this future to report an <tt>ExecutionException</tt>
 146      * with the given throwable as its cause, unless this Future has
 147      * already been set or has been cancelled.
 148      * This method is invoked internally by the <tt>run</tt> method
 149      * upon failure of the computation.
 150      * @param t the cause of failure
 151      */
 152     protected void setException(Throwable t) {
 153         sync.innerSetException(t);
 154     }
 155 
 156     // The following (duplicated) doc comment can be removed once
 157     //
 158     // 6270645: Javadoc comments should be inherited from most derived
 159     //          superinterface or superclass
 160     // is fixed.
 161     /**
 162      * Sets this Future to the result of its computation
 163      * unless it has been cancelled.
 164      */
 165     public void run() {
 166         sync.innerRun();
 167     }
 168 
 169     /**
 170      * Executes the computation without setting its result, and then
 171      * resets this Future to initial state, failing to do so if the
 172      * computation encounters an exception or is cancelled.  This is
 173      * designed for use with tasks that intrinsically execute more
 174      * than once.
 175      * @return true if successfully run and reset
 176      */
 177     protected boolean runAndReset() {
 178         return sync.innerRunAndReset();
 179     }
 180 
 181     /**
 182      * Synchronization control for FutureTask. Note that this must be
 183      * a non-static inner class in order to invoke the protected
 184      * <tt>done</tt> method. For clarity, all inner class support
 185      * methods are same as outer, prefixed with "inner".
 186      *
 187      * Uses AQS sync state to represent run status
 188      */
 189     private final class Sync extends AbstractQueuedSynchronizer {
 190         private static final long serialVersionUID = -7828117401763700385L;
 191 
 192         /** State value representing that task is ready to run */
 193         private static final int READY     = 0;
 194         /** State value representing that task is running */
 195         private static final int RUNNING   = 1;
 196         /** State value representing that task ran */
 197         private static final int RAN       = 2;
 198         /** State value representing that task was cancelled */
 199         private static final int CANCELLED = 4;
 200 
 201         /** The underlying callable */
 202         private final Callable<V> callable;
 203         /** The result to return from get() */
 204         private V result;
 205         /** The exception to throw from get() */
 206         private Throwable exception;
 207 
 208         /**
 209          * The thread running task. When nulled after set/cancel, this
 210          * indicates that the results are accessible.  Must be
 211          * volatile, to ensure visibility upon completion.
 212          */
 213         private volatile Thread runner;
 214 
 215         Sync(Callable<V> callable) {
 216             this.callable = callable;
 217         }
 218 
 219         private boolean ranOrCancelled(int state) {
 220             return (state & (RAN | CANCELLED)) != 0;
 221         }
 222 
 223         /**
 224          * Implements AQS base acquire to succeed if ran or cancelled
 225          */
 226         protected int tryAcquireShared(int ignore) {
 227             return innerIsDone() ? 1 : -1;
 228         }
 229 
 230         /**
 231          * Implements AQS base release to always signal after setting
 232          * final done status by nulling runner thread.
 233          */
 234         protected boolean tryReleaseShared(int ignore) {
 235             runner = null;
 236             return true;
 237         }
 238 
 239         boolean innerIsCancelled() {
 240             return getState() == CANCELLED;
 241         }
 242 
 243         boolean innerIsDone() {
 244             return ranOrCancelled(getState()) && runner == null;
 245         }
 246 
 247         V innerGet() throws InterruptedException, ExecutionException {
 248             acquireSharedInterruptibly(0);
 249             if (getState() == CANCELLED)
 250                 throw new CancellationException();
 251             if (exception != null)
 252                 throw new ExecutionException(exception);
 253             return result;
 254         }
 255 
 256         V innerGet(long nanosTimeout) throws InterruptedException, ExecutionException, TimeoutException {
 257             if (!tryAcquireSharedNanos(0, nanosTimeout))
 258                 throw new TimeoutException();
 259             if (getState() == CANCELLED)
 260                 throw new CancellationException();
 261             if (exception != null)
 262                 throw new ExecutionException(exception);
 263             return result;
 264         }
 265 
 266         void innerSet(V v) {
 267             for (;;) {
 268                 int s = getState();
 269                 if (s == RAN)
 270                     return;
 271                 if (s == CANCELLED) {
 272                     // aggressively release to set runner to null,
 273                     // in case we are racing with a cancel request
 274                     // that will try to interrupt runner
 275                     releaseShared(0);
 276                     return;
 277                 }
 278                 if (compareAndSetState(s, RAN)) {
 279                     result = v;
 280                     releaseShared(0);
 281                     done();
 282                     return;
 283                 }
 284             }
 285         }
 286 
 287         void innerSetException(Throwable t) {
 288             for (;;) {
 289                 int s = getState();
 290                 if (s == RAN)
 291                     return;
 292                 if (s == CANCELLED) {
 293                     // aggressively release to set runner to null,
 294                     // in case we are racing with a cancel request
 295                     // that will try to interrupt runner
 296                     releaseShared(0);
 297                     return;
 298                 }
 299                 if (compareAndSetState(s, RAN)) {
 300                     exception = t;
 301                     releaseShared(0);
 302                     done();
 303                     return;
 304                 }
 305             }
 306         }
 307 
 308         boolean innerCancel(boolean mayInterruptIfRunning) {
 309             for (;;) {
 310                 int s = getState();
 311                 if (ranOrCancelled(s))
 312                     return false;
 313                 if (compareAndSetState(s, CANCELLED))
 314                     break;
 315             }
 316             if (mayInterruptIfRunning) {
 317                 Thread r = runner;
 318                 if (r != null)
 319                     r.interrupt();
 320             }
 321             releaseShared(0);
 322             done();
 323             return true;
 324         }
 325 
 326         void innerRun() {
 327             if (!compareAndSetState(READY, RUNNING))
 328                 return;
 329 
 330             runner = Thread.currentThread();
 331             if (getState() == RUNNING) { // recheck after setting thread
 332                 V result;
 333                 try {
 334                     result = callable.call();
 335                 } catch (Throwable ex) {
 336                     setException(ex);
 337                     return;
 338                 }
 339                 set(result);
 340             } else {
 341                 releaseShared(0); // cancel
 342             }
 343         }
 344 
 345         boolean innerRunAndReset() {
 346             if (!compareAndSetState(READY, RUNNING))
 347                 return false;
 348             try {
 349                 runner = Thread.currentThread();
 350                 if (getState() == RUNNING)
 351                     callable.call(); // don't set result
 352                 runner = null;
 353                 return compareAndSetState(RUNNING, READY);
 354             } catch (Throwable ex) {
 355                 setException(ex);
 356                 return false;
 357             }
 358         }
 359     }
 360 }