1bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor/* 21d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Copyright (C) 2007 The Guava Authors 3bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * 4bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * Licensed under the Apache License, Version 2.0 (the "License"); 5bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * you may not use this file except in compliance with the License. 6bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * You may obtain a copy of the License at 7bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * 8bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * http://www.apache.org/licenses/LICENSE-2.0 9bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * 10bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * Unless required by applicable law or agreed to in writing, software 11bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * distributed under the License is distributed on an "AS IS" BASIS, 12bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * See the License for the specific language governing permissions and 14bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * limitations under the License. 15bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor */ 16bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor 17bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnorpackage com.google.common.util.concurrent; 18bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor 191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport static com.google.common.base.Preconditions.checkNotNull; 201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 21bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnorimport java.util.concurrent.CancellationException; 22bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnorimport java.util.concurrent.ExecutionException; 231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.concurrent.Executor; 24bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnorimport java.util.concurrent.TimeUnit; 25bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnorimport java.util.concurrent.TimeoutException; 26bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnorimport java.util.concurrent.locks.AbstractQueuedSynchronizer; 27bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor 281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport javax.annotation.Nullable; 291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 30bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor/** 311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * An abstract implementation of the {@link ListenableFuture} interface. This 321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * class is preferable to {@link java.util.concurrent.FutureTask} for two 331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * reasons: It implements {@code ListenableFuture}, and it does not implement 341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * {@code Runnable}. (If you want a {@code Runnable} implementation of {@code 351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * ListenableFuture}, create a {@link ListenableFutureTask}, or submit your 361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * tasks to a {@link ListeningExecutorService}.) 371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * <p>This class implements all methods in {@code ListenableFuture}. 391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Subclasses should provide a way to set the result of the computation through 401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * the protected methods {@link #set(Object)} and 411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * {@link #setException(Throwable)}. Subclasses may also override {@link 421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * #interruptTask()}, which will be invoked automatically if a call to {@link 431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * #cancel(boolean) cancel(true)} succeeds in canceling the future. 44bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * 451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * <p>{@code AbstractFuture} uses an {@link AbstractQueuedSynchronizer} to deal 461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * with concurrency issues and guarantee thread safety. 47bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * 48bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * <p>The state changing methods all return a boolean indicating success or 49bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * failure in changing the future's state. Valid states are running, 501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * completed, failed, or cancelled. 511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * <p>This class uses an {@link ExecutionList} to guarantee that all registered 531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * listeners will be executed, either when the future finishes or, for listeners 541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * that are added after the future completes, immediately. 551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * {@code Runnable}-{@code Executor} pairs are stored in the execution list but 561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * are not necessarily executed in the order in which they were added. (If a 571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * listener is added after the Future is complete, it will be executed 581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * immediately, even if earlier listeners have not been executed. Additionally, 591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * executors need not guarantee FIFO execution, or different listeners may run 601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * in different executors.) 61bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * 62bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * @author Sven Mawson 631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * @since 1.0 64bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor */ 651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertpublic abstract class AbstractFuture<V> implements ListenableFuture<V> { 66bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor 67bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor /** Synchronization control for AbstractFutures. */ 68bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor private final Sync<V> sync = new Sync<V>(); 69bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor 701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert // The execution list to hold our executors. 711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert private final ExecutionList executionList = new ExecutionList(); 721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 73bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor /* 741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Improve the documentation of when InterruptedException is thrown. Our 751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * behavior matches the JDK's, but the JDK's documentation is misleading. 761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */ 771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert /** 781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * {@inheritDoc} 791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * <p>The default {@link AbstractFuture} implementation throws {@code 811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * InterruptedException} if the current thread is interrupted before or during 821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * the call, even if the value is already available. 831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * @throws InterruptedException if the current thread was interrupted before 851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * or during the call (optional but recommended). 861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * @throws CancellationException {@inheritDoc} 87bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor */ 881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override 89bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor public V get(long timeout, TimeUnit unit) throws InterruptedException, 90bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor TimeoutException, ExecutionException { 91bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor return sync.get(unit.toNanos(timeout)); 92bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor } 93bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor 94bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor /* 951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Improve the documentation of when InterruptedException is thrown. Our 961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * behavior matches the JDK's, but the JDK's documentation is misleading. 971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */ 981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert /** 991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * {@inheritDoc} 1001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 1011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * <p>The default {@link AbstractFuture} implementation throws {@code 1021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * InterruptedException} if the current thread is interrupted before or during 1031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * the call, even if the value is already available. 1041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 1051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * @throws InterruptedException if the current thread was interrupted before 1061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * or during the call (optional but recommended). 1071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * @throws CancellationException {@inheritDoc} 108bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor */ 1091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override 110bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor public V get() throws InterruptedException, ExecutionException { 111bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor return sync.get(); 112bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor } 113bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor 1141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override 115bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor public boolean isDone() { 116bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor return sync.isDone(); 117bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor } 118bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor 1191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override 120bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor public boolean isCancelled() { 121bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor return sync.isCancelled(); 122bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor } 123bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor 1241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override 125bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor public boolean cancel(boolean mayInterruptIfRunning) { 1261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert if (!sync.cancel()) { 1271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return false; 1281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert executionList.execute(); 1301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert if (mayInterruptIfRunning) { 1311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert interruptTask(); 1321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return true; 1341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert /** 1371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Subclasses can override this method to implement interruption of the 1381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * future's computation. The method is invoked automatically by a successful 1391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * call to {@link #cancel(boolean) cancel(true)}. 1401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 1411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * <p>The default implementation does nothing. 1421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 1431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * @since 10.0 1441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */ 1451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert protected void interruptTask() { 1461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert /** 1491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * {@inheritDoc} 1501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 1511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * @since 10.0 1521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */ 1531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override 1541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public void addListener(Runnable listener, Executor exec) { 1551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert executionList.add(listener, exec); 156bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor } 157bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor 158bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor /** 159bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * Subclasses should invoke this method to set the result of the computation 160bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * to {@code value}. This will set the state of the future to 1611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * {@link AbstractFuture.Sync#COMPLETED} and invoke the listeners if the 162bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * state was successfully changed. 163bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * 164bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * @param value the value that was the result of the task. 165bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * @return true if the state was successfully changed. 166bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor */ 1671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert protected boolean set(@Nullable V value) { 168bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor boolean result = sync.set(value); 169bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor if (result) { 1701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert executionList.execute(); 171bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor } 172bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor return result; 173bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor } 174bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor 175bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor /** 176bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * Subclasses should invoke this method to set the result of the computation 177bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * to an error, {@code throwable}. This will set the state of the future to 1781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * {@link AbstractFuture.Sync#COMPLETED} and invoke the listeners if the 179bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * state was successfully changed. 180bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * 181bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * @param throwable the exception that the task failed with. 182bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * @return true if the state was successfully changed. 183bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * @throws Error if the throwable was an {@link Error}. 184bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor */ 185bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor protected boolean setException(Throwable throwable) { 1861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert boolean result = sync.setException(checkNotNull(throwable)); 187bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor if (result) { 1881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert executionList.execute(); 189bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor } 190bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor 191bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor // If it's an Error, we want to make sure it reaches the top of the 192bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor // call stack, so we rethrow it. 193bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor if (throwable instanceof Error) { 194bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor throw (Error) throwable; 195bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor } 196bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor return result; 197bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor } 198bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor 199bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor /** 200bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * <p>Following the contract of {@link AbstractQueuedSynchronizer} we create a 201bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * private subclass to hold the synchronizer. This synchronizer is used to 202bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * implement the blocking and waiting calls as well as to handle state changes 203bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * in a thread-safe manner. The current state of the future is held in the 204bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * Sync state, and the lock is released whenever the state changes to either 205bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * {@link #COMPLETED} or {@link #CANCELLED}. 206bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * 207bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * <p>To avoid races between threads doing release and acquire, we transition 208bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * to the final state in two steps. One thread will successfully CAS from 209bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * RUNNING to COMPLETING, that thread will then set the result of the 210bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * computation, and only then transition to COMPLETED or CANCELLED. 211bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * 212bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * <p>We don't use the integer argument passed between acquire methods so we 213bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * pass around a -1 everywhere. 214bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor */ 215bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor static final class Sync<V> extends AbstractQueuedSynchronizer { 216bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor 217bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor private static final long serialVersionUID = 0L; 218bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor 219bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor /* Valid states. */ 220bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor static final int RUNNING = 0; 221bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor static final int COMPLETING = 1; 222bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor static final int COMPLETED = 2; 223bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor static final int CANCELLED = 4; 224bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor 225bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor private V value; 2261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert private Throwable exception; 227bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor 228bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor /* 229bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * Acquisition succeeds if the future is done, otherwise it fails. 230bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor */ 231bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor @Override 232bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor protected int tryAcquireShared(int ignored) { 233bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor if (isDone()) { 234bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor return 1; 235bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor } 236bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor return -1; 237bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor } 238bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor 239bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor /* 240bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * We always allow a release to go through, this means the state has been 241bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * successfully changed and the result is available. 242bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor */ 243bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor @Override 244bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor protected boolean tryReleaseShared(int finalState) { 245bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor setState(finalState); 246bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor return true; 247bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor } 248bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor 249bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor /** 250bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * Blocks until the task is complete or the timeout expires. Throws a 251bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * {@link TimeoutException} if the timer expires, otherwise behaves like 252bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * {@link #get()}. 253bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor */ 254bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor V get(long nanos) throws TimeoutException, CancellationException, 255bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor ExecutionException, InterruptedException { 256bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor 257bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor // Attempt to acquire the shared lock with a timeout. 258bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor if (!tryAcquireSharedNanos(-1, nanos)) { 259bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor throw new TimeoutException("Timeout waiting for task."); 260bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor } 261bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor 262bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor return getValue(); 263bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor } 264bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor 265bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor /** 266bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * Blocks until {@link #complete(Object, Throwable, int)} has been 267bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * successfully called. Throws a {@link CancellationException} if the task 268bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * was cancelled, or a {@link ExecutionException} if the task completed with 269bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * an error. 270bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor */ 271bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor V get() throws CancellationException, ExecutionException, 272bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor InterruptedException { 273bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor 274bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor // Acquire the shared lock allowing interruption. 275bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor acquireSharedInterruptibly(-1); 276bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor return getValue(); 277bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor } 278bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor 279bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor /** 280bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * Implementation of the actual value retrieval. Will return the value 281bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * on success, an exception on failure, a cancellation on cancellation, or 282bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * an illegal state if the synchronizer is in an invalid state. 283bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor */ 284bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor private V getValue() throws CancellationException, ExecutionException { 285bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor int state = getState(); 286bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor switch (state) { 287bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor case COMPLETED: 288bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor if (exception != null) { 2891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert throw new ExecutionException(exception); 290bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor } else { 291bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor return value; 292bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor } 293bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor 294bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor case CANCELLED: 295bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor throw new CancellationException("Task was cancelled."); 296bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor 297bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor default: 298bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor throw new IllegalStateException( 299bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor "Error, synchronizer in invalid state: " + state); 300bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor } 301bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor } 302bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor 303bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor /** 304bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * Checks if the state is {@link #COMPLETED} or {@link #CANCELLED}. 305bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor */ 306bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor boolean isDone() { 307bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor return (getState() & (COMPLETED | CANCELLED)) != 0; 308bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor } 309bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor 310bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor /** 311bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * Checks if the state is {@link #CANCELLED}. 312bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor */ 313bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor boolean isCancelled() { 314bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor return getState() == CANCELLED; 315bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor } 316bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor 317bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor /** 318bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * Transition to the COMPLETED state and set the value. 319bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor */ 3201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert boolean set(@Nullable V v) { 321bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor return complete(v, null, COMPLETED); 322bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor } 323bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor 324bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor /** 325bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * Transition to the COMPLETED state and set the exception. 326bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor */ 327bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor boolean setException(Throwable t) { 328bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor return complete(null, t, COMPLETED); 329bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor } 330bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor 331bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor /** 332bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * Transition to the CANCELLED state. 333bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor */ 334bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor boolean cancel() { 335bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor return complete(null, null, CANCELLED); 336bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor } 337bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor 338bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor /** 339bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * Implementation of completing a task. Either {@code v} or {@code t} will 340bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * be set but not both. The {@code finalState} is the state to change to 341bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * from {@link #RUNNING}. If the state is not in the RUNNING state we 3421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * return {@code false} after waiting for the state to be set to a valid 3431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * final state ({@link #COMPLETED} or {@link #CANCELLED}). 344bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * 345bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * @param v the value to set as the result of the computation. 346bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * @param t the exception to set as the result of the computation. 347bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * @param finalState the state to transition to. 348bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor */ 3491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert private boolean complete(@Nullable V v, @Nullable Throwable t, 3501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert int finalState) { 3511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert boolean doCompletion = compareAndSetState(RUNNING, COMPLETING); 3521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert if (doCompletion) { 3531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert // If this thread successfully transitioned to COMPLETING, set the value 3541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert // and exception and then release to the final state. 355bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor this.value = v; 3561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert this.exception = t; 357bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor releaseShared(finalState); 3581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } else if (getState() == COMPLETING) { 3591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert // If some other thread is currently completing the future, block until 3601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert // they are done so we can guarantee completion. 3611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert acquireShared(-1); 362bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor } 3631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return doCompletion; 364bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor } 365bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor } 366bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor} 367