jdk/src/share/classes/java/util/concurrent/FutureTask.java
changeset 2 90ce3da70b43
child 5506 202f599c92aa
equal deleted inserted replaced
0:fd16c54261b3 2:90ce3da70b43
       
     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.  Sun designates this
       
     7  * particular file as subject to the "Classpath" exception as provided
       
     8  * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
       
    21  * CA 95054 USA or visit www.sun.com if you need additional information or
       
    22  * have any 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 }