mirror of git://gcc.gnu.org/git/gcc.git
				
				
				
			
		
			
				
	
	
		
			326 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			Java
		
	
	
	
			
		
		
	
	
			326 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			Java
		
	
	
	
/*
 | 
						|
 * Written by Doug Lea with assistance from members of JCP JSR-166
 | 
						|
 * Expert Group and released to the public domain, as explained at
 | 
						|
 * http://creativecommons.org/licenses/publicdomain
 | 
						|
 */
 | 
						|
 | 
						|
package java.util.concurrent;
 | 
						|
import java.util.concurrent.locks.*;
 | 
						|
 | 
						|
/**
 | 
						|
 * A cancellable asynchronous computation.  This class provides a base
 | 
						|
 * implementation of {@link Future}, with methods to start and cancel
 | 
						|
 * a computation, query to see if the computation is complete, and
 | 
						|
 * retrieve the result of the computation.  The result can only be
 | 
						|
 * retrieved when the computation has completed; the <tt>get</tt>
 | 
						|
 * method will block if the computation has not yet completed.  Once
 | 
						|
 * the computation has completed, the computation cannot be restarted
 | 
						|
 * or cancelled.
 | 
						|
 *
 | 
						|
 * <p>A <tt>FutureTask</tt> can be used to wrap a {@link Callable} or
 | 
						|
 * {@link java.lang.Runnable} object.  Because <tt>FutureTask</tt>
 | 
						|
 * implements <tt>Runnable</tt>, a <tt>FutureTask</tt> can be
 | 
						|
 * submitted to an {@link Executor} for execution.
 | 
						|
 *
 | 
						|
 * <p>In addition to serving as a standalone class, this class provides
 | 
						|
 * <tt>protected</tt> functionality that may be useful when creating
 | 
						|
 * customized task classes.
 | 
						|
 *
 | 
						|
 * @since 1.5
 | 
						|
 * @author Doug Lea
 | 
						|
 * @param <V> The result type returned by this FutureTask's <tt>get</tt> method
 | 
						|
 */
 | 
						|
public class FutureTask<V> implements RunnableFuture<V> {
 | 
						|
    /** Synchronization control for FutureTask */
 | 
						|
    private final Sync sync;
 | 
						|
 | 
						|
    /**
 | 
						|
     * Creates a <tt>FutureTask</tt> that will upon running, execute the
 | 
						|
     * given <tt>Callable</tt>.
 | 
						|
     *
 | 
						|
     * @param  callable the callable task
 | 
						|
     * @throws NullPointerException if callable is null
 | 
						|
     */
 | 
						|
    public FutureTask(Callable<V> callable) {
 | 
						|
        if (callable == null)
 | 
						|
            throw new NullPointerException();
 | 
						|
        sync = new Sync(callable);
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Creates a <tt>FutureTask</tt> that will upon running, execute the
 | 
						|
     * given <tt>Runnable</tt>, and arrange that <tt>get</tt> will return the
 | 
						|
     * given result on successful completion.
 | 
						|
     *
 | 
						|
     * @param  runnable the runnable task
 | 
						|
     * @param result the result to return on successful completion. If
 | 
						|
     * you don't need a particular result, consider using
 | 
						|
     * constructions of the form:
 | 
						|
     * <tt>Future<?> f = new FutureTask<Object>(runnable, null)</tt>
 | 
						|
     * @throws NullPointerException if runnable is null
 | 
						|
     */
 | 
						|
    public FutureTask(Runnable runnable, V result) {
 | 
						|
        sync = new Sync(Executors.callable(runnable, result));
 | 
						|
    }
 | 
						|
 | 
						|
    public boolean isCancelled() {
 | 
						|
        return sync.innerIsCancelled();
 | 
						|
    }
 | 
						|
 | 
						|
    public boolean isDone() {
 | 
						|
        return sync.innerIsDone();
 | 
						|
    }
 | 
						|
 | 
						|
    public boolean cancel(boolean mayInterruptIfRunning) {
 | 
						|
        return sync.innerCancel(mayInterruptIfRunning);
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * @throws CancellationException {@inheritDoc}
 | 
						|
     */
 | 
						|
    public V get() throws InterruptedException, ExecutionException {
 | 
						|
        return sync.innerGet();
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * @throws CancellationException {@inheritDoc}
 | 
						|
     */
 | 
						|
    public V get(long timeout, TimeUnit unit)
 | 
						|
        throws InterruptedException, ExecutionException, TimeoutException {
 | 
						|
        return sync.innerGet(unit.toNanos(timeout));
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Protected method invoked when this task transitions to state
 | 
						|
     * <tt>isDone</tt> (whether normally or via cancellation). The
 | 
						|
     * default implementation does nothing.  Subclasses may override
 | 
						|
     * this method to invoke completion callbacks or perform
 | 
						|
     * bookkeeping. Note that you can query status inside the
 | 
						|
     * implementation of this method to determine whether this task
 | 
						|
     * has been cancelled.
 | 
						|
     */
 | 
						|
    protected void done() { }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Sets the result of this Future to the given value unless
 | 
						|
     * this future has already been set or has been cancelled.
 | 
						|
     * This method is invoked internally by the <tt>run</tt> method
 | 
						|
     * upon successful completion of the computation.
 | 
						|
     * @param v the value
 | 
						|
     */
 | 
						|
    protected void set(V v) {
 | 
						|
        sync.innerSet(v);
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Causes this future to report an <tt>ExecutionException</tt>
 | 
						|
     * with the given throwable as its cause, unless this Future has
 | 
						|
     * already been set or has been cancelled.
 | 
						|
     * This method is invoked internally by the <tt>run</tt> method
 | 
						|
     * upon failure of the computation.
 | 
						|
     * @param t the cause of failure
 | 
						|
     */
 | 
						|
    protected void setException(Throwable t) {
 | 
						|
        sync.innerSetException(t);
 | 
						|
    }
 | 
						|
 | 
						|
    // The following (duplicated) doc comment can be removed once
 | 
						|
    //
 | 
						|
    // 6270645: Javadoc comments should be inherited from most derived
 | 
						|
    //          superinterface or superclass
 | 
						|
    // is fixed.
 | 
						|
    /**
 | 
						|
     * Sets this Future to the result of its computation
 | 
						|
     * unless it has been cancelled.
 | 
						|
     */
 | 
						|
    public void run() {
 | 
						|
        sync.innerRun();
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Executes the computation without setting its result, and then
 | 
						|
     * resets this Future to initial state, failing to do so if the
 | 
						|
     * computation encounters an exception or is cancelled.  This is
 | 
						|
     * designed for use with tasks that intrinsically execute more
 | 
						|
     * than once.
 | 
						|
     * @return true if successfully run and reset
 | 
						|
     */
 | 
						|
    protected boolean runAndReset() {
 | 
						|
        return sync.innerRunAndReset();
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Synchronization control for FutureTask. Note that this must be
 | 
						|
     * a non-static inner class in order to invoke the protected
 | 
						|
     * <tt>done</tt> method. For clarity, all inner class support
 | 
						|
     * methods are same as outer, prefixed with "inner".
 | 
						|
     *
 | 
						|
     * Uses AQS sync state to represent run status
 | 
						|
     */
 | 
						|
    private final class Sync extends AbstractQueuedSynchronizer {
 | 
						|
        private static final long serialVersionUID = -7828117401763700385L;
 | 
						|
 | 
						|
        /** State value representing that task is running */
 | 
						|
        private static final int RUNNING   = 1;
 | 
						|
        /** State value representing that task ran */
 | 
						|
        private static final int RAN       = 2;
 | 
						|
        /** State value representing that task was cancelled */
 | 
						|
        private static final int CANCELLED = 4;
 | 
						|
 | 
						|
        /** The underlying callable */
 | 
						|
        private final Callable<V> callable;
 | 
						|
        /** The result to return from get() */
 | 
						|
        private V result;
 | 
						|
        /** The exception to throw from get() */
 | 
						|
        private Throwable exception;
 | 
						|
 | 
						|
        /**
 | 
						|
         * The thread running task. When nulled after set/cancel, this
 | 
						|
         * indicates that the results are accessible.  Must be
 | 
						|
         * volatile, to ensure visibility upon completion.
 | 
						|
         */
 | 
						|
        private volatile Thread runner;
 | 
						|
 | 
						|
        Sync(Callable<V> callable) {
 | 
						|
            this.callable = callable;
 | 
						|
        }
 | 
						|
 | 
						|
        private boolean ranOrCancelled(int state) {
 | 
						|
            return (state & (RAN | CANCELLED)) != 0;
 | 
						|
        }
 | 
						|
 | 
						|
        /**
 | 
						|
         * Implements AQS base acquire to succeed if ran or cancelled
 | 
						|
         */
 | 
						|
        protected int tryAcquireShared(int ignore) {
 | 
						|
            return innerIsDone()? 1 : -1;
 | 
						|
        }
 | 
						|
 | 
						|
        /**
 | 
						|
         * Implements AQS base release to always signal after setting
 | 
						|
         * final done status by nulling runner thread.
 | 
						|
         */
 | 
						|
        protected boolean tryReleaseShared(int ignore) {
 | 
						|
            runner = null;
 | 
						|
            return true;
 | 
						|
        }
 | 
						|
 | 
						|
        boolean innerIsCancelled() {
 | 
						|
            return getState() == CANCELLED;
 | 
						|
        }
 | 
						|
 | 
						|
        boolean innerIsDone() {
 | 
						|
            return ranOrCancelled(getState()) && runner == null;
 | 
						|
        }
 | 
						|
 | 
						|
        V innerGet() throws InterruptedException, ExecutionException {
 | 
						|
            acquireSharedInterruptibly(0);
 | 
						|
            if (getState() == CANCELLED)
 | 
						|
                throw new CancellationException();
 | 
						|
            if (exception != null)
 | 
						|
                throw new ExecutionException(exception);
 | 
						|
            return result;
 | 
						|
        }
 | 
						|
 | 
						|
        V innerGet(long nanosTimeout) throws InterruptedException, ExecutionException, TimeoutException {
 | 
						|
            if (!tryAcquireSharedNanos(0, nanosTimeout))
 | 
						|
                throw new TimeoutException();
 | 
						|
            if (getState() == CANCELLED)
 | 
						|
                throw new CancellationException();
 | 
						|
            if (exception != null)
 | 
						|
                throw new ExecutionException(exception);
 | 
						|
            return result;
 | 
						|
        }
 | 
						|
 | 
						|
        void innerSet(V v) {
 | 
						|
            for (;;) {
 | 
						|
                int s = getState();
 | 
						|
                if (s == RAN)
 | 
						|
                    return;
 | 
						|
                if (s == CANCELLED) {
 | 
						|
                    // aggressively release to set runner to null,
 | 
						|
                    // in case we are racing with a cancel request
 | 
						|
                    // that will try to interrupt runner
 | 
						|
                    releaseShared(0);
 | 
						|
                    return;
 | 
						|
                }
 | 
						|
                if (compareAndSetState(s, RAN)) {
 | 
						|
                    result = v;
 | 
						|
                    releaseShared(0);
 | 
						|
                    done();
 | 
						|
                    return;
 | 
						|
                }
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        void innerSetException(Throwable t) {
 | 
						|
            for (;;) {
 | 
						|
                int s = getState();
 | 
						|
                if (s == RAN)
 | 
						|
                    return;
 | 
						|
                if (s == CANCELLED) {
 | 
						|
                    // aggressively release to set runner to null,
 | 
						|
                    // in case we are racing with a cancel request
 | 
						|
                    // that will try to interrupt runner
 | 
						|
                    releaseShared(0);
 | 
						|
                    return;
 | 
						|
                }
 | 
						|
                if (compareAndSetState(s, RAN)) {
 | 
						|
                    exception = t;
 | 
						|
                    result = null;
 | 
						|
                    releaseShared(0);
 | 
						|
                    done();
 | 
						|
                    return;
 | 
						|
                }
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        boolean innerCancel(boolean mayInterruptIfRunning) {
 | 
						|
            for (;;) {
 | 
						|
                int s = getState();
 | 
						|
                if (ranOrCancelled(s))
 | 
						|
                    return false;
 | 
						|
                if (compareAndSetState(s, CANCELLED))
 | 
						|
                    break;
 | 
						|
            }
 | 
						|
            if (mayInterruptIfRunning) {
 | 
						|
                Thread r = runner;
 | 
						|
                if (r != null)
 | 
						|
                    r.interrupt();
 | 
						|
            }
 | 
						|
            releaseShared(0);
 | 
						|
            done();
 | 
						|
            return true;
 | 
						|
        }
 | 
						|
 | 
						|
        void innerRun() {
 | 
						|
            if (!compareAndSetState(0, RUNNING))
 | 
						|
                return;
 | 
						|
            try {
 | 
						|
                runner = Thread.currentThread();
 | 
						|
                if (getState() == RUNNING) // recheck after setting thread
 | 
						|
                    innerSet(callable.call());
 | 
						|
                else
 | 
						|
                    releaseShared(0); // cancel
 | 
						|
            } catch (Throwable ex) {
 | 
						|
                innerSetException(ex);
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        boolean innerRunAndReset() {
 | 
						|
            if (!compareAndSetState(0, RUNNING))
 | 
						|
                return false;
 | 
						|
            try {
 | 
						|
                runner = Thread.currentThread();
 | 
						|
                if (getState() == RUNNING)
 | 
						|
                    callable.call(); // don't set result
 | 
						|
                runner = null;
 | 
						|
                return compareAndSetState(RUNNING, 0);
 | 
						|
            } catch (Throwable ex) {
 | 
						|
                innerSetException(ex);
 | 
						|
                return false;
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
}
 |