001 /* 002 * Copyright (C) 2007 The Guava Authors 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017 package com.google.common.util.concurrent; 018 019 import static com.google.common.base.Preconditions.checkNotNull; 020 021 import java.util.concurrent.CancellationException; 022 import java.util.concurrent.ExecutionException; 023 import java.util.concurrent.Executor; 024 import java.util.concurrent.TimeUnit; 025 import java.util.concurrent.TimeoutException; 026 import java.util.concurrent.locks.AbstractQueuedSynchronizer; 027 028 import javax.annotation.Nullable; 029 030 /** 031 * An abstract implementation of the {@link ListenableFuture} interface. This 032 * class is preferable to {@link java.util.concurrent.FutureTask} for two 033 * reasons: It implements {@code ListenableFuture}, and it does not implement 034 * {@code Runnable}. (If you want a {@code Runnable} implementation of {@code 035 * ListenableFuture}, create a {@link ListenableFutureTask}, or submit your 036 * tasks to a {@link ListeningExecutorService}.) 037 * 038 * <p>This class implements all methods in {@code ListenableFuture}. 039 * Subclasses should provide a way to set the result of the computation through 040 * the protected methods {@link #set(Object)} and 041 * {@link #setException(Throwable)}. Subclasses may also override {@link 042 * #interruptTask()}, which will be invoked automatically if a call to {@link 043 * #cancel(boolean) cancel(true)} succeeds in canceling the future. 044 * 045 * <p>{@code AbstractFuture} uses an {@link AbstractQueuedSynchronizer} to deal 046 * with concurrency issues and guarantee thread safety. 047 * 048 * <p>The state changing methods all return a boolean indicating success or 049 * failure in changing the future's state. Valid states are running, 050 * completed, failed, or cancelled. 051 * 052 * <p>This class uses an {@link ExecutionList} to guarantee that all registered 053 * listeners will be executed, either when the future finishes or, for listeners 054 * that are added after the future completes, immediately. 055 * {@code Runnable}-{@code Executor} pairs are stored in the execution list but 056 * are not necessarily executed in the order in which they were added. (If a 057 * listener is added after the Future is complete, it will be executed 058 * immediately, even if earlier listeners have not been executed. Additionally, 059 * executors need not guarantee FIFO execution, or different listeners may run 060 * in different executors.) 061 * 062 * @author Sven Mawson 063 * @since 1.0 064 */ 065 public abstract class AbstractFuture<V> implements ListenableFuture<V> { 066 067 /** Synchronization control for AbstractFutures. */ 068 private final Sync<V> sync = new Sync<V>(); 069 070 // The execution list to hold our executors. 071 private final ExecutionList executionList = new ExecutionList(); 072 073 /* 074 * Improve the documentation of when InterruptedException is thrown. Our 075 * behavior matches the JDK's, but the JDK's documentation is misleading. 076 */ 077 /** 078 * {@inheritDoc} 079 * 080 * <p>The default {@link AbstractFuture} implementation throws {@code 081 * InterruptedException} if the current thread is interrupted before or during 082 * the call, even if the value is already available. 083 * 084 * @throws InterruptedException if the current thread was interrupted before 085 * or during the call (optional but recommended). 086 * @throws CancellationException {@inheritDoc} 087 */ 088 @Override 089 public V get(long timeout, TimeUnit unit) throws InterruptedException, 090 TimeoutException, ExecutionException { 091 return sync.get(unit.toNanos(timeout)); 092 } 093 094 /* 095 * Improve the documentation of when InterruptedException is thrown. Our 096 * behavior matches the JDK's, but the JDK's documentation is misleading. 097 */ 098 /** 099 * {@inheritDoc} 100 * 101 * <p>The default {@link AbstractFuture} implementation throws {@code 102 * InterruptedException} if the current thread is interrupted before or during 103 * the call, even if the value is already available. 104 * 105 * @throws InterruptedException if the current thread was interrupted before 106 * or during the call (optional but recommended). 107 * @throws CancellationException {@inheritDoc} 108 */ 109 @Override 110 public V get() throws InterruptedException, ExecutionException { 111 return sync.get(); 112 } 113 114 @Override 115 public boolean isDone() { 116 return sync.isDone(); 117 } 118 119 @Override 120 public boolean isCancelled() { 121 return sync.isCancelled(); 122 } 123 124 @Override 125 public boolean cancel(boolean mayInterruptIfRunning) { 126 if (!sync.cancel()) { 127 return false; 128 } 129 executionList.execute(); 130 if (mayInterruptIfRunning) { 131 interruptTask(); 132 } 133 return true; 134 } 135 136 /** 137 * Subclasses can override this method to implement interruption of the 138 * future's computation. The method is invoked automatically by a successful 139 * call to {@link #cancel(boolean) cancel(true)}. 140 * 141 * <p>The default implementation does nothing. 142 * 143 * @since 10.0 144 */ 145 protected void interruptTask() { 146 } 147 148 /** 149 * {@inheritDoc} 150 * 151 * @since 10.0 152 */ 153 @Override 154 public void addListener(Runnable listener, Executor exec) { 155 executionList.add(listener, exec); 156 } 157 158 /** 159 * Subclasses should invoke this method to set the result of the computation 160 * to {@code value}. This will set the state of the future to 161 * {@link AbstractFuture.Sync#COMPLETED} and invoke the listeners if the 162 * state was successfully changed. 163 * 164 * @param value the value that was the result of the task. 165 * @return true if the state was successfully changed. 166 */ 167 protected boolean set(@Nullable V value) { 168 boolean result = sync.set(value); 169 if (result) { 170 executionList.execute(); 171 } 172 return result; 173 } 174 175 /** 176 * Subclasses should invoke this method to set the result of the computation 177 * to an error, {@code throwable}. This will set the state of the future to 178 * {@link AbstractFuture.Sync#COMPLETED} and invoke the listeners if the 179 * state was successfully changed. 180 * 181 * @param throwable the exception that the task failed with. 182 * @return true if the state was successfully changed. 183 * @throws Error if the throwable was an {@link Error}. 184 */ 185 protected boolean setException(Throwable throwable) { 186 boolean result = sync.setException(checkNotNull(throwable)); 187 if (result) { 188 executionList.execute(); 189 } 190 191 // If it's an Error, we want to make sure it reaches the top of the 192 // call stack, so we rethrow it. 193 if (throwable instanceof Error) { 194 throw (Error) throwable; 195 } 196 return result; 197 } 198 199 /** 200 * <p>Following the contract of {@link AbstractQueuedSynchronizer} we create a 201 * private subclass to hold the synchronizer. This synchronizer is used to 202 * implement the blocking and waiting calls as well as to handle state changes 203 * in a thread-safe manner. The current state of the future is held in the 204 * Sync state, and the lock is released whenever the state changes to either 205 * {@link #COMPLETED} or {@link #CANCELLED}. 206 * 207 * <p>To avoid races between threads doing release and acquire, we transition 208 * to the final state in two steps. One thread will successfully CAS from 209 * RUNNING to COMPLETING, that thread will then set the result of the 210 * computation, and only then transition to COMPLETED or CANCELLED. 211 * 212 * <p>We don't use the integer argument passed between acquire methods so we 213 * pass around a -1 everywhere. 214 */ 215 static final class Sync<V> extends AbstractQueuedSynchronizer { 216 217 private static final long serialVersionUID = 0L; 218 219 /* Valid states. */ 220 static final int RUNNING = 0; 221 static final int COMPLETING = 1; 222 static final int COMPLETED = 2; 223 static final int CANCELLED = 4; 224 225 private V value; 226 private Throwable exception; 227 228 /* 229 * Acquisition succeeds if the future is done, otherwise it fails. 230 */ 231 @Override 232 protected int tryAcquireShared(int ignored) { 233 if (isDone()) { 234 return 1; 235 } 236 return -1; 237 } 238 239 /* 240 * We always allow a release to go through, this means the state has been 241 * successfully changed and the result is available. 242 */ 243 @Override 244 protected boolean tryReleaseShared(int finalState) { 245 setState(finalState); 246 return true; 247 } 248 249 /** 250 * Blocks until the task is complete or the timeout expires. Throws a 251 * {@link TimeoutException} if the timer expires, otherwise behaves like 252 * {@link #get()}. 253 */ 254 V get(long nanos) throws TimeoutException, CancellationException, 255 ExecutionException, InterruptedException { 256 257 // Attempt to acquire the shared lock with a timeout. 258 if (!tryAcquireSharedNanos(-1, nanos)) { 259 throw new TimeoutException("Timeout waiting for task."); 260 } 261 262 return getValue(); 263 } 264 265 /** 266 * Blocks until {@link #complete(Object, Throwable, int)} has been 267 * successfully called. Throws a {@link CancellationException} if the task 268 * was cancelled, or a {@link ExecutionException} if the task completed with 269 * an error. 270 */ 271 V get() throws CancellationException, ExecutionException, 272 InterruptedException { 273 274 // Acquire the shared lock allowing interruption. 275 acquireSharedInterruptibly(-1); 276 return getValue(); 277 } 278 279 /** 280 * Implementation of the actual value retrieval. Will return the value 281 * on success, an exception on failure, a cancellation on cancellation, or 282 * an illegal state if the synchronizer is in an invalid state. 283 */ 284 private V getValue() throws CancellationException, ExecutionException { 285 int state = getState(); 286 switch (state) { 287 case COMPLETED: 288 if (exception != null) { 289 throw new ExecutionException(exception); 290 } else { 291 return value; 292 } 293 294 case CANCELLED: 295 throw new CancellationException("Task was cancelled."); 296 297 default: 298 throw new IllegalStateException( 299 "Error, synchronizer in invalid state: " + state); 300 } 301 } 302 303 /** 304 * Checks if the state is {@link #COMPLETED} or {@link #CANCELLED}. 305 */ 306 boolean isDone() { 307 return (getState() & (COMPLETED | CANCELLED)) != 0; 308 } 309 310 /** 311 * Checks if the state is {@link #CANCELLED}. 312 */ 313 boolean isCancelled() { 314 return getState() == CANCELLED; 315 } 316 317 /** 318 * Transition to the COMPLETED state and set the value. 319 */ 320 boolean set(@Nullable V v) { 321 return complete(v, null, COMPLETED); 322 } 323 324 /** 325 * Transition to the COMPLETED state and set the exception. 326 */ 327 boolean setException(Throwable t) { 328 return complete(null, t, COMPLETED); 329 } 330 331 /** 332 * Transition to the CANCELLED state. 333 */ 334 boolean cancel() { 335 return complete(null, null, CANCELLED); 336 } 337 338 /** 339 * Implementation of completing a task. Either {@code v} or {@code t} will 340 * be set but not both. The {@code finalState} is the state to change to 341 * from {@link #RUNNING}. If the state is not in the RUNNING state we 342 * return {@code false} after waiting for the state to be set to a valid 343 * final state ({@link #COMPLETED} or {@link #CANCELLED}). 344 * 345 * @param v the value to set as the result of the computation. 346 * @param t the exception to set as the result of the computation. 347 * @param finalState the state to transition to. 348 */ 349 private boolean complete(@Nullable V v, @Nullable Throwable t, 350 int finalState) { 351 boolean doCompletion = compareAndSetState(RUNNING, COMPLETING); 352 if (doCompletion) { 353 // If this thread successfully transitioned to COMPLETING, set the value 354 // and exception and then release to the final state. 355 this.value = v; 356 this.exception = t; 357 releaseShared(finalState); 358 } else if (getState() == COMPLETING) { 359 // If some other thread is currently completing the future, block until 360 // they are done so we can guarantee completion. 361 acquireShared(-1); 362 } 363 return doCompletion; 364 } 365 } 366 }