/* * Copyright (C) 2007 The Guava Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.common.util.concurrent; import static com.google.common.base.Preconditions.checkNotNull; import java.util.concurrent.CancellationException; import java.util.concurrent.ExecutionException; import java.util.concurrent.Executor; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; import java.util.concurrent.locks.AbstractQueuedSynchronizer; import javax.annotation.Nullable; /** * An abstract implementation of the {@link ListenableFuture} interface. This * class is preferable to {@link java.util.concurrent.FutureTask} for two * reasons: It implements {@code ListenableFuture}, and it does not implement * {@code Runnable}. (If you want a {@code Runnable} implementation of {@code * ListenableFuture}, create a {@link ListenableFutureTask}, or submit your * tasks to a {@link ListeningExecutorService}.) * *
This class implements all methods in {@code ListenableFuture}. * Subclasses should provide a way to set the result of the computation through * the protected methods {@link #set(Object)} and * {@link #setException(Throwable)}. Subclasses may also override {@link * #interruptTask()}, which will be invoked automatically if a call to {@link * #cancel(boolean) cancel(true)} succeeds in canceling the future. * *
{@code AbstractFuture} uses an {@link AbstractQueuedSynchronizer} to deal * with concurrency issues and guarantee thread safety. * *
The state changing methods all return a boolean indicating success or * failure in changing the future's state. Valid states are running, * completed, failed, or cancelled. * *
This class uses an {@link ExecutionList} to guarantee that all registered
* listeners will be executed, either when the future finishes or, for listeners
* that are added after the future completes, immediately.
* {@code Runnable}-{@code Executor} pairs are stored in the execution list but
* are not necessarily executed in the order in which they were added. (If a
* listener is added after the Future is complete, it will be executed
* immediately, even if earlier listeners have not been executed. Additionally,
* executors need not guarantee FIFO execution, or different listeners may run
* in different executors.)
*
* @author Sven Mawson
* @since 1.0
*/
public abstract class AbstractFuture The default {@link AbstractFuture} implementation throws {@code
* InterruptedException} if the current thread is interrupted before or during
* the call, even if the value is already available.
*
* @throws InterruptedException if the current thread was interrupted before
* or during the call (optional but recommended).
* @throws CancellationException {@inheritDoc}
*/
@Override
public V get(long timeout, TimeUnit unit) throws InterruptedException,
TimeoutException, ExecutionException {
return sync.get(unit.toNanos(timeout));
}
/*
* Improve the documentation of when InterruptedException is thrown. Our
* behavior matches the JDK's, but the JDK's documentation is misleading.
*/
/**
* {@inheritDoc}
*
* The default {@link AbstractFuture} implementation throws {@code
* InterruptedException} if the current thread is interrupted before or during
* the call, even if the value is already available.
*
* @throws InterruptedException if the current thread was interrupted before
* or during the call (optional but recommended).
* @throws CancellationException {@inheritDoc}
*/
@Override
public V get() throws InterruptedException, ExecutionException {
return sync.get();
}
@Override
public boolean isDone() {
return sync.isDone();
}
@Override
public boolean isCancelled() {
return sync.isCancelled();
}
@Override
public boolean cancel(boolean mayInterruptIfRunning) {
if (!sync.cancel()) {
return false;
}
executionList.execute();
if (mayInterruptIfRunning) {
interruptTask();
}
return true;
}
/**
* Subclasses can override this method to implement interruption of the
* future's computation. The method is invoked automatically by a successful
* call to {@link #cancel(boolean) cancel(true)}.
*
* The default implementation does nothing.
*
* @since 10.0
*/
protected void interruptTask() {
}
/**
* {@inheritDoc}
*
* @since 10.0
*/
@Override
public void addListener(Runnable listener, Executor exec) {
executionList.add(listener, exec);
}
/**
* Subclasses should invoke this method to set the result of the computation
* to {@code value}. This will set the state of the future to
* {@link AbstractFuture.Sync#COMPLETED} and invoke the listeners if the
* state was successfully changed.
*
* @param value the value that was the result of the task.
* @return true if the state was successfully changed.
*/
protected boolean set(@Nullable V value) {
boolean result = sync.set(value);
if (result) {
executionList.execute();
}
return result;
}
/**
* Subclasses should invoke this method to set the result of the computation
* to an error, {@code throwable}. This will set the state of the future to
* {@link AbstractFuture.Sync#COMPLETED} and invoke the listeners if the
* state was successfully changed.
*
* @param throwable the exception that the task failed with.
* @return true if the state was successfully changed.
* @throws Error if the throwable was an {@link Error}.
*/
protected boolean setException(Throwable throwable) {
boolean result = sync.setException(checkNotNull(throwable));
if (result) {
executionList.execute();
}
// If it's an Error, we want to make sure it reaches the top of the
// call stack, so we rethrow it.
if (throwable instanceof Error) {
throw (Error) throwable;
}
return result;
}
/**
* Following the contract of {@link AbstractQueuedSynchronizer} we create a
* private subclass to hold the synchronizer. This synchronizer is used to
* implement the blocking and waiting calls as well as to handle state changes
* in a thread-safe manner. The current state of the future is held in the
* Sync state, and the lock is released whenever the state changes to either
* {@link #COMPLETED} or {@link #CANCELLED}.
*
* To avoid races between threads doing release and acquire, we transition
* to the final state in two steps. One thread will successfully CAS from
* RUNNING to COMPLETING, that thread will then set the result of the
* computation, and only then transition to COMPLETED or CANCELLED.
*
* We don't use the integer argument passed between acquire methods so we
* pass around a -1 everywhere.
*/
static final class Sync