FutureTask.java revision 3984
0N/A/*
0N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0N/A *
0N/A * This code is free software; you can redistribute it and/or modify it
0N/A * under the terms of the GNU General Public License version 2 only, as
2362N/A * published by the Free Software Foundation. Oracle designates this
0N/A * particular file as subject to the "Classpath" exception as provided
2362N/A * by Oracle in the LICENSE file that accompanied this code.
0N/A *
0N/A * This code is distributed in the hope that it will be useful, but WITHOUT
0N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
0N/A * version 2 for more details (a copy is included in the LICENSE file that
0N/A * accompanied this code).
0N/A *
0N/A * You should have received a copy of the GNU General Public License version
0N/A * 2 along with this work; if not, write to the Free Software Foundation,
0N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0N/A *
2362N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2362N/A * or visit www.oracle.com if you need additional information or have any
2362N/A * questions.
0N/A */
0N/A
0N/A/*
0N/A * This file is available under and governed by the GNU General Public
0N/A * License version 2 only, as published by the Free Software Foundation.
0N/A * However, the following notice accompanied the original version of this
0N/A * file:
0N/A *
0N/A * Written by Doug Lea with assistance from members of JCP JSR-166
0N/A * Expert Group and released to the public domain, as explained at
3984N/A * http://creativecommons.org/publicdomain/zero/1.0/
0N/A */
0N/A
0N/Apackage java.util.concurrent;
0N/Aimport java.util.concurrent.locks.*;
0N/A
0N/A/**
0N/A * A cancellable asynchronous computation. This class provides a base
0N/A * implementation of {@link Future}, with methods to start and cancel
0N/A * a computation, query to see if the computation is complete, and
0N/A * retrieve the result of the computation. The result can only be
0N/A * retrieved when the computation has completed; the <tt>get</tt>
0N/A * method will block if the computation has not yet completed. Once
0N/A * the computation has completed, the computation cannot be restarted
0N/A * or cancelled.
0N/A *
0N/A * <p>A <tt>FutureTask</tt> can be used to wrap a {@link Callable} or
0N/A * {@link java.lang.Runnable} object. Because <tt>FutureTask</tt>
0N/A * implements <tt>Runnable</tt>, a <tt>FutureTask</tt> can be
0N/A * submitted to an {@link Executor} for execution.
0N/A *
0N/A * <p>In addition to serving as a standalone class, this class provides
0N/A * <tt>protected</tt> functionality that may be useful when creating
0N/A * customized task classes.
0N/A *
0N/A * @since 1.5
0N/A * @author Doug Lea
0N/A * @param <V> The result type returned by this FutureTask's <tt>get</tt> method
0N/A */
0N/Apublic class FutureTask<V> implements RunnableFuture<V> {
0N/A /** Synchronization control for FutureTask */
0N/A private final Sync sync;
0N/A
0N/A /**
0N/A * Creates a <tt>FutureTask</tt> that will, upon running, execute the
0N/A * given <tt>Callable</tt>.
0N/A *
0N/A * @param callable the callable task
0N/A * @throws NullPointerException if callable is null
0N/A */
0N/A public FutureTask(Callable<V> callable) {
0N/A if (callable == null)
0N/A throw new NullPointerException();
0N/A sync = new Sync(callable);
0N/A }
0N/A
0N/A /**
0N/A * Creates a <tt>FutureTask</tt> that will, upon running, execute the
0N/A * given <tt>Runnable</tt>, and arrange that <tt>get</tt> will return the
0N/A * given result on successful completion.
0N/A *
0N/A * @param runnable the runnable task
0N/A * @param result the result to return on successful completion. If
0N/A * you don't need a particular result, consider using
0N/A * constructions of the form:
3203N/A * {@code Future<?> f = new FutureTask<Void>(runnable, null)}
0N/A * @throws NullPointerException if runnable is null
0N/A */
0N/A public FutureTask(Runnable runnable, V result) {
0N/A sync = new Sync(Executors.callable(runnable, result));
0N/A }
0N/A
0N/A public boolean isCancelled() {
0N/A return sync.innerIsCancelled();
0N/A }
0N/A
0N/A public boolean isDone() {
0N/A return sync.innerIsDone();
0N/A }
0N/A
0N/A public boolean cancel(boolean mayInterruptIfRunning) {
0N/A return sync.innerCancel(mayInterruptIfRunning);
0N/A }
0N/A
0N/A /**
0N/A * @throws CancellationException {@inheritDoc}
0N/A */
0N/A public V get() throws InterruptedException, ExecutionException {
0N/A return sync.innerGet();
0N/A }
0N/A
0N/A /**
0N/A * @throws CancellationException {@inheritDoc}
0N/A */
0N/A public V get(long timeout, TimeUnit unit)
0N/A throws InterruptedException, ExecutionException, TimeoutException {
0N/A return sync.innerGet(unit.toNanos(timeout));
0N/A }
0N/A
0N/A /**
0N/A * Protected method invoked when this task transitions to state
0N/A * <tt>isDone</tt> (whether normally or via cancellation). The
0N/A * default implementation does nothing. Subclasses may override
0N/A * this method to invoke completion callbacks or perform
0N/A * bookkeeping. Note that you can query status inside the
0N/A * implementation of this method to determine whether this task
0N/A * has been cancelled.
0N/A */
0N/A protected void done() { }
0N/A
0N/A /**
0N/A * Sets the result of this Future to the given value unless
0N/A * this future has already been set or has been cancelled.
0N/A * This method is invoked internally by the <tt>run</tt> method
0N/A * upon successful completion of the computation.
0N/A * @param v the value
0N/A */
0N/A protected void set(V v) {
0N/A sync.innerSet(v);
0N/A }
0N/A
0N/A /**
0N/A * Causes this future to report an <tt>ExecutionException</tt>
0N/A * with the given throwable as its cause, unless this Future has
0N/A * already been set or has been cancelled.
0N/A * This method is invoked internally by the <tt>run</tt> method
0N/A * upon failure of the computation.
0N/A * @param t the cause of failure
0N/A */
0N/A protected void setException(Throwable t) {
0N/A sync.innerSetException(t);
0N/A }
0N/A
0N/A // The following (duplicated) doc comment can be removed once
0N/A //
0N/A // 6270645: Javadoc comments should be inherited from most derived
0N/A // superinterface or superclass
0N/A // is fixed.
0N/A /**
0N/A * Sets this Future to the result of its computation
0N/A * unless it has been cancelled.
0N/A */
0N/A public void run() {
0N/A sync.innerRun();
0N/A }
0N/A
0N/A /**
0N/A * Executes the computation without setting its result, and then
0N/A * resets this Future to initial state, failing to do so if the
0N/A * computation encounters an exception or is cancelled. This is
0N/A * designed for use with tasks that intrinsically execute more
0N/A * than once.
0N/A * @return true if successfully run and reset
0N/A */
0N/A protected boolean runAndReset() {
0N/A return sync.innerRunAndReset();
0N/A }
0N/A
0N/A /**
0N/A * Synchronization control for FutureTask. Note that this must be
0N/A * a non-static inner class in order to invoke the protected
0N/A * <tt>done</tt> method. For clarity, all inner class support
0N/A * methods are same as outer, prefixed with "inner".
0N/A *
0N/A * Uses AQS sync state to represent run status
0N/A */
0N/A private final class Sync extends AbstractQueuedSynchronizer {
0N/A private static final long serialVersionUID = -7828117401763700385L;
0N/A
0N/A /** State value representing that task is ready to run */
0N/A private static final int READY = 0;
0N/A /** State value representing that task is running */
0N/A private static final int RUNNING = 1;
0N/A /** State value representing that task ran */
0N/A private static final int RAN = 2;
0N/A /** State value representing that task was cancelled */
0N/A private static final int CANCELLED = 4;
0N/A
0N/A /** The underlying callable */
0N/A private final Callable<V> callable;
0N/A /** The result to return from get() */
0N/A private V result;
0N/A /** The exception to throw from get() */
0N/A private Throwable exception;
0N/A
0N/A /**
0N/A * The thread running task. When nulled after set/cancel, this
0N/A * indicates that the results are accessible. Must be
0N/A * volatile, to ensure visibility upon completion.
0N/A */
0N/A private volatile Thread runner;
0N/A
0N/A Sync(Callable<V> callable) {
0N/A this.callable = callable;
0N/A }
0N/A
0N/A private boolean ranOrCancelled(int state) {
0N/A return (state & (RAN | CANCELLED)) != 0;
0N/A }
0N/A
0N/A /**
0N/A * Implements AQS base acquire to succeed if ran or cancelled
0N/A */
0N/A protected int tryAcquireShared(int ignore) {
0N/A return innerIsDone() ? 1 : -1;
0N/A }
0N/A
0N/A /**
0N/A * Implements AQS base release to always signal after setting
0N/A * final done status by nulling runner thread.
0N/A */
0N/A protected boolean tryReleaseShared(int ignore) {
0N/A runner = null;
0N/A return true;
0N/A }
0N/A
0N/A boolean innerIsCancelled() {
0N/A return getState() == CANCELLED;
0N/A }
0N/A
0N/A boolean innerIsDone() {
0N/A return ranOrCancelled(getState()) && runner == null;
0N/A }
0N/A
0N/A V innerGet() throws InterruptedException, ExecutionException {
0N/A acquireSharedInterruptibly(0);
0N/A if (getState() == CANCELLED)
0N/A throw new CancellationException();
0N/A if (exception != null)
0N/A throw new ExecutionException(exception);
0N/A return result;
0N/A }
0N/A
0N/A V innerGet(long nanosTimeout) throws InterruptedException, ExecutionException, TimeoutException {
0N/A if (!tryAcquireSharedNanos(0, nanosTimeout))
0N/A throw new TimeoutException();
0N/A if (getState() == CANCELLED)
0N/A throw new CancellationException();
0N/A if (exception != null)
0N/A throw new ExecutionException(exception);
0N/A return result;
0N/A }
0N/A
0N/A void innerSet(V v) {
0N/A for (;;) {
0N/A int s = getState();
0N/A if (s == RAN)
0N/A return;
0N/A if (s == CANCELLED) {
0N/A // aggressively release to set runner to null,
0N/A // in case we are racing with a cancel request
0N/A // that will try to interrupt runner
0N/A releaseShared(0);
0N/A return;
0N/A }
0N/A if (compareAndSetState(s, RAN)) {
0N/A result = v;
0N/A releaseShared(0);
0N/A done();
0N/A return;
0N/A }
0N/A }
0N/A }
0N/A
0N/A void innerSetException(Throwable t) {
0N/A for (;;) {
0N/A int s = getState();
0N/A if (s == RAN)
0N/A return;
0N/A if (s == CANCELLED) {
0N/A // aggressively release to set runner to null,
0N/A // in case we are racing with a cancel request
0N/A // that will try to interrupt runner
0N/A releaseShared(0);
0N/A return;
0N/A }
0N/A if (compareAndSetState(s, RAN)) {
0N/A exception = t;
0N/A releaseShared(0);
0N/A done();
0N/A return;
0N/A }
0N/A }
0N/A }
0N/A
0N/A boolean innerCancel(boolean mayInterruptIfRunning) {
0N/A for (;;) {
0N/A int s = getState();
0N/A if (ranOrCancelled(s))
0N/A return false;
0N/A if (compareAndSetState(s, CANCELLED))
0N/A break;
0N/A }
0N/A if (mayInterruptIfRunning) {
0N/A Thread r = runner;
0N/A if (r != null)
0N/A r.interrupt();
0N/A }
0N/A releaseShared(0);
0N/A done();
0N/A return true;
0N/A }
0N/A
0N/A void innerRun() {
0N/A if (!compareAndSetState(READY, RUNNING))
0N/A return;
0N/A
0N/A runner = Thread.currentThread();
0N/A if (getState() == RUNNING) { // recheck after setting thread
0N/A V result;
0N/A try {
0N/A result = callable.call();
0N/A } catch (Throwable ex) {
0N/A setException(ex);
0N/A return;
0N/A }
0N/A set(result);
0N/A } else {
0N/A releaseShared(0); // cancel
0N/A }
0N/A }
0N/A
0N/A boolean innerRunAndReset() {
0N/A if (!compareAndSetState(READY, RUNNING))
0N/A return false;
0N/A try {
0N/A runner = Thread.currentThread();
0N/A if (getState() == RUNNING)
0N/A callable.call(); // don't set result
0N/A runner = null;
0N/A return compareAndSetState(RUNNING, READY);
0N/A } catch (Throwable ex) {
0N/A setException(ex);
0N/A return false;
0N/A }
0N/A }
0N/A }
0N/A}