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

org.docx4j.com.google.common.util.concurrent.Futures Maven / Gradle / Ivy

Go to download

docx4j is a library which helps you to work with the Office Open XML file format as used in docx documents, pptx presentations, and xlsx spreadsheets.

There is a newer version: 11.4.11
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 compliance with the License. You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software distributed under the License
 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
 * or implied. See the License for the specific language governing permissions and limitations under
 * the License.
 */

package org.docx4j.com.google.common.util.concurrent;

import com.google.errorprone.annotations.CanIgnoreReturnValue;

import static org.docx4j.com.google.common.base.Preconditions.checkNotNull;
import static org.docx4j.com.google.common.base.Preconditions.checkState;
import static org.docx4j.com.google.common.util.concurrent.MoreExecutors.directExecutor;
import static org.docx4j.com.google.common.util.concurrent.Uninterruptibles.getUninterruptibly;

import java.util.Collection;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.CancellationException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executor;
import java.util.concurrent.Future;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicInteger;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.docx4j.com.google.common.annotations.Beta;
import org.docx4j.com.google.common.annotations.GwtCompatible;
import org.docx4j.com.google.common.annotations.GwtIncompatible;
import org.docx4j.com.google.common.base.Function;
import org.docx4j.com.google.common.base.MoreObjects;
import org.docx4j.com.google.common.base.Preconditions;
import org.docx4j.com.google.common.util.concurrent.ImmediateFuture.ImmediateFailedFuture;
import org.docx4j.com.google.common.util.concurrent.ImmediateFuture.ImmediateSuccessfulFuture;

/**
 * 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}. * *

The main purpose of {@code ListenableFuture} is to help you chain together a graph of * asynchronous operations. You can chain them together manually with calls to methods like {@link * Futures#transform(ListenableFuture, Function, Executor) Futures.transform}, but you will often * find it easier to use a framework. Frameworks automate the process, often adding features like * monitoring, debugging, and cancellation. Examples of frameworks include: * *

* *

If you do chain your operations manually, you may want to use {@link FluentFuture}. * * @author Kevin Bourrillion * @author Nishant Thakkar * @author Sven Mawson * @since 1.0 */ @GwtCompatible(emulated = true) public final class Futures extends GwtFuturesCatchingSpecialization { // A note on memory visibility. // Many of the utilities in this class (transform, withFallback, withTimeout, asList, combine) // have two requirements that significantly complicate their design. // 1. Cancellation should propagate from the returned future to the input future(s). // 2. The returned futures shouldn't unnecessarily 'pin' their inputs after completion. // // A consequence of these requirements is that the delegate futures cannot be stored in // final fields. // // For simplicity the rest of this description will discuss Futures.catching since it is the // simplest instance, though very similar descriptions apply to many other classes in this file. // // In the constructor of AbstractCatchingFuture, the delegate future is assigned to a field // 'inputFuture'. That field is non-final and non-volatile. There are 2 places where the // 'inputFuture' field is read and where we will have to consider visibility of the write // operation in the constructor. // // 1. In the listener that performs the callback. In this case it is fine since inputFuture is // assigned prior to calling addListener, and addListener happens-before any invocation of the // listener. Notably, this means that 'volatile' is unnecessary to make 'inputFuture' visible // to the listener. // // 2. In done() where we may propagate cancellation to the input. In this case it is _not_ fine. // There is currently nothing that enforces that the write to inputFuture in the constructor is // visible to done(). This is because there is no happens before edge between the write and a // (hypothetical) unsafe read by our caller. Note: adding 'volatile' does not fix this issue, // it would just add an edge such that if done() observed non-null, then it would also // definitely observe all earlier writes, but we still have no guarantee that done() would see // the inital write (just stronger guarantees if it does). // // See: http://cs.oswego.edu/pipermail/concurrency-interest/2015-January/013800.html // For a (long) discussion about this specific issue and the general futility of life. // // For the time being we are OK with the problem discussed above since it requires a caller to // introduce a very specific kind of data-race. And given the other operations performed by these // methods that involve volatile read/write operations, in practice there is no issue. Also, the // way in such a visibility issue would surface is most likely as a failure of cancel() to // propagate to the input. Cancellation propagation is fundamentally racy so this is fine. // // Future versions of the JMM may revise safe construction semantics in such a way that we can // safely publish these objects and we won't need this whole discussion. // TODO(user,lukes): consider adding volatile to all these fields since in current known JVMs // that should resolve the issue. This comes at the cost of adding more write barriers to the // implementations. 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. // * // *

Warning: We recommend against using {@code CheckedFuture} in new projects. {@code // * CheckedFuture} is difficult to build libraries atop. {@code CheckedFuture} ports of methods // * like {@link Futures#transformAsync} have historically had bugs, and some of these bugs are // * necessary, unavoidable consequences of the {@code CheckedFuture} API. Additionally, {@code // * CheckedFuture} encourages users to take exceptions from one thread and rethrow them in another, // * producing confusing stack traces. // * // *

The given mapping function will be applied to an {@link InterruptedException}, a {@link // * CancellationException}, or an {@link ExecutionException}. See {@link Future#get()} for details // * on the exceptions thrown. // * // * @since 9.0 (source-compatible since 1.0) // * @deprecated {@link CheckedFuture} cannot properly support the chained operations that are the // * primary goal of {@link ListenableFuture}. {@code CheckedFuture} also encourages users to // * rethrow exceptions from one thread in another thread, producing misleading stack traces. // * Additionally, it has a surprising policy about which exceptions to map and which to leave // * untouched. Guava users who want a {@code CheckedFuture} can fork the classes for their own // * use, possibly specializing them to the particular exception type they use. We recommend // * that most people use {@code ListenableFuture} and perform any exception wrapping // * themselves. This method is scheduled for removal from Guava in January 2019. // */ // // TODO(b/72241575): Remove by 2019-01 // @Beta // @Deprecated // @GwtIncompatible // TODO // public static CheckedFuture makeChecked( // ListenableFuture future, Function mapper) { // return new MappingCheckedFuture<>(checkNotNull(future), mapper); // } // /** * 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) { if (value == null) { // This cast is safe because null is assignable to V for all V (i.e. it is covariant) @SuppressWarnings({"unchecked", "rawtypes"}) ListenableFuture typedNull = (ListenableFuture) ImmediateSuccessfulFuture.NULL; return typedNull; } 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. // * // * @deprecated {@link CheckedFuture} cannot properly support the chained operations that are the // * primary goal of {@link ListenableFuture}. {@code CheckedFuture} also encourages users to // * rethrow exceptions from one thread in another thread, producing misleading stack traces. // * Additionally, it has a surprising policy about which exceptions to map and which to leave // * untouched. Guava users who want a {@code CheckedFuture} can fork the classes for their own // * use, possibly specializing them to the particular exception type they use. We recommend // * that most people use {@code ListenableFuture} and perform any exception wrapping // * themselves. This method is scheduled for removal from Guava in January 2019. // */ // // TODO(b/72241893): Remove by 2019-01 // @Beta // @Deprecated // @GwtIncompatible // TODO // 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. // * // * @deprecated {@link CheckedFuture} cannot properly support the chained operations that are the // * primary goal of {@link ListenableFuture}. {@code CheckedFuture} also encourages users to // * rethrow exceptions from one thread in another thread, producing misleading stack traces. // * Additionally, it has a surprising policy about which exceptions to map and which to leave // * untouched. Guava users who want a {@code CheckedFuture} can fork the classes for their own // * use, possibly specializing them to the particular exception type they use. We recommend // * that most people use {@code ListenableFuture} and perform any exception wrapping // * themselves. This method is scheduled for removal from Guava in January 2019. // */ // // TODO(b/72241500): Remove by 2019-01 // @Beta // @Deprecated // @GwtIncompatible // TODO // public static CheckedFuture immediateFailedCheckedFuture( // X exception) { // checkNotNull(exception); // return new ImmediateFailedCheckedFuture<>(exception); // } // // /** // * Executes {@code callable} on the specified {@code executor}, returning a {@code Future}. // * // * @throws RejectedExecutionException if the task cannot be scheduled for execution // * @since 23.0 // */ // @Beta // public static ListenableFuture submitAsync(AsyncCallable callable, Executor executor) { // TrustedListenableFutureTask task = TrustedListenableFutureTask.create(callable); // executor.execute(task); // return task; // } // // /** // * Schedules {@code callable} on the specified {@code executor}, returning a {@code Future}. // * // * @throws RejectedExecutionException if the task cannot be scheduled for execution // * @since 23.0 // */ // @Beta // @GwtIncompatible // java.util.concurrent.ScheduledExecutorService // @SuppressWarnings("GoodTime") // should accept a java.time.Duration // public static ListenableFuture scheduleAsync( // AsyncCallable callable, // long delay, // TimeUnit timeUnit, // ScheduledExecutorService executorService) { // TrustedListenableFutureTask task = TrustedListenableFutureTask.create(callable); // final Future scheduled = executorService.schedule(task, delay, timeUnit); // task.addListener( // new Runnable() { // @Override // public void run() { // // Don't want to interrupt twice // scheduled.cancel(false); // } // }, // directExecutor()); // return task; // } // // /** // * Returns a {@code Future} whose result is taken from the given primary {@code input} or, if the // * primary input fails with the given {@code exceptionType}, from the result provided by the // * {@code fallback}. {@link Function#apply} 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}. // * // *

Usage example: // * // *

{@code
//   * ListenableFuture fetchCounterFuture = ...;
//   *
//   * // Falling back to a zero counter in case an exception happens when
//   * // processing the RPC to fetch counters.
//   * ListenableFuture faultTolerantFuture = Futures.catching(
//   *     fetchCounterFuture, FetchException.class, x -> 0, directExecutor());
//   * }
// * // *

When selecting an executor, note that {@code directExecutor} is dangerous in some cases. See // * the discussion in the {@link ListenableFuture#addListener ListenableFuture.addListener} // * documentation. All its warnings about heavyweight listeners are also applicable to heavyweight // * functions passed to this method. // * // * @param input the primary input {@code Future} // * @param exceptionType the exception type that triggers use of {@code fallback}. The exception // * type is matched against the input's exception. "The input's exception" means the cause of // * the {@link ExecutionException} thrown by {@code input.get()} or, if {@code get()} throws a // * different kind of exception, that exception itself. To avoid hiding bugs and other // * unrecoverable errors, callers should prefer more specific types, avoiding {@code // * Throwable.class} in particular. // * @param fallback the {@link Function} to be called if {@code input} fails with the expected // * exception type. The function's argument is the input's exception. "The input's exception" // * means the cause of the {@link ExecutionException} thrown by {@code input.get()} or, if // * {@code get()} throws a different kind of exception, that exception itself. // * @param executor the executor that runs {@code fallback} if {@code input} fails // * @since 19.0 // */ // @Beta // @Partially.GwtIncompatible("AVAILABLE but requires exceptionType to be Throwable.class") // public static ListenableFuture catching( // ListenableFuture input, // Class exceptionType, // Function fallback, // Executor executor) { // return AbstractCatchingFuture.create(input, exceptionType, fallback, executor); // } // // /** // * Returns a {@code Future} whose result is taken from the given primary {@code input} or, if the // * primary input fails with the given {@code exceptionType}, from the result provided by the // * {@code fallback}. {@link AsyncFunction#apply} 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}. // * // *

Usage examples: // * // *

{@code
//   * ListenableFuture fetchCounterFuture = ...;
//   *
//   * // Falling back to a zero counter in case an exception happens when
//   * // processing the RPC to fetch counters.
//   * ListenableFuture faultTolerantFuture = Futures.catchingAsync(
//   *     fetchCounterFuture, FetchException.class, x -> immediateFuture(0), directExecutor());
//   * }
// * // *

The fallback can also choose to propagate the original exception when desired: // * // *

{@code
//   * ListenableFuture fetchCounterFuture = ...;
//   *
//   * // Falling back to a zero counter only in case the exception was a
//   * // TimeoutException.
//   * ListenableFuture faultTolerantFuture = Futures.catchingAsync(
//   *     fetchCounterFuture,
//   *     FetchException.class,
//   *     e -> {
//   *       if (omitDataOnFetchFailure) {
//   *         return immediateFuture(0);
//   *       }
//   *       throw e;
//   *     },
//   *     directExecutor());
//   * }
// * // *

When selecting an executor, note that {@code directExecutor} is dangerous in some cases. See // * the discussion in the {@link ListenableFuture#addListener ListenableFuture.addListener} // * documentation. All its warnings about heavyweight listeners are also applicable to heavyweight // * functions passed to this method. (Specifically, {@code directExecutor} functions should avoid // * heavyweight operations inside {@code AsyncFunction.apply}. Any heavyweight operations should // * occur in other threads responsible for completing the returned {@code Future}.) // * // * @param input the primary input {@code Future} // * @param exceptionType the exception type that triggers use of {@code fallback}. The exception // * type is matched against the input's exception. "The input's exception" means the cause of // * the {@link ExecutionException} thrown by {@code input.get()} or, if {@code get()} throws a // * different kind of exception, that exception itself. To avoid hiding bugs and other // * unrecoverable errors, callers should prefer more specific types, avoiding {@code // * Throwable.class} in particular. // * @param fallback the {@link AsyncFunction} to be called if {@code input} fails with the expected // * exception type. The function's argument is the input's exception. "The input's exception" // * means the cause of the {@link ExecutionException} thrown by {@code input.get()} or, if // * {@code get()} throws a different kind of exception, that exception itself. // * @param executor the executor that runs {@code fallback} if {@code input} fails // * @since 19.0 (similar functionality in 14.0 as {@code withFallback}) // */ // @Beta // @Partially.GwtIncompatible("AVAILABLE but requires exceptionType to be Throwable.class") // public static ListenableFuture catchingAsync( // ListenableFuture input, // Class exceptionType, // AsyncFunction fallback, // Executor executor) { // return AbstractCatchingFuture.create(input, exceptionType, fallback, executor); // } // /** * Returns a future that delegates to another but will finish early (via a {@link * TimeoutException} wrapped in an {@link ExecutionException}) if the specified duration expires. * *

The delegate future is interrupted and cancelled if it times out. * * @param delegate The future to delegate to. * @param time when to timeout the future * @param unit the time unit of the time parameter * @param scheduledExecutor The executor service to enforce the timeout. * @since 19.0 */ @Beta @GwtIncompatible // java.util.concurrent.ScheduledExecutorService @SuppressWarnings("GoodTime") // should accept a java.time.Duration public static ListenableFuture withTimeout( ListenableFuture delegate, long time, TimeUnit unit, ScheduledExecutorService scheduledExecutor) { if (delegate.isDone()) { return delegate; } return TimeoutFuture.create(delegate, time, unit, scheduledExecutor); } // // /** // * Returns a new {@code Future} whose result is asynchronously derived from the result of the // * given {@code Future}. If the given {@code Future} fails, the returned {@code Future} fails with // * the same exception (and the function is not invoked). // * // *

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 usage: // * // *

{@code
//   * ListenableFuture rowKeyFuture = indexService.lookUp(query);
//   * ListenableFuture queryFuture =
//   *     transformAsync(rowKeyFuture, dataService::readFuture, executor);
//   * }
// * // *

When selecting an executor, note that {@code directExecutor} is dangerous in some cases. See // * the discussion in the {@link ListenableFuture#addListener ListenableFuture.addListener} // * documentation. All its warnings about heavyweight listeners are also applicable to heavyweight // * functions passed to this method. (Specifically, {@code directExecutor} functions should avoid // * heavyweight operations inside {@code AsyncFunction.apply}. Any heavyweight operations should // * occur in other threads responsible for completing the returned {@code Future}.) // * // *

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. // * // * @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 19.0 (in 11.0 as {@code transform}) // */ // @Beta // public static ListenableFuture transformAsync( // ListenableFuture input, // AsyncFunction function, // Executor executor) { // return AbstractTransformFuture.create(input, function, executor); // } // /** * Returns a new {@code Future} whose result is derived from the result of the given {@code * Future}. If {@code input} fails, the returned {@code Future} fails with the same exception (and * the function is not invoked). Example usage: * *

{@code
   * ListenableFuture queryFuture = ...;
   * ListenableFuture> rowsFuture =
   *     transform(queryFuture, QueryResult::getRows, executor);
   * }
* *

When selecting an executor, note that {@code directExecutor} is dangerous in some cases. See * the discussion in the {@link ListenableFuture#addListener ListenableFuture.addListener} * documentation. All its warnings about heavyweight listeners are also applicable to heavyweight * functions passed to this method. * *

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. * @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 compose}) */ @Beta public static ListenableFuture transform( ListenableFuture input, Function function, Executor executor) { return AbstractTransformFuture.create(input, function, executor); } // // /** // * Like {@link #transform(ListenableFuture, Function, Executor)} 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 // */ // @Beta // @GwtIncompatible // TODO // 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); // } // } // }; // } // // /** // * Creates a new {@code ListenableFuture} whose value is a list containing the values of all its // * input futures, if all succeed. // * // *

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

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

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

Canceling this future will attempt to cancel all the component futures, and if any of the // * provided futures fails or is canceled, this one is, too. // * // * @param futures futures to combine // * @return a future that provides a list of the results of the component futures // * @since 10.0 // */ // @Beta // public static ListenableFuture> allAsList( // Iterable> futures) { // return new ListFuture(ImmutableList.copyOf(futures), true); // } // // /** // * Creates a {@link FutureCombiner} that processes the completed futures whether or not they're // * successful. // * // * @since 20.0 // */ // @Beta // @SafeVarargs // public static FutureCombiner whenAllComplete(ListenableFuture... futures) { // return new FutureCombiner(false, ImmutableList.copyOf(futures)); // } // // /** // * Creates a {@link FutureCombiner} that processes the completed futures whether or not they're // * successful. // * // * @since 20.0 // */ // @Beta // public static FutureCombiner whenAllComplete( // Iterable> futures) { // return new FutureCombiner(false, ImmutableList.copyOf(futures)); // } // // /** // * Creates a {@link FutureCombiner} requiring that all passed in futures are successful. // * // *

If any input fails, the returned future fails immediately. // * // * @since 20.0 // */ // @Beta // @SafeVarargs // public static FutureCombiner whenAllSucceed(ListenableFuture... futures) { // return new FutureCombiner(true, ImmutableList.copyOf(futures)); // } // // /** // * Creates a {@link FutureCombiner} requiring that all passed in futures are successful. // * // *

If any input fails, the returned future fails immediately. // * // * @since 20.0 // */ // @Beta // public static FutureCombiner whenAllSucceed( // Iterable> futures) { // return new FutureCombiner(true, ImmutableList.copyOf(futures)); // } // // /** // * A helper to create a new {@code ListenableFuture} whose result is generated from a combination // * of input futures. // * // *

See {@link #whenAllComplete} and {@link #whenAllSucceed} for how to instantiate this class. // * // *

Example: // * // *

{@code
//   * final ListenableFuture loginDateFuture =
//   *     loginService.findLastLoginDate(username);
//   * final ListenableFuture> recentCommandsFuture =
//   *     recentCommandsService.findRecentCommands(username);
//   * ListenableFuture usageFuture =
//   *     Futures.whenAllSucceed(loginDateFuture, recentCommandsFuture)
//   *         .call(
//   *             () ->
//   *                 new UsageHistory(
//   *                     username,
//   *                     Futures.getDone(loginDateFuture),
//   *                     Futures.getDone(recentCommandsFuture)),
//   *             executor);
//   * }
// * // * @since 20.0 // */ // @Beta // @CanIgnoreReturnValue // TODO(cpovirk): Consider removing, especially if we provide run(Runnable) // @GwtCompatible // public static final class FutureCombiner { // private final boolean allMustSucceed; // private final ImmutableList> futures; // // private FutureCombiner( // boolean allMustSucceed, ImmutableList> futures) { // this.allMustSucceed = allMustSucceed; // this.futures = futures; // } // // /** // * Creates the {@link ListenableFuture} which will return the result of calling {@link // * AsyncCallable#call} in {@code combiner} when all futures complete, using the specified {@code // * executor}. // * // *

If the combiner throws a {@code CancellationException}, the returned future will be // * cancelled. // * // *

If the combiner throws an {@code ExecutionException}, the cause of the thrown {@code // * ExecutionException} will be extracted and returned as the cause of the new {@code // * ExecutionException} that gets thrown by the returned combined future. // * // *

Canceling this future will attempt to cancel all the component futures. // */ // public ListenableFuture callAsync(AsyncCallable combiner, Executor executor) { // return new CombinedFuture(futures, allMustSucceed, executor, combiner); // } // // /** // * Creates the {@link ListenableFuture} which will return the result of calling {@link // * Callable#call} in {@code combiner} when all futures complete, using the specified {@code // * executor}. // * // *

If the combiner throws a {@code CancellationException}, the returned future will be // * cancelled. // * // *

If the combiner throws an {@code ExecutionException}, the cause of the thrown {@code // * ExecutionException} will be extracted and returned as the cause of the new {@code // * ExecutionException} that gets thrown by the returned combined future. // * // *

Canceling this future will attempt to cancel all the component futures. // */ // @CanIgnoreReturnValue // TODO(cpovirk): Remove this // public ListenableFuture call(Callable combiner, Executor executor) { // return new CombinedFuture(futures, allMustSucceed, executor, combiner); // } // // /** // * Creates the {@link ListenableFuture} which will return the result of running {@code combiner} // * when all Futures complete. {@code combiner} will run using {@code executor}. // * // *

If the combiner throws a {@code CancellationException}, the returned future will be // * cancelled. // * // *

Canceling this Future will attempt to cancel all the component futures. // * // * @since 23.6 // */ // public ListenableFuture run(final Runnable combiner, Executor executor) { // return call( // new Callable() { // @Override // public Void call() throws Exception { // combiner.run(); // return null; // } // }, // executor); // } // } // // /** // * Returns a {@code ListenableFuture} whose result is set from the supplied future when it // * completes. 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 // */ // @Beta // public static ListenableFuture nonCancellationPropagating(ListenableFuture future) { // if (future.isDone()) { // return future; // } // NonCancellationPropagatingFuture output = new NonCancellationPropagatingFuture<>(future); // future.addListener(output, directExecutor()); // return output; // } // // /** A wrapped future that does not propagate cancellation to its delegate. */ // private static final class NonCancellationPropagatingFuture // extends AbstractFuture.TrustedFuture implements Runnable { // private ListenableFuture delegate; // // NonCancellationPropagatingFuture(final ListenableFuture delegate) { // this.delegate = delegate; // } // // @Override // public void run() { // // This prevents cancellation from propagating because we don't call setFuture(delegate) until // // delegate is already done, so calling cancel() on this future won't affect it. // ListenableFuture localDelegate = delegate; // if (localDelegate != null) { // setFuture(localDelegate); // } // } // // @Override // protected String pendingToString() { // ListenableFuture localDelegate = delegate; // if (localDelegate != null) { // return "delegate=[" + localDelegate + "]"; // } // return null; // } // // @Override // protected void afterDone() { // delegate = null; // } // } // // /** // * 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 component futures. // * // * @param futures futures to combine // * @return a future that provides a list of the results of the component futures // * @since 10.0 // */ // @Beta // @SafeVarargs // public static ListenableFuture> successfulAsList( // ListenableFuture... futures) { // return new ListFuture(ImmutableList.copyOf(futures), false); // } // // /** // * 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 component futures. // * // * @param futures futures to combine // * @return a future that provides a list of the results of the component futures // * @since 10.0 // */ // @Beta // public static ListenableFuture> successfulAsList( // Iterable> futures) { // return new ListFuture(ImmutableList.copyOf(futures), false); // } // // /** // * Returns a list of delegate futures that correspond to the futures received in the order that // * they complete. Delegate futures return the same value or throw the same exception as the // * corresponding input future returns/throws. // * // *

"In the order that they complete" means, for practical purposes, about what you would // * expect, but there are some subtleties. First, we do guarantee that, if the output future at // * index n is done, the output future at index n-1 is also done. (But as usual with futures, some // * listeners for future n may complete before some for future n-1.) However, it is possible, if // * one input completes with result X and another later with result Y, for Y to come before X in // * the output future list. (Such races are impossible to solve without global synchronization of // * all future completions. And they should have little practical impact.) // * // *

Cancelling a delegate future propagates to input futures once all the delegates complete, // * either from cancellation or because an input future has completed. If N futures are passed in, // * and M delegates are cancelled, the remaining M input futures will be cancelled once N - M of // * the input futures complete. If all the delegates are cancelled, all the input futures will be // * too. // * // * @since 17.0 // */ // @Beta // public static ImmutableList> inCompletionOrder( // Iterable> futures) { // // Can't use Iterables.toArray because it's not gwt compatible // final Collection> collection; // if (futures instanceof Collection) { // collection = (Collection>) futures; // } else { // collection = ImmutableList.copyOf(futures); // } // @SuppressWarnings("unchecked") // ListenableFuture[] copy = // (ListenableFuture[]) // collection.toArray(new ListenableFuture[collection.size()]); // final InCompletionOrderState state = new InCompletionOrderState<>(copy); // ImmutableList.Builder> delegatesBuilder = ImmutableList.builder(); // for (int i = 0; i < copy.length; i++) { // delegatesBuilder.add(new InCompletionOrderFuture(state)); // } // // final ImmutableList> delegates = delegatesBuilder.build(); // for (int i = 0; i < copy.length; i++) { // final int localI = i; // copy[i].addListener( // new Runnable() { // @Override // public void run() { // state.recordInputCompletion(delegates, localI); // } // }, // directExecutor()); // } // // @SuppressWarnings("unchecked") // ImmutableList> delegatesCast = (ImmutableList) delegates; // return delegatesCast; // } // // // This can't be a TrustedFuture, because TrustedFuture has clever optimizations that // // mean cancel won't be called if this Future is passed into setFuture, and then // // cancelled. // private static final class InCompletionOrderFuture extends AbstractFuture { // private InCompletionOrderState state; // // private InCompletionOrderFuture(InCompletionOrderState state) { // this.state = state; // } // // @Override // public boolean cancel(boolean interruptIfRunning) { // InCompletionOrderState localState = state; // if (super.cancel(interruptIfRunning)) { // localState.recordOutputCancellation(interruptIfRunning); // return true; // } // return false; // } // // @Override // protected void afterDone() { // state = null; // } // // @Override // protected String pendingToString() { // InCompletionOrderState localState = state; // if (localState != null) { // // Don't print the actual array! We don't want inCompletionOrder(list).toString() to have // // quadratic output. // return "inputCount=[" // + localState.inputFutures.length // + "], remaining=[" // + localState.incompleteOutputCount.get() // + "]"; // } // return null; // } // } // // private static final class InCompletionOrderState { // // A happens-before edge between the writes of these fields and their reads exists, because // // in order to read these fields, the corresponding write to incompleteOutputCount must have // // been read. // private boolean wasCancelled = false; // private boolean shouldInterrupt = true; // private final AtomicInteger incompleteOutputCount; // private final ListenableFuture[] inputFutures; // private volatile int delegateIndex = 0; // // private InCompletionOrderState(ListenableFuture[] inputFutures) { // this.inputFutures = inputFutures; // incompleteOutputCount = new AtomicInteger(inputFutures.length); // } // // private void recordOutputCancellation(boolean interruptIfRunning) { // wasCancelled = true; // // If all the futures were cancelled with interruption, cancel the input futures // // with interruption; otherwise cancel without // if (!interruptIfRunning) { // shouldInterrupt = false; // } // recordCompletion(); // } // // private void recordInputCompletion( // ImmutableList> delegates, int inputFutureIndex) { // ListenableFuture inputFuture = inputFutures[inputFutureIndex]; // // Null out our reference to this future, so it can be GCed // inputFutures[inputFutureIndex] = null; // for (int i = delegateIndex; i < delegates.size(); i++) { // if (delegates.get(i).setFuture(inputFuture)) { // recordCompletion(); // // this is technically unnecessary, but should speed up later accesses // delegateIndex = i + 1; // return; // } // } // // If all the delegates were complete, no reason for the next listener to have to // // go through the whole list. Avoids O(n^2) behavior when the entire output list is // // cancelled. // delegateIndex = delegates.size(); // } // // private void recordCompletion() { // if (incompleteOutputCount.decrementAndGet() == 0 && wasCancelled) { // for (ListenableFuture toCancel : inputFutures) { // if (toCancel != null) { // toCancel.cancel(shouldInterrupt); // } // } // } // } // } // // /** // * Registers separate success and failure callbacks to be run when the {@code Future}'s // * computation is {@linkplain java.util.concurrent.Future#isDone() complete} or, if the // * computation is already complete, immediately. // * // *

The callback is run on {@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 // * computation is complete. // * // *

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 selecting an executor, note that {@code directExecutor} is dangerous in some cases. See // * the discussion in the {@link ListenableFuture#addListener ListenableFuture.addListener} // * documentation. All its warnings about heavyweight listeners are also applicable to heavyweight // * callbacks passed to this method. // * // *

For a more general interface to attach a completion 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 completed. // * @param executor The executor to run {@code callback} when the future completes. // * @since 10.0 // */ // public static void addCallback( // final ListenableFuture future, // final FutureCallback callback, // Executor executor) { // Preconditions.checkNotNull(callback); // future.addListener(new CallbackListener(future, callback), executor); // } // // /** See {@link #addCallback(ListenableFuture, FutureCallback, Executor)} for behavioral notes. */ // private static final class CallbackListener implements Runnable { // final Future future; // final FutureCallback callback; // // CallbackListener(Future future, FutureCallback callback) { // this.future = future; // this.callback = callback; // } // // @Override // public void run() { // final V value; // try { // value = getDone(future); // } catch (ExecutionException e) { // callback.onFailure(e.getCause()); // return; // } catch (RuntimeException | Error e) { // callback.onFailure(e); // return; // } // callback.onSuccess(value); // } // // @Override // public String toString() { // return MoreObjects.toStringHelper(this).addValue(callback).toString(); // } // } // /** * Returns the result of the input {@code Future}, which must have already completed. * *

The benefits of this method are twofold. First, the name "getDone" suggests to readers that * the {@code Future} is already done. Second, if buggy code calls {@code getDone} on a {@code * Future} that is still pending, the program will throw instead of block. This can be important * for APIs like {@link #whenAllComplete whenAllComplete(...)}{@code .}{@link * FutureCombiner#call(Callable, Executor) call(...)}, where it is easy to use a new input from * the {@code call} implementation but forget to add it to the arguments of {@code * whenAllComplete}. * *

If you are looking for a method to determine whether a given {@code Future} is done, use the * instance method {@link Future#isDone()}. * * @throws ExecutionException if the {@code Future} failed with an exception * @throws CancellationException if the {@code Future} was cancelled * @throws IllegalStateException if the {@code Future} is not done * @since 20.0 */ @CanIgnoreReturnValue // TODO(cpovirk): Consider calling getDone() in our own code. public static V getDone(Future future) throws ExecutionException { /* * We throw IllegalStateException, since the call could succeed later. Perhaps we "should" throw * IllegalArgumentException, since the call could succeed with a different argument. Those * exceptions' docs suggest that either is acceptable. Google's Java Practices page recommends * IllegalArgumentException here, in part to keep its recommendation simple: Static methods * should throw IllegalStateException only when they use static state. * * * Why do we deviate here? The answer: We want for fluentFuture.getDone() to throw the same * exception as Futures.getDone(fluentFuture). */ checkState(future.isDone(), "Future was expected to be done: %s", future); return getUninterruptibly(future); } // // /** // * 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 common 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 19.0 (in 10.0 as {@code get}) // */ // @Beta // @CanIgnoreReturnValue // @GwtIncompatible // reflection // public static V getChecked(Future future, Class exceptionClass) // throws X { // return FuturesGetChecked.getChecked(future, exceptionClass); // } // // /** // * 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 common 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 19.0 (in 10.0 as {@code get} and with different parameter order) // */ // @Beta // @CanIgnoreReturnValue // @GwtIncompatible // reflection // @SuppressWarnings("GoodTime") // should accept a java.time.Duration // public static V getChecked( // Future future, Class exceptionClass, long timeout, TimeUnit unit) throws X { // return FuturesGetChecked.getChecked(future, exceptionClass, timeout, unit); // } // // /** // * 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 computation 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 // */ // @CanIgnoreReturnValue // 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 an Exception. (Or 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); // } // // /* // * 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 computation -- 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. You might also also look into the // * Fork-Join framework: http://docs.oracle.com/javase/tutorial/essential/concurrency/forkjoin.html // */ // // /** // * A checked future that uses a function to map from exceptions to the appropriate checked type. // */ // @GwtIncompatible // TODO // private static class MappingCheckedFuture // extends AbstractCheckedFuture { // // final Function mapper; // // MappingCheckedFuture(ListenableFuture delegate, Function mapper) { // super(delegate); // // this.mapper = checkNotNull(mapper); // } // // @Override // protected X mapException(Exception e) { // return mapper.apply(e); // } // } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy