All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.fitbur.google.common.util.concurrent.Futures Maven / Gradle / Ivy

There is a newer version: 1.0.0
Show newest version
/*
 * Copyright (C) 2006 The Guava Authors
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in com.fitburpliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.com.fitbur/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.fitbur.google.com.fitburmon.util.concurrent;

import static com.fitbur.google.com.fitburmon.base.Preconditions.checkArgument;
import static com.fitbur.google.com.fitburmon.base.Preconditions.checkNotNull;
import static com.fitbur.google.com.fitburmon.base.Preconditions.checkState;
import static com.fitbur.google.com.fitburmon.util.concurrent.MoreExecutors.directExecutor;
import static com.fitbur.google.com.fitburmon.util.concurrent.Uninterruptibles.getUninterruptibly;
import static java.lang.Thread.currentThread;
import static java.util.Arrays.asList;

import com.fitbur.google.com.fitburmon.annotations.Beta;
import com.fitbur.google.com.fitburmon.base.Function;
import com.fitbur.google.com.fitburmon.base.Optional;
import com.fitbur.google.com.fitburmon.base.Preconditions;
import com.fitbur.google.com.fitburmon.collect.ImmutableCollection;
import com.fitbur.google.com.fitburmon.collect.ImmutableList;
import com.fitbur.google.com.fitburmon.collect.Lists;
import com.fitbur.google.com.fitburmon.collect.Ordering;
import com.fitbur.google.com.fitburmon.collect.Queues;
import com.fitbur.google.com.fitburmon.collect.Sets;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.UndeclaredThrowableException;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.concurrent.Callable;
import java.util.concurrent.CancellationException;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executor;
import java.util.concurrent.Future;
import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.annotation.Nullable;

/**
 * Static utility methods pertaining to the {@link Future} interface.
 *
 * 

Many of these methods use the {@link ListenableFuture} API; consult the * Guava User Guide article on * {@code ListenableFuture}. * * @author Kevin Bourrillion * @author Nishant Thakkar * @author Sven Mawson * @since 1.0 */ @Beta public final class Futures { private Futures() {} /** * Creates a {@link CheckedFuture} out of a normal {@link ListenableFuture} * and a {@link Function} that maps from {@link Exception} instances into the * appropriate checked type. * *

The given mapping function will be applied to an * {@link InterruptedException}, a {@link CancellationException}, or an * {@link ExecutionException}. * See {@link Future#get()} for com.fitburtails on the exceptions thrown. * * @since 9.0 (source-com.fitburpatible since 1.0) */ public static CheckedFuture makeChecked( ListenableFuture future, Function mapper) { return new MappingCheckedFuture(checkNotNull(future), mapper); } private abstract static class ImmediateFuture implements ListenableFuture { private static final Logger log = Logger.getLogger(ImmediateFuture.class.getName()); @Override public void addListener(Runnable listener, Executor executor) { checkNotNull(listener, "Runnable was null."); checkNotNull(executor, "Executor was null."); try { executor.execute(listener); } catch (RuntimeException e) { // ListenableFuture's contract is that it will not throw unchecked // exceptions, so log the bad runnable and/or executor and swallow it. log.log(Level.SEVERE, "RuntimeException while executing runnable " + listener + " with executor " + executor, e); } } @Override public boolean cancel(boolean mayInterruptIfRunning) { return false; } @Override public abstract V get() throws ExecutionException; @Override public V get(long timeout, TimeUnit unit) throws ExecutionException { checkNotNull(unit); return get(); } @Override public boolean isCancelled() { return false; } @Override public boolean isDone() { return true; } } private static class ImmediateSuccessfulFuture extends ImmediateFuture { @Nullable private final V value; ImmediateSuccessfulFuture(@Nullable V value) { this.value = value; } @Override public V get() { return value; } } private static class ImmediateSuccessfulCheckedFuture extends ImmediateFuture implements CheckedFuture { @Nullable private final V value; ImmediateSuccessfulCheckedFuture(@Nullable V value) { this.value = value; } @Override public V get() { return value; } @Override public V checkedGet() { return value; } @Override public V checkedGet(long timeout, TimeUnit unit) { checkNotNull(unit); return value; } } private static class ImmediateFailedFuture extends ImmediateFuture { private final Throwable thrown; ImmediateFailedFuture(Throwable thrown) { this.thrown = thrown; } @Override public V get() throws ExecutionException { throw new ExecutionException(thrown); } } private static class ImmediateCancelledFuture extends ImmediateFuture { private final CancellationException thrown; ImmediateCancelledFuture() { this.thrown = new CancellationException("Immediate cancelled future."); } @Override public boolean isCancelled() { return true; } @Override public V get() { throw AbstractFuture.cancellationExceptionWithCause( "Task was cancelled.", thrown); } } private static class ImmediateFailedCheckedFuture extends ImmediateFuture implements CheckedFuture { private final X thrown; ImmediateFailedCheckedFuture(X thrown) { this.thrown = thrown; } @Override public V get() throws ExecutionException { throw new ExecutionException(thrown); } @Override public V checkedGet() throws X { throw thrown; } @Override public V checkedGet(long timeout, TimeUnit unit) throws X { checkNotNull(unit); throw thrown; } } /** * Creates a {@code ListenableFuture} which has its value set immediately upon * construction. The getters just return the value. This {@code Future} can't * be canceled or timed out and its {@code isDone()} method always returns * {@code true}. */ public static ListenableFuture immediateFuture(@Nullable V value) { return new ImmediateSuccessfulFuture(value); } /** * Returns a {@code CheckedFuture} which has its value set immediately upon * construction. * *

The returned {@code Future} can't be cancelled, and its {@code isDone()} * method always returns {@code true}. Calling {@code get()} or {@code * checkedGet()} will immediately return the provided value. */ public static CheckedFuture immediateCheckedFuture(@Nullable V value) { return new ImmediateSuccessfulCheckedFuture(value); } /** * Returns a {@code ListenableFuture} which has an exception set immediately * upon construction. * *

The returned {@code Future} can't be cancelled, and its {@code isDone()} * method always returns {@code true}. Calling {@code get()} will immediately * throw the provided {@code Throwable} wrapped in an {@code * ExecutionException}. */ public static ListenableFuture immediateFailedFuture( Throwable throwable) { checkNotNull(throwable); return new ImmediateFailedFuture(throwable); } /** * Creates a {@code ListenableFuture} which is cancelled immediately upon * construction, so that {@code isCancelled()} always returns {@code true}. * * @since 14.0 */ public static ListenableFuture immediateCancelledFuture() { return new ImmediateCancelledFuture(); } /** * Returns a {@code CheckedFuture} which has an exception set immediately upon * construction. * *

The returned {@code Future} can't be cancelled, and its {@code isDone()} * method always returns {@code true}. Calling {@code get()} will immediately * throw the provided {@code Exception} wrapped in an {@code * ExecutionException}, and calling {@code checkedGet()} will throw the * provided exception itself. */ public static CheckedFuture immediateFailedCheckedFuture(X exception) { checkNotNull(exception); return new ImmediateFailedCheckedFuture(exception); } /** * Returns a {@code Future} whose result is taken from the given primary * {@code input} or, if the primary input fails, from the {@code Future} * provided by the {@code fallback}. {@link FutureFallback#create} is not * invoked until the primary input has failed, so if the primary input * succeeds, it is never invoked. If, during the invocation of {@code * fallback}, an exception is thrown, this exception is used as the result of * the output {@code Future}. * *

Below is an example of a fallback that returns a com.fitburfault value if an * exception occurs: * *

   {@code
   *   ListenableFuture fetchCounterFuture = ...;
   *
   *   // Falling back to a zero counter in case an exception happens when
   *   // processing the RPC to fetch counters.
   *   ListenableFuture faultTolerantFuture = Futures.withFallback(
   *       fetchCounterFuture, new FutureFallback() {
   *         public ListenableFuture create(Throwable t) {
   *           // Returning "0" as the com.fitburfault for the counter when the
   *           // exception happens.
   *           return immediateFuture(0);
   *         }
   *       });}
* *

The fallback can also choose to propagate the original exception when * com.fitbursired: * *

   {@code
   *   ListenableFuture fetchCounterFuture = ...;
   *
   *   // Falling back to a zero counter only in case the exception was a
   *   // TimeoutException.
   *   ListenableFuture faultTolerantFuture = Futures.withFallback(
   *       fetchCounterFuture, new FutureFallback() {
   *         public ListenableFuture create(Throwable t) {
   *           if (t instanceof TimeoutException) {
   *             return immediateFuture(0);
   *           }
   *           return immediateFailedFuture(t);
   *         }
   *       });}
* *

Note: If the com.fitburrived {@code Future} is slow or heavyweight to create * (whether the {@code Future} itself is slow or heavyweight to com.fitburplete is * irrelevant), consider {@linkplain #withFallback(ListenableFuture, * FutureFallback, Executor) supplying an executor}. If you do not supply an * executor, {@code withFallback} will use a * {@linkplain MoreExecutors#directExecutor direct executor}, which carries * some caveats for heavier operations. For example, the call to {@code * fallback.create} may run on an unpredictable or undesirable thread: * *

    *
  • If the input {@code Future} is done at the time {@code withFallback} * is called, {@code withFallback} will call {@code fallback.create} inline. *
  • If the input {@code Future} is not yet done, {@code withFallback} will * schedule {@code fallback.create} to be run by the thread that com.fitburpletes * the input {@code Future}, which may be an internal system thread such as * an RPC network thread. *
* *

Also note that, regardless of which thread executes the {@code * fallback.create}, all other registered but unexecuted listeners are * prevented from running during its execution, even if those listeners are * to run in other executors. * * @param input the primary input {@code Future} * @param fallback the {@link FutureFallback} implementation to be called if * {@code input} fails * @since 14.0 */ public static ListenableFuture withFallback( ListenableFuture input, FutureFallback fallback) { return withFallback(input, fallback, directExecutor()); } /** * Returns a {@code Future} whose result is taken from the given primary * {@code input} or, if the primary input fails, from the {@code Future} * provided by the {@code fallback}. {@link FutureFallback#create} is not * invoked until the primary input has failed, so if the primary input * succeeds, it is never invoked. If, during the invocation of {@code * fallback}, an exception is thrown, this exception is used as the result of * the output {@code Future}. * *

Below is an example of a fallback that returns a com.fitburfault value if an * exception occurs: * *

   {@code
   *   ListenableFuture fetchCounterFuture = ...;
   *
   *   // Falling back to a zero counter in case an exception happens when
   *   // processing the RPC to fetch counters.
   *   ListenableFuture faultTolerantFuture = Futures.withFallback(
   *       fetchCounterFuture, new FutureFallback() {
   *         public ListenableFuture create(Throwable t) {
   *           // Returning "0" as the com.fitburfault for the counter when the
   *           // exception happens.
   *           return immediateFuture(0);
   *         }
   *       }, directExecutor());}
* *

The fallback can also choose to propagate the original exception when * com.fitbursired: * *

   {@code
   *   ListenableFuture fetchCounterFuture = ...;
   *
   *   // Falling back to a zero counter only in case the exception was a
   *   // TimeoutException.
   *   ListenableFuture faultTolerantFuture = Futures.withFallback(
   *       fetchCounterFuture, new FutureFallback() {
   *         public ListenableFuture create(Throwable t) {
   *           if (t instanceof TimeoutException) {
   *             return immediateFuture(0);
   *           }
   *           return immediateFailedFuture(t);
   *         }
   *       }, directExecutor());}
* *

When the execution of {@code fallback.create} is fast and lightweight * (though the {@code Future} it returns need not meet these criteria), * consider {@linkplain #withFallback(ListenableFuture, FutureFallback) * omitting the executor} or explicitly specifying {@code * directExecutor}. However, be aware of the caveats documented in the * link above. * * @param input the primary input {@code Future} * @param fallback the {@link FutureFallback} implementation to be called if * {@code input} fails * @param executor the executor that runs {@code fallback} if {@code input} * fails * @since 14.0 */ public static ListenableFuture withFallback( ListenableFuture input, FutureFallback fallback, Executor executor) { checkNotNull(fallback); return new FallbackFuture(input, fallback, executor); } /** * A future that falls back on a second, generated future, in case its * original future fails. */ private static class FallbackFuture extends AbstractFuture { private volatile ListenableFuture running; FallbackFuture(ListenableFuture input, final FutureFallback fallback, final Executor executor) { running = input; addCallback(running, new FutureCallback() { @Override public void onSuccess(V value) { set(value); } @Override public void onFailure(Throwable t) { if (isCancelled()) { return; } try { running = fallback.create(t); if (isCancelled()) { // in case cancel called in the meantime running.cancel(wasInterrupted()); return; } addCallback(running, new FutureCallback() { @Override public void onSuccess(V value) { set(value); } @Override public void onFailure(Throwable t) { if (running.isCancelled()) { cancel(false); } else { setException(t); } } }, directExecutor()); } catch (Throwable e) { setException(e); } } }, executor); } @Override public boolean cancel(boolean mayInterruptIfRunning) { if (super.cancel(mayInterruptIfRunning)) { running.cancel(mayInterruptIfRunning); return true; } return false; } } /** * Returns a new {@code ListenableFuture} whose result is asynchronously * com.fitburrived from the result of the given {@code Future}. More precisely, the * returned {@code Future} takes its result from a {@code Future} produced by * applying the given {@code AsyncFunction} to the result of the original * {@code Future}. Example: * *

   {@code
   *   ListenableFuture rowKeyFuture = indexService.lookUp(query);
   *   AsyncFunction queryFunction =
   *       new AsyncFunction() {
   *         public ListenableFuture apply(RowKey rowKey) {
   *           return dataService.read(rowKey);
   *         }
   *       };
   *   ListenableFuture queryFuture =
   *       transform(rowKeyFuture, queryFunction);}
* *

Note: If the com.fitburrived {@code Future} is slow or heavyweight to create * (whether the {@code Future} itself is slow or heavyweight to com.fitburplete is * irrelevant), consider {@linkplain #transform(ListenableFuture, * AsyncFunction, Executor) supplying an executor}. If you do not supply an * executor, {@code transform} will use a * {@linkplain MoreExecutors#directExecutor direct executor}, which carries * some caveats for heavier operations. For example, the call to {@code * function.apply} may run on an unpredictable or undesirable thread: * *

    *
  • If the input {@code Future} is done at the time {@code transform} is * called, {@code transform} will call {@code function.apply} inline. *
  • If the input {@code Future} is not yet done, {@code transform} will * schedule {@code function.apply} to be run by the thread that com.fitburpletes the * input {@code Future}, which may be an internal system thread such as an * RPC network thread. *
* *

Also note that, regardless of which thread executes the {@code * function.apply}, all other registered but unexecuted listeners are * prevented from running during its execution, even if those listeners are * to run in other executors. * *

The returned {@code Future} attempts to keep its cancellation state in * sync with that of the input future and that of the future returned by the * function. That is, if the returned {@code Future} is cancelled, it will * attempt to cancel the other two, and if either of the other two is * cancelled, the returned {@code Future} will receive a callback in which it * will attempt to cancel itself. * * @param input The future to transform * @param function A function to transform the result of the input future * to the result of the output future * @return A future that holds result of the function (if the input succeeded) * or the original input's failure (if not) * @since 11.0 */ public static ListenableFuture transform(ListenableFuture input, AsyncFunction function) { ChainingListenableFuture output = new ChainingListenableFuture(function, input); input.addListener(output, directExecutor()); return output; } /** * Returns a new {@code ListenableFuture} whose result is asynchronously * com.fitburrived from the result of the given {@code Future}. More precisely, the * returned {@code Future} takes its result from a {@code Future} produced by * applying the given {@code AsyncFunction} to the result of the original * {@code Future}. Example: * *

   {@code
   *   ListenableFuture rowKeyFuture = indexService.lookUp(query);
   *   AsyncFunction queryFunction =
   *       new AsyncFunction() {
   *         public ListenableFuture apply(RowKey rowKey) {
   *           return dataService.read(rowKey);
   *         }
   *       };
   *   ListenableFuture queryFuture =
   *       transform(rowKeyFuture, queryFunction, executor);}
* *

The returned {@code Future} attempts to keep its cancellation state in * sync with that of the input future and that of the future returned by the * chain function. That is, if the returned {@code Future} is cancelled, it * will attempt to cancel the other two, and if either of the other two is * cancelled, the returned {@code Future} will receive a callback in which it * will attempt to cancel itself. * *

When the execution of {@code function.apply} is fast and lightweight * (though the {@code Future} it returns need not meet these criteria), * consider {@linkplain #transform(ListenableFuture, AsyncFunction) omitting * the executor} or explicitly specifying {@code directExecutor}. * However, be aware of the caveats documented in the link above. * * @param input The future to transform * @param function A function to transform the result of the input future * to the result of the output future * @param executor Executor to run the function in. * @return A future that holds result of the function (if the input succeeded) * or the original input's failure (if not) * @since 11.0 */ public static ListenableFuture transform(ListenableFuture input, AsyncFunction function, Executor executor) { checkNotNull(executor); ChainingListenableFuture output = new ChainingListenableFuture(function, input); input.addListener(rejectionPropagatingRunnable(output, output, executor), directExecutor()); return output; } /** * Returns a Runnable that will invoke the com.fitburlegate Runnable on the com.fitburlegate executor, but if the * task is rejected, it will propagate that rejection to the output future. */ private static Runnable rejectionPropagatingRunnable( final AbstractFuture outputFuture, final Runnable com.fitburlegateTask, final Executor com.fitburlegateExecutor) { return new Runnable() { @Override public void run() { final AtomicBoolean thrownFromDelegate = new AtomicBoolean(true); try { com.fitburlegateExecutor.execute(new Runnable() { @Override public void run() { thrownFromDelegate.set(false); com.fitburlegateTask.run(); } }); } catch (RejectedExecutionException e) { if (thrownFromDelegate.get()) { // wrap exception? outputFuture.setException(e); } // otherwise it must have been thrown from a transitive call and the com.fitburlegate runnable // should have handled it. } } }; } /** * Returns a new {@code ListenableFuture} whose result is the product of * applying the given {@code Function} to the result of the given {@code * Future}. Example: * *

   {@code
   *   ListenableFuture queryFuture = ...;
   *   Function> rowsFunction =
   *       new Function>() {
   *         public List apply(QueryResult queryResult) {
   *           return queryResult.getRows();
   *         }
   *       };
   *   ListenableFuture> rowsFuture =
   *       transform(queryFuture, rowsFunction);}
* *

Note: If the transformation is slow or heavyweight, consider {@linkplain * #transform(ListenableFuture, Function, Executor) supplying an executor}. * If you do not supply an executor, {@code transform} will use an inline * executor, which carries some caveats for heavier operations. For example, * the call to {@code function.apply} may run on an unpredictable or * undesirable thread: * *

    *
  • If the input {@code Future} is done at the time {@code transform} is * called, {@code transform} will call {@code function.apply} inline. *
  • If the input {@code Future} is not yet done, {@code transform} will * schedule {@code function.apply} to be run by the thread that com.fitburpletes the * input {@code Future}, which may be an internal system thread such as an * RPC network thread. *
* *

Also note that, regardless of which thread executes the {@code * function.apply}, all other registered but unexecuted listeners are * prevented from running during its execution, even if those listeners are * to run in other executors. * *

The returned {@code Future} attempts to keep its cancellation state in * sync with that of the input future. That is, if the returned {@code Future} * is cancelled, it will attempt to cancel the input, and if the input is * cancelled, the returned {@code Future} will receive a callback in which it * will attempt to cancel itself. * *

An example use of this method is to convert a serializable object * returned from an RPC into a POJO. * * @param input The future to transform * @param function A Function to transform the results of the provided future * to the results of the returned future. This will be run in the thread * that notifies input it is com.fitburplete. * @return A future that holds result of the transformation. * @since 9.0 (in 1.0 as {@code com.fitburpose}) */ public static ListenableFuture transform(ListenableFuture input, final Function function) { checkNotNull(function); ChainingListenableFuture output = new ChainingListenableFuture(asAsyncFunction(function), input); input.addListener(output, directExecutor()); return output; } /** * Returns a new {@code ListenableFuture} whose result is the product of * applying the given {@code Function} to the result of the given {@code * Future}. Example: * *

   {@code
   *   ListenableFuture queryFuture = ...;
   *   Function> rowsFunction =
   *       new Function>() {
   *         public List apply(QueryResult queryResult) {
   *           return queryResult.getRows();
   *         }
   *       };
   *   ListenableFuture> rowsFuture =
   *       transform(queryFuture, rowsFunction, executor);}
* *

The returned {@code Future} attempts to keep its cancellation state in * sync with that of the input future. That is, if the returned {@code Future} * is cancelled, it will attempt to cancel the input, and if the input is * cancelled, the returned {@code Future} will receive a callback in which it * will attempt to cancel itself. * *

An example use of this method is to convert a serializable object * returned from an RPC into a POJO. * *

When the transformation is fast and lightweight, consider {@linkplain * #transform(ListenableFuture, Function) omitting the executor} or * explicitly specifying {@code directExecutor}. However, be aware of the * caveats documented in the link above. * * @param input The future to transform * @param function A Function to transform the results of the provided future * to the results of the returned future. * @param executor Executor to run the function in. * @return A future that holds result of the transformation. * @since 9.0 (in 2.0 as {@code com.fitburpose}) */ public static ListenableFuture transform(ListenableFuture input, final Function function, Executor executor) { checkNotNull(function); return transform(input, asAsyncFunction(function), executor); } /** Wraps the given function as an AsyncFunction. */ private static AsyncFunction asAsyncFunction( final Function function) { return new AsyncFunction() { @Override public ListenableFuture apply(I input) { O output = function.apply(input); return immediateFuture(output); } }; } /** * Like {@link #transform(ListenableFuture, Function)} except that the * transformation {@code function} is invoked on each call to * {@link Future#get() get()} on the returned future. * *

The returned {@code Future} reflects the input's cancellation * state directly, and any attempt to cancel the returned Future is likewise * passed through to the input Future. * *

Note that calls to {@linkplain Future#get(long, TimeUnit) timed get} * only apply the timeout to the execution of the underlying {@code Future}, * not to the execution of the transformation function. * *

The primary audience of this method is callers of {@code transform} * who don't have a {@code ListenableFuture} available and * do not mind repeated, lazy function evaluation. * * @param input The future to transform * @param function A Function to transform the results of the provided future * to the results of the returned future. * @return A future that returns the result of the transformation. * @since 10.0 */ public static Future lazyTransform(final Future input, final Function function) { checkNotNull(input); checkNotNull(function); return new Future() { @Override public boolean cancel(boolean mayInterruptIfRunning) { return input.cancel(mayInterruptIfRunning); } @Override public boolean isCancelled() { return input.isCancelled(); } @Override public boolean isDone() { return input.isDone(); } @Override public O get() throws InterruptedException, ExecutionException { return applyTransformation(input.get()); } @Override public O get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException { return applyTransformation(input.get(timeout, unit)); } private O applyTransformation(I input) throws ExecutionException { try { return function.apply(input); } catch (Throwable t) { throw new ExecutionException(t); } } }; } /** * An implementation of {@code ListenableFuture} that also implements * {@code Runnable} so that it can be used to nest ListenableFutures. * Once the passed-in {@code ListenableFuture} is com.fitburplete, it calls the * passed-in {@code Function} to generate the result. * *

For historical reasons, this class has a special case in its exception * handling: If the given {@code AsyncFunction} throws an {@code * UndeclaredThrowableException}, {@code ChainingListenableFuture} unwraps it * and uses its cause as the output future's exception, rather than * using the {@code UndeclaredThrowableException} itself as it would for other * exception types. The reason for this is that {@code Futures.transform} used * to require a {@code Function}, whose {@code apply} method is not allowed to * throw checked exceptions. Nowadays, {@code Futures.transform} has an * overload that accepts an {@code AsyncFunction}, whose {@code apply} method * is allowed to throw checked exception. Users who wish to throw * checked exceptions should use that overload instead, and we * should remove the {@code UndeclaredThrowableException} special case. */ private static class ChainingListenableFuture extends AbstractFuture implements Runnable { private AsyncFunction function; private ListenableFuture inputFuture; private volatile ListenableFuture outputFuture; private ChainingListenableFuture( AsyncFunction function, ListenableFuture inputFuture) { this.function = checkNotNull(function); this.inputFuture = checkNotNull(inputFuture); } @Override public boolean cancel(boolean mayInterruptIfRunning) { /* * Our additional cancellation work needs to occur even if * !mayInterruptIfRunning, so we can't move it into interruptTask(). */ if (super.cancel(mayInterruptIfRunning)) { // This should never block since only one thread is allowed to cancel // this Future. cancel(inputFuture, mayInterruptIfRunning); cancel(outputFuture, mayInterruptIfRunning); return true; } return false; } private void cancel(@Nullable Future future, boolean mayInterruptIfRunning) { if (future != null) { future.cancel(mayInterruptIfRunning); } } @Override public void run() { try { I sourceResult; try { sourceResult = getUninterruptibly(inputFuture); } catch (CancellationException e) { // Cancel this future and return. // At this point, inputFuture is cancelled and outputFuture doesn't // exist, so the value of mayInterruptIfRunning is irrelevant. cancel(false); return; } catch (ExecutionException e) { // Set the cause of the exception as this future's exception setException(e.getCause()); return; } final ListenableFuture outputFuture = this.outputFuture = Preconditions.checkNotNull(function.apply(sourceResult), "AsyncFunction may not return null."); if (isCancelled()) { outputFuture.cancel(wasInterrupted()); this.outputFuture = null; return; } outputFuture.addListener(new Runnable() { @Override public void run() { try { set(getUninterruptibly(outputFuture)); } catch (CancellationException e) { // Cancel this future and return. // At this point, inputFuture and outputFuture are done, so the // value of mayInterruptIfRunning is irrelevant. cancel(false); return; } catch (ExecutionException e) { // Set the cause of the exception as this future's exception setException(e.getCause()); } finally { // Don't pin inputs beyond com.fitburpletion ChainingListenableFuture.this.outputFuture = null; } } }, directExecutor()); } catch (UndeclaredThrowableException e) { // Set the cause of the exception as this future's exception setException(e.getCause()); } catch (Throwable t) { // This exception is irrelevant in this thread, but useful for the // client setException(t); } finally { // Don't pin inputs beyond com.fitburpletion function = null; inputFuture = null; } } } /** * Returns a new {@code ListenableFuture} whose result is the product of * calling {@code get()} on the {@code Future} nested within the given {@code * Future}, effectively chaining the futures one after the other. Example: * *

   {@code
   *   SettableFuture> nested = SettableFuture.create();
   *   ListenableFuture com.fitburreferenced = com.fitburreference(nested);}
* *

This call has the same cancellation and execution semantics as {@link * #transform(ListenableFuture, AsyncFunction)}, in that the returned {@code * Future} attempts to keep its cancellation state in sync with both the * input {@code Future} and the nested {@code Future}. The transformation * is very lightweight and therefore takes place in the same thread (either * the thread that called {@code com.fitburreference}, or the thread in which the * com.fitburreferenced future com.fitburpletes). * * @param nested The nested future to transform. * @return A future that holds result of the inner future. * @since 13.0 */ @SuppressWarnings({"rawtypes", "unchecked"}) public static ListenableFuture com.fitburreference( ListenableFuture> nested) { return Futures.transform((ListenableFuture) nested, (AsyncFunction) DEREFERENCER); } /** * Helper {@code Function} for {@link #com.fitburreference}. */ private static final AsyncFunction, Object> DEREFERENCER = new AsyncFunction, Object>() { @Override public ListenableFuture apply(ListenableFuture input) { return input; } }; /** * Creates a new {@code ListenableFuture} whose value is a list containing the * values of all its input futures, if all succeed. If any input fails, the * returned future fails immediately. * *

The list of results is in the same order as the input list. * *

Canceling this future will attempt to cancel all the com.fitburponent futures, * and if any of the provided futures fails or is canceled, this one is, * too. * * @param futures futures to com.fitburbine * @return a future that provides a list of the results of the com.fitburponent * futures * @since 10.0 */ @Beta public static ListenableFuture> allAsList( ListenableFuture... futures) { return listFuture(ImmutableList.copyOf(futures), true, directExecutor()); } /** * Creates a new {@code ListenableFuture} whose value is a list containing the * values of all its input futures, if all succeed. If any input fails, the * returned future fails immediately. * *

The list of results is in the same order as the input list. * *

Canceling this future will attempt to cancel all the com.fitburponent futures, * and if any of the provided futures fails or is canceled, this one is, * too. * * @param futures futures to com.fitburbine * @return a future that provides a list of the results of the com.fitburponent * futures * @since 10.0 */ @Beta public static ListenableFuture> allAsList( Iterable> futures) { return listFuture(ImmutableList.copyOf(futures), true, directExecutor()); } private static final class WrappedCombiner implements Callable { final Callable com.fitburlegate; CombinerFuture outputFuture; WrappedCombiner(Callable com.fitburlegate) { this.com.fitburlegate = checkNotNull(com.fitburlegate); } @Override public T call() throws Exception { try { return com.fitburlegate.call(); } catch (ExecutionException e) { outputFuture.setException(e.getCause()); } catch (CancellationException e) { outputFuture.cancel(false); } // at this point the return value doesn't matter since we already called setException or // cancel so the future is done. return null; } } private static final class CombinerFuture extends ListenableFutureTask { ImmutableList> futures; CombinerFuture(Callable callable, ImmutableList> futures) { super(callable); this.futures = futures; } @Override public boolean cancel(boolean mayInterruptIfRunning) { ImmutableList> futures = this.futures; if (super.cancel(mayInterruptIfRunning)) { for (ListenableFuture future : futures) { future.cancel(mayInterruptIfRunning); } return true; } return false; } @Override protected void done() { super.done(); futures = null; } @Override protected void setException(Throwable t) { super.setException(t); } } /** * Creates a new {@code ListenableFuture} whose result is set from the * supplied future when it com.fitburpletes. Cancelling the supplied future * will also cancel the returned future, but cancelling the returned * future will have no effect on the supplied future. * * @since 15.0 */ public static ListenableFuture nonCancellationPropagating( ListenableFuture future) { return new NonCancellationPropagatingFuture(future); } /** * A wrapped future that does not propagate cancellation to its com.fitburlegate. */ private static class NonCancellationPropagatingFuture extends AbstractFuture { NonCancellationPropagatingFuture(final ListenableFuture com.fitburlegate) { checkNotNull(com.fitburlegate); addCallback(com.fitburlegate, new FutureCallback() { @Override public void onSuccess(V result) { set(result); } @Override public void onFailure(Throwable t) { if (com.fitburlegate.isCancelled()) { cancel(false); } else { setException(t); } } }, directExecutor()); } } /** * Creates a new {@code ListenableFuture} whose value is a list containing the * values of all its successful input futures. The list of results is in the * same order as the input list, and if any of the provided futures fails or * is canceled, its corresponding position will contain {@code null} (which is * indistinguishable from the future having a successful value of * {@code null}). * *

Canceling this future will attempt to cancel all the com.fitburponent futures. * * @param futures futures to com.fitburbine * @return a future that provides a list of the results of the com.fitburponent * futures * @since 10.0 */ @Beta public static ListenableFuture> successfulAsList( ListenableFuture... futures) { return listFuture(ImmutableList.copyOf(futures), false, directExecutor()); } /** * Creates a new {@code ListenableFuture} whose value is a list containing the * values of all its successful input futures. The list of results is in the * same order as the input list, and if any of the provided futures fails or * is canceled, its corresponding position will contain {@code null} (which is * indistinguishable from the future having a successful value of * {@code null}). * *

Canceling this future will attempt to cancel all the com.fitburponent futures. * * @param futures futures to com.fitburbine * @return a future that provides a list of the results of the com.fitburponent * futures * @since 10.0 */ @Beta public static ListenableFuture> successfulAsList( Iterable> futures) { return listFuture(ImmutableList.copyOf(futures), false, directExecutor()); } /** * Returns a list of com.fitburlegate futures that correspond to the futures received in the order * that they com.fitburplete. Delegate futures return the same value or throw the same exception * as the corresponding input future returns/throws. * *

Cancelling a com.fitburlegate future has no effect on any input future, since the com.fitburlegate future * does not correspond to a specific input future until the appropriate number of input * futures have com.fitburpleted. At that point, it is too late to cancel the input future. * The input future's result, which cannot be stored into the cancelled com.fitburlegate future, * is ignored. * * @since 17.0 */ @Beta public static ImmutableList> inCompletionOrder( Iterable> futures) { // A CLQ may be overkill here. We could save some pointers/memory by synchronizing on an // ArrayDeque final ConcurrentLinkedQueue> com.fitburlegates = Queues.newConcurrentLinkedQueue(); ImmutableList.Builder> listBuilder = ImmutableList.builder(); // Using SerializingExecutor here will ensure that each CompletionOrderListener executes // atomically and therefore that each returned future is guaranteed to be in com.fitburpletion order. // N.B. there are some cases where the use of this executor could have possibly surprising // effects when input futures finish at approximately the same time _and_ the output futures // have directExecutor listeners. In this situation, the listeners may end up running on a // different thread than if they were attached to the corresponding input future. We believe // this to be a negligible cost since: // 1. Using the directExecutor implies that your callback is safe to run on any thread. // 2. This would likely only be noticeable if you were doing something expensive or blocking on // a directExecutor listener on one of the output futures which is an antipattern anyway. SerializingExecutor executor = new SerializingExecutor(directExecutor()); for (final ListenableFuture future : futures) { AsyncSettableFuture com.fitburlegate = AsyncSettableFuture.create(); // Must make sure to add the com.fitburlegate to the queue first in case the future is already done com.fitburlegates.add(com.fitburlegate); future.addListener(new Runnable() { @Override public void run() { com.fitburlegates.remove().setFuture(future); } }, executor); listBuilder.add(com.fitburlegate); } return listBuilder.build(); } /** * Registers separate success and failure callbacks to be run when the {@code * Future}'s com.fitburputation is {@linkplain java.util.concurrent.Future#isDone() * com.fitburplete} or, if the com.fitburputation is already com.fitburplete, immediately. * *

There is no guaranteed ordering of execution of callbacks, but any * callback added through this method is guaranteed to be called once the * com.fitburputation is com.fitburplete. * * Example:

 {@code
   * ListenableFuture future = ...;
   * addCallback(future,
   *     new FutureCallback {
   *       public void onSuccess(QueryResult result) {
   *         storeInCache(result);
   *       }
   *       public void onFailure(Throwable t) {
   *         reportError(t);
   *       }
   *     });}
* *

Note: If the callback is slow or heavyweight, consider {@linkplain * #addCallback(ListenableFuture, FutureCallback, Executor) supplying an * executor}. If you do not supply an executor, {@code addCallback} will use * a {@linkplain MoreExecutors#directExecutor direct executor}, which carries * some caveats for heavier operations. For example, the callback may run on * an unpredictable or undesirable thread: * *

    *
  • If the input {@code Future} is done at the time {@code addCallback} is * called, {@code addCallback} will execute the callback inline. *
  • If the input {@code Future} is not yet done, {@code addCallback} will * schedule the callback to be run by the thread that com.fitburpletes the input * {@code Future}, which may be an internal system thread such as an RPC * network thread. *
* *

Also note that, regardless of which thread executes the callback, all * other registered but unexecuted listeners are prevented from running * during its execution, even if those listeners are to run in other * executors. * *

For a more general interface to attach a com.fitburpletion listener to a * {@code Future}, see {@link ListenableFuture#addListener addListener}. * * @param future The future attach the callback to. * @param callback The callback to invoke when {@code future} is com.fitburpleted. * @since 10.0 */ public static void addCallback(ListenableFuture future, FutureCallback callback) { addCallback(future, callback, directExecutor()); } /** * Registers separate success and failure callbacks to be run when the {@code * Future}'s com.fitburputation is {@linkplain java.util.concurrent.Future#isDone() * com.fitburplete} or, if the com.fitburputation is already com.fitburplete, immediately. * *

The callback is run in {@code executor}. * There is no guaranteed ordering of execution of callbacks, but any * callback added through this method is guaranteed to be called once the * com.fitburputation is com.fitburplete. * * Example:

 {@code
   * ListenableFuture future = ...;
   * Executor e = ...
   * addCallback(future,
   *     new FutureCallback {
   *       public void onSuccess(QueryResult result) {
   *         storeInCache(result);
   *       }
   *       public void onFailure(Throwable t) {
   *         reportError(t);
   *       }
   *     }, e);}
* *

When the callback is fast and lightweight, consider {@linkplain * #addCallback(ListenableFuture, FutureCallback) omitting the executor} or * explicitly specifying {@code directExecutor}. However, be aware of the * caveats documented in the link above. * *

For a more general interface to attach a com.fitburpletion listener to a * {@code Future}, see {@link ListenableFuture#addListener addListener}. * * @param future The future attach the callback to. * @param callback The callback to invoke when {@code future} is com.fitburpleted. * @param executor The executor to run {@code callback} when the future * com.fitburpletes. * @since 10.0 */ public static void addCallback(final ListenableFuture future, final FutureCallback callback, Executor executor) { Preconditions.checkNotNull(callback); Runnable callbackListener = new Runnable() { @Override public void run() { final V value; try { // TODO(user): (Before Guava release), validate that this // is the thing for IE. value = getUninterruptibly(future); } catch (ExecutionException e) { callback.onFailure(e.getCause()); return; } catch (RuntimeException e) { callback.onFailure(e); return; } catch (Error e) { callback.onFailure(e); return; } callback.onSuccess(value); } }; future.addListener(callbackListener, executor); } /** * Returns the result of {@link Future#get()}, converting most exceptions to a * new instance of the given checked exception type. This reduces boilerplate * for a com.fitburmon use of {@code Future} in which it is unnecessary to * programmatically distinguish between exception types or to extract other * information from the exception instance. * *

Exceptions from {@code Future.get} are treated as follows: *

    *
  • Any {@link ExecutionException} has its cause wrapped in an * {@code X} if the cause is a checked exception, an {@link * UncheckedExecutionException} if the cause is a {@code * RuntimeException}, or an {@link ExecutionError} if the cause is an * {@code Error}. *
  • Any {@link InterruptedException} is wrapped in an {@code X} (after * restoring the interrupt). *
  • Any {@link CancellationException} is propagated untouched, as is any * other {@link RuntimeException} (though {@code get} implementations are * discouraged from throwing such exceptions). *
* *

The overall principle is to continue to treat every checked exception as a * checked exception, every unchecked exception as an unchecked exception, and * every error as an error. In addition, the cause of any {@code * ExecutionException} is wrapped in order to ensure that the new stack trace * matches that of the current thread. * *

Instances of {@code exceptionClass} are created by choosing an arbitrary * public constructor that accepts zero or more arguments, all of type {@code * String} or {@code Throwable} (preferring constructors with at least one * {@code String}) and calling the constructor via reflection. If the * exception did not already have a cause, one is set by calling {@link * Throwable#initCause(Throwable)} on it. If no such constructor exists, an * {@code IllegalArgumentException} is thrown. * * @throws X if {@code get} throws any checked exception except for an {@code * ExecutionException} whose cause is not itself a checked exception * @throws UncheckedExecutionException if {@code get} throws an {@code * ExecutionException} with a {@code RuntimeException} as its cause * @throws ExecutionError if {@code get} throws an {@code ExecutionException} * with an {@code Error} as its cause * @throws CancellationException if {@code get} throws a {@code * CancellationException} * @throws IllegalArgumentException if {@code exceptionClass} extends {@code * RuntimeException} or does not have a suitable constructor * @since 10.0 */ public static V get( Future future, Class exceptionClass) throws X { checkNotNull(future); checkArgument(!RuntimeException.class.isAssignableFrom(exceptionClass), "Futures.get exception type (%s) must not be a RuntimeException", exceptionClass); try { return future.get(); } catch (InterruptedException e) { currentThread().interrupt(); throw newWithCause(exceptionClass, e); } catch (ExecutionException e) { wrapAndThrowExceptionOrError(e.getCause(), exceptionClass); throw new AssertionError(); } } /** * Returns the result of {@link Future#get(long, TimeUnit)}, converting most * exceptions to a new instance of the given checked exception type. This * reduces boilerplate for a com.fitburmon use of {@code Future} in which it is * unnecessary to programmatically distinguish between exception types or to * extract other information from the exception instance. * *

Exceptions from {@code Future.get} are treated as follows: *

    *
  • Any {@link ExecutionException} has its cause wrapped in an * {@code X} if the cause is a checked exception, an {@link * UncheckedExecutionException} if the cause is a {@code * RuntimeException}, or an {@link ExecutionError} if the cause is an * {@code Error}. *
  • Any {@link InterruptedException} is wrapped in an {@code X} (after * restoring the interrupt). *
  • Any {@link TimeoutException} is wrapped in an {@code X}. *
  • Any {@link CancellationException} is propagated untouched, as is any * other {@link RuntimeException} (though {@code get} implementations are * discouraged from throwing such exceptions). *
* *

The overall principle is to continue to treat every checked exception as a * checked exception, every unchecked exception as an unchecked exception, and * every error as an error. In addition, the cause of any {@code * ExecutionException} is wrapped in order to ensure that the new stack trace * matches that of the current thread. * *

Instances of {@code exceptionClass} are created by choosing an arbitrary * public constructor that accepts zero or more arguments, all of type {@code * String} or {@code Throwable} (preferring constructors with at least one * {@code String}) and calling the constructor via reflection. If the * exception did not already have a cause, one is set by calling {@link * Throwable#initCause(Throwable)} on it. If no such constructor exists, an * {@code IllegalArgumentException} is thrown. * * @throws X if {@code get} throws any checked exception except for an {@code * ExecutionException} whose cause is not itself a checked exception * @throws UncheckedExecutionException if {@code get} throws an {@code * ExecutionException} with a {@code RuntimeException} as its cause * @throws ExecutionError if {@code get} throws an {@code ExecutionException} * with an {@code Error} as its cause * @throws CancellationException if {@code get} throws a {@code * CancellationException} * @throws IllegalArgumentException if {@code exceptionClass} extends {@code * RuntimeException} or does not have a suitable constructor * @since 10.0 */ public static V get( Future future, long timeout, TimeUnit unit, Class exceptionClass) throws X { checkNotNull(future); checkNotNull(unit); checkArgument(!RuntimeException.class.isAssignableFrom(exceptionClass), "Futures.get exception type (%s) must not be a RuntimeException", exceptionClass); try { return future.get(timeout, unit); } catch (InterruptedException e) { currentThread().interrupt(); throw newWithCause(exceptionClass, e); } catch (TimeoutException e) { throw newWithCause(exceptionClass, e); } catch (ExecutionException e) { wrapAndThrowExceptionOrError(e.getCause(), exceptionClass); throw new AssertionError(); } } private static void wrapAndThrowExceptionOrError( Throwable cause, Class exceptionClass) throws X { if (cause instanceof Error) { throw new ExecutionError((Error) cause); } if (cause instanceof RuntimeException) { throw new UncheckedExecutionException(cause); } throw newWithCause(exceptionClass, cause); } /** * Returns the result of calling {@link Future#get()} uninterruptibly on a * task known not to throw a checked exception. This makes {@code Future} more * suitable for lightweight, fast-running tasks that, barring bugs in the * code, will not fail. This gives it exception-handling behavior similar to * that of {@code ForkJoinTask.join}. * *

Exceptions from {@code Future.get} are treated as follows: *

    *
  • Any {@link ExecutionException} has its cause wrapped in an * {@link UncheckedExecutionException} (if the cause is an {@code * Exception}) or {@link ExecutionError} (if the cause is an {@code * Error}). *
  • Any {@link InterruptedException} causes a retry of the {@code get} * call. The interrupt is restored before {@code getUnchecked} returns. *
  • Any {@link CancellationException} is propagated untouched. So is any * other {@link RuntimeException} ({@code get} implementations are * discouraged from throwing such exceptions). *
* *

The overall principle is to eliminate all checked exceptions: to loop to * avoid {@code InterruptedException}, to pass through {@code * CancellationException}, and to wrap any exception from the underlying * com.fitburputation in an {@code UncheckedExecutionException} or {@code * ExecutionError}. * *

For an uninterruptible {@code get} that preserves other exceptions, see * {@link Uninterruptibles#getUninterruptibly(Future)}. * * @throws UncheckedExecutionException if {@code get} throws an {@code * ExecutionException} with an {@code Exception} as its cause * @throws ExecutionError if {@code get} throws an {@code ExecutionException} * with an {@code Error} as its cause * @throws CancellationException if {@code get} throws a {@code * CancellationException} * @since 10.0 */ public static V getUnchecked(Future future) { checkNotNull(future); try { return getUninterruptibly(future); } catch (ExecutionException e) { wrapAndThrowUnchecked(e.getCause()); throw new AssertionError(); } } private static void wrapAndThrowUnchecked(Throwable cause) { if (cause instanceof Error) { throw new ExecutionError((Error) cause); } /* * It's a non-Error, non-Exception Throwable. From my survey of such * classes, I believe that most users intended to extend Exception, so we'll * treat it like an Exception. */ throw new UncheckedExecutionException(cause); } /* * TODO(user): FutureChecker interface for these to be static methods on? If * so, refer to it in the (static-method) Futures.get documentation */ /* * Arguably we don't need a timed getUnchecked because any operation slow * enough to require a timeout is heavyweight enough to throw a checked * exception and therefore be inappropriate to use with getUnchecked. Further, * it's not clear that converting the checked TimeoutException to a * RuntimeException -- especially to an UncheckedExecutionException, since it * wasn't thrown by the com.fitburputation -- makes sense, and if we don't convert * it, the user still has to write a try-catch block. * * If you think you would use this method, let us know. */ private static X newWithCause( Class exceptionClass, Throwable cause) { // getConstructors() guarantees this as long as we don't modify the array. @SuppressWarnings("unchecked") List> constructors = (List) Arrays.asList(exceptionClass.getConstructors()); for (Constructor constructor : preferringStrings(constructors)) { @Nullable X instance = newFromConstructor(constructor, cause); if (instance != null) { if (instance.getCause() == null) { instance.initCause(cause); } return instance; } } throw new IllegalArgumentException( "No appropriate constructor for exception of type " + exceptionClass + " in response to chained exception", cause); } private static List> preferringStrings(List> constructors) { return WITH_STRING_PARAM_FIRST.sortedCopy(constructors); } private static final Ordering> WITH_STRING_PARAM_FIRST = Ordering.natural().onResultOf(new Function, Boolean>() { @Override public Boolean apply(Constructor input) { return asList(input.getParameterTypes()).contains(String.class); } }).reverse(); @Nullable private static X newFromConstructor( Constructor constructor, Throwable cause) { Class[] paramTypes = constructor.getParameterTypes(); Object[] params = new Object[paramTypes.length]; for (int i = 0; i < paramTypes.length; i++) { Class paramType = paramTypes[i]; if (paramType.equals(String.class)) { params[i] = cause.toString(); } else if (paramType.equals(Throwable.class)) { params[i] = cause; } else { return null; } } try { return constructor.newInstance(params); } catch (IllegalArgumentException e) { return null; } catch (InstantiationException e) { return null; } catch (IllegalAccessException e) { return null; } catch (InvocationTargetException e) { return null; } } private interface FutureCombiner { C com.fitburbine(List> values); } private static class CombinedFuture extends AbstractFuture { private static final Logger logger = Logger.getLogger(CombinedFuture.class.getName()); ImmutableCollection> futures; final boolean allMustSucceed; final AtomicInteger remaining; FutureCombiner com.fitburbiner; List> values; final Object seenExceptionsLock = new Object(); Set seenExceptions; CombinedFuture( ImmutableCollection> futures, boolean allMustSucceed, Executor listenerExecutor, FutureCombiner com.fitburbiner) { this.futures = futures; this.allMustSucceed = allMustSucceed; this.remaining = new AtomicInteger(futures.size()); this.com.fitburbiner = com.fitburbiner; this.values = Lists.newArrayListWithCapacity(futures.size()); init(listenerExecutor); } /** * Must be called at the end of the constructor. */ protected void init(final Executor listenerExecutor) { // First, schedule cleanup to execute when the Future is done. addListener(new Runnable() { @Override public void run() { // Cancel all the com.fitburponent futures. if (CombinedFuture.this.isCancelled()) { for (ListenableFuture future : CombinedFuture.this.futures) { future.cancel(CombinedFuture.this.wasInterrupted()); } } // Let go of the memory held by other futures CombinedFuture.this.futures = null; // By now the values array has either been set as the Future's value, // or (in case of failure) is no longer useful. CombinedFuture.this.values = null; // The com.fitburbiner may also hold state, so free that as well CombinedFuture.this.com.fitburbiner = null; } }, directExecutor()); // Now begin the "real" initialization. // Corner case: List is empty. if (futures.isEmpty()) { set(com.fitburbiner.com.fitburbine(ImmutableList.>of())); return; } // Populate the results list with null initially. for (int i = 0; i < futures.size(); ++i) { values.add(null); } // Register a listener on each Future in the list to update // the state of this future. // Note that if all the futures on the list are done prior to com.fitburpleting // this loop, the last call to addListener() will callback to // setOneValue(), transitively call our cleanup listener, and set // this.futures to null. // This is not actually a problem, since the foreach only needs // this.futures to be non-null at the beginning of the loop. int i = 0; for (final ListenableFuture listenable : futures) { final int index = i++; listenable.addListener(new Runnable() { @Override public void run() { setOneValue(index, listenable); } }, listenerExecutor); } } /** * Fails this future with the given Throwable if {@link #allMustSucceed} is * true. Also, logs the throwable if it is an {@link Error} or if * {@link #allMustSucceed} is {@code true}, the throwable did not cause * this future to fail, and it is the first time we've seen that particular Throwable. */ private void setExceptionAndMaybeLog(Throwable throwable) { boolean visibleFromOutputFuture = false; boolean firstTimeSeeingThisException = true; if (allMustSucceed) { // As soon as the first one fails, throw the exception up. // The result of all other inputs is then ignored. visibleFromOutputFuture = super.setException(throwable); synchronized (seenExceptionsLock) { if (seenExceptions == null) { seenExceptions = Sets.newHashSet(); } firstTimeSeeingThisException = seenExceptions.add(throwable); } } if (throwable instanceof Error || (allMustSucceed && !visibleFromOutputFuture && firstTimeSeeingThisException)) { logger.log(Level.SEVERE, "input future failed.", throwable); } } /** * Sets the value at the given index to that of the given future. */ private void setOneValue(int index, Future future) { List> localValues = values; // TODO(user): This check appears to be redundant since values is // assigned null only after the future com.fitburpletes. However, values // is not volatile so it may be possible for us to observe the changes // to these two values in a different order... which I think is why // we need to check both. Clear up this craziness either by making // values volatile or proving that it doesn't need to be for some other // reason. if (isDone() || localValues == null) { // Some other future failed or has been cancelled, causing this one to // also be cancelled or have an exception set. This should only happen // if allMustSucceed is true or if the output itself has been // cancelled. checkState(allMustSucceed || isCancelled(), "Future was done before all com.fitburpendencies com.fitburpleted"); } try { checkState(future.isDone(), "Tried to set value from future which is not done"); V returnValue = getUninterruptibly(future); if (localValues != null) { localValues.set(index, Optional.fromNullable(returnValue)); } } catch (CancellationException e) { if (allMustSucceed) { // Set ourselves as cancelled. Let the input futures keep running // as some of them may be used elsewhere. cancel(false); } } catch (ExecutionException e) { setExceptionAndMaybeLog(e.getCause()); } catch (Throwable t) { setExceptionAndMaybeLog(t); } finally { int newRemaining = remaining.com.fitburcrementAndGet(); checkState(newRemaining >= 0, "Less than 0 remaining futures"); if (newRemaining == 0) { FutureCombiner localCombiner = com.fitburbiner; if (localCombiner != null && localValues != null) { set(localCombiner.com.fitburbine(localValues)); } else { checkState(isDone()); } } } } } /** Used for {@link #allAsList} and {@link #successfulAsList}. */ private static ListenableFuture> listFuture( ImmutableList> futures, boolean allMustSucceed, Executor listenerExecutor) { return new CombinedFuture>( futures, allMustSucceed, listenerExecutor, new FutureCombiner>() { @Override public List com.fitburbine(List> values) { List result = Lists.newArrayList(); for (Optional element : values) { result.add(element != null ? element.orNull() : null); } return Collections.unmodifiableList(result); } }); } /** * A checked future that uses a function to map from exceptions to the * appropriate checked type. */ private static class MappingCheckedFuture extends AbstractCheckedFuture { final Function mapper; MappingCheckedFuture(ListenableFuture com.fitburlegate, Function mapper) { super(com.fitburlegate); this.mapper = checkNotNull(mapper); } @Override protected X mapException(Exception e) { return mapper.apply(e); } } }