content: /*
   * Written by Doug Lea with assistance from members of JCP JSR-166 Expert Group and released to the
   * public domain, as explained at http://creativecommons.org/publicdomain/zero/1.0/
   */
  package alluxio.concurrent.jsr;
  
  import java.util.concurrent.CompletionException;
  import java.util.concurrent.Executor;
  import java.util.function.BiConsumer;
  import java.util.function.BiFunction;
  import java.util.function.Consumer;
  import java.util.function.Function;
  
  /**
   * A stage of a possibly asynchronous computation, that performs an action or computes a value when
   * another CompletionStage completes. A stage completes upon termination of its computation, but
   * this may in turn trigger other dependent stages. The functionality defined in this interface
   * takes only a few basic forms, which expand out to a larger set of methods to capture a range of
   * usage styles:
   *
   * <ul>
   *
   * <li>The computation performed by a stage may be expressed as a Function, Consumer, or Runnable
   * (using methods with names including <em>apply</em>, <em>accept</em>, or <em>run</em>,
   * respectively) depending on whether it requires arguments and/or produces results. For example:
   * 
   * <pre>
   *  {@code
   * stage.thenApply(x -> square(x))
   *      .thenAccept(x -> System.out.print(x))
   *      .thenRun(() -> System.out.println());}
   * </pre>
   *
   * An additional form (<em>compose</em>) allows the construction of computation pipelines from
   * functions returning completion stages.
   *
   * <p>
   * Any argument to a stage's computation is the outcome of a triggering stage's computation.
   *
   * <li>One stage's execution may be triggered by completion of a single stage, or both of two
   * stages, or either of two stages. Dependencies on a single stage are arranged using methods with
   * prefix <em>then</em>. Those triggered by completion of <em>both</em> of two stages may
   * <em>combine</em> their results or effects, using correspondingly named methods. Those triggered
   * by <em>either</em> of two stages make no guarantees about which of the results or effects are
   * used for the dependent stage's computation.
   *
   * <li>Dependencies among stages control the triggering of computations, but do not otherwise
   * guarantee any particular ordering. Additionally, execution of a new stage's computations may be
   * arranged in any of three ways: default execution, default asynchronous execution (using methods
   * with suffix <em>async</em> that employ the stage's default asynchronous execution facility), or
   * custom (via a supplied {@link Executor}). The execution properties of default and async modes are
   * specified by CompletionStage implementations, not this interface. Methods with explicit Executor
   * arguments may have arbitrary execution properties, and might not even support concurrent
   * execution, but are arranged for processing in a way that accommodates asynchrony.
   *
   * <li>Two method forms ({@link #handle handle} and {@link #whenComplete whenComplete}) support
   * unconditional computation whether the triggering stage completed normally or exceptionally.
   * Method {@link #exceptionally exceptionally} supports computation only when the triggering stage
   * completes exceptionally, computing a replacement result, similarly to the java {@code catch}
   * keyword. In all other cases, if a stage's computation terminates abruptly with an (unchecked)
   * exception or error, then all dependent stages requiring its completion complete exceptionally as
   * well, with a {@link CompletionException} holding the exception as its cause. If a stage is
   * dependent on <em>both</em> of two stages, and both complete exceptionally, then the
   * CompletionException may correspond to either one of these exceptions. If a stage is dependent on
   * <em>either</em> of two others, and only one of them completes exceptionally, no guarantees are
   * made about whether the dependent stage completes normally or exceptionally. In the case of method
   * {@code whenComplete}, when the supplied action itself encounters an exception, then the stage
   * completes exceptionally with this exception unless the source stage also completed exceptionally,
   * in which case the exceptional completion from the source stage is given preference and propagated
   * to the dependent stage.
   *
   * </ul>
   *
   * <p>
   * All methods adhere to the above triggering, execution, and exceptional completion specifications
   * (which are not repeated in individual method specifications). Additionally, while arguments used
   * to pass a completion result (that is, for parameters of type {@code T}) for methods accepting
   * them may be null, passing a null value for any other parameter will result in a
   * {@link NullPointerException} being thrown.
   *
   * <p>
   * Method form {@link #handle handle} is the most general way of creating a continuation stage,
   * unconditionally performing a computation that is given both the result and exception (if any) of
   * the triggering CompletionStage, and computing an arbitrary result. Method {@link #whenComplete
   * whenComplete} is similar, but preserves the result of the triggering stage instead of computing a
   * new one. Because a stage's normal result may be {@code null}, both methods should have a
   * computation structured thus:
   *
   * <pre>
   * {@code (result, exception) -> {
   *   if (exception == null) {
   *     // triggering stage completed normally
   *   } else {
   *     // triggering stage completed exceptionally
   *   }
   * }}
   * </pre>
   *
   * <p>
   * This interface does not define methods for initially creating, forcibly completing normally or
   * exceptionally, probing completion status or results, or awaiting completion of a stage.
   * Implementations of CompletionStage may provide means of achieving such effects, as appropriate.
   * Method {@link #toCompletableFuture} enables interoperability among different implementations of
   * this interface by providing a common conversion type.
   *
   * @author Doug Lea
   * @since 1.8
   */
  public interface CompletionStage<T> {
    // CVS rev. 1.39
    /**
     * Returns a new CompletionStage that, when this stage completes normally, is executed with this
     * stage's result as the argument to the supplied function.
     *
     * <p>
     * This method is analogous to {@link java.util.Optional#map Optional.map} and
     * {@link java.util.stream.Stream#map Stream.map}.
     *
     * <p>
     * See the {@link CompletionStage} documentation for rules covering exceptional completion.
     *
     * @param fn the function to use to compute the value of the returned CompletionStage
     * @param <U> the function's return type
     * @return the new CompletionStage
     */
    public <U> CompletionStage<U> thenApply(Function<? super T, ? extends U> fn);
  
    /**
     * Returns a new CompletionStage that, when this stage completes normally, is executed using this
     * stage's default asynchronous execution facility, with this stage's result as the argument to
     * the supplied function.
     *
     * See the {@link CompletionStage} documentation for rules covering exceptional completion.
     *
     * @param fn the function to use to compute the value of the returned CompletionStage
     * @param <U> the function's return type
     * @return the new CompletionStage
     */
    public <U> CompletionStage<U> thenApplyAsync(Function<? super T, ? extends U> fn);
  
    /**
     * Returns a new CompletionStage that, when this stage completes normally, is executed using the
     * supplied Executor, with this stage's result as the argument to the supplied function.
     *
     * See the {@link CompletionStage} documentation for rules covering exceptional completion.
     *
     * @param fn the function to use to compute the value of the returned CompletionStage
     * @param executor the executor to use for asynchronous execution
     * @param <U> the function's return type
     * @return the new CompletionStage
     */
    public <U> CompletionStage<U> thenApplyAsync(Function<? super T, ? extends U> fn,
        Executor executor);
  
    /**
     * Returns a new CompletionStage that, when this stage completes normally, is executed with this
     * stage's result as the argument to the supplied action.
     *
     * See the {@link CompletionStage} documentation for rules covering exceptional completion.
     *
     * @param action the action to perform before completing the returned CompletionStage
     * @return the new CompletionStage
     */
    public CompletionStage<Void> thenAccept(Consumer<? super T> action);
  
    /**
     * Returns a new CompletionStage that, when this stage completes normally, is executed using this
     * stage's default asynchronous execution facility, with this stage's result as the argument to
     * the supplied action.
     *
     * See the {@link CompletionStage} documentation for rules covering exceptional completion.
     *
     * @param action the action to perform before completing the returned CompletionStage
     * @return the new CompletionStage
     */
    public CompletionStage<Void> thenAcceptAsync(Consumer<? super T> action);
  
    /**
     * Returns a new CompletionStage that, when this stage completes normally, is executed using the
     * supplied Executor, with this stage's result as the argument to the supplied action.
     *
     * See the {@link CompletionStage} documentation for rules covering exceptional completion.
     *
     * @param action the action to perform before completing the returned CompletionStage
     * @param executor the executor to use for asynchronous execution
     * @return the new CompletionStage
     */
    public CompletionStage<Void> thenAcceptAsync(Consumer<? super T> action, Executor executor);
  
    /**
     * Returns a new CompletionStage that, when this stage completes normally, executes the given
     * action.
     *
     * See the {@link CompletionStage} documentation for rules covering exceptional completion.
     *
     * @param action the action to perform before completing the returned CompletionStage
     * @return the new CompletionStage
     */
    public CompletionStage<Void> thenRun(Runnable action);
  
    /**
     * Returns a new CompletionStage that, when this stage completes normally, executes the given
     * action using this stage's default asynchronous execution facility.
     *
     * See the {@link CompletionStage} documentation for rules covering exceptional completion.
     *
     * @param action the action to perform before completing the returned CompletionStage
     * @return the new CompletionStage
     */
    public CompletionStage<Void> thenRunAsync(Runnable action);
  
    /**
     * Returns a new CompletionStage that, when this stage completes normally, executes the given
     * action using the supplied Executor.
     *
     * See the {@link CompletionStage} documentation for rules covering exceptional completion.
     *
     * @param action the action to perform before completing the returned CompletionStage
     * @param executor the executor to use for asynchronous execution
     * @return the new CompletionStage
     */
    public CompletionStage<Void> thenRunAsync(Runnable action, Executor executor);
  
    /**
     * Returns a new CompletionStage that, when this and the other given stage both complete normally,
     * is executed with the two results as arguments to the supplied function.
     *
     * See the {@link CompletionStage} documentation for rules covering exceptional completion.
     *
     * @param other the other CompletionStage
     * @param fn the function to use to compute the value of the returned CompletionStage
     * @param <U> the type of the other CompletionStage's result
     * @param <V> the function's return type
     * @return the new CompletionStage
     */
    public <U, V> CompletionStage<V> thenCombine(CompletionStage<? extends U> other,
        BiFunction<? super T, ? super U, ? extends V> fn);
  
    /**
     * Returns a new CompletionStage that, when this and the other given stage both complete normally,
     * is executed using this stage's default asynchronous execution facility, with the two results as
     * arguments to the supplied function.
     *
     * See the {@link CompletionStage} documentation for rules covering exceptional completion.
     *
     * @param other the other CompletionStage
     * @param fn the function to use to compute the value of the returned CompletionStage
     * @param <U> the type of the other CompletionStage's result
     * @param <V> the function's return type
     * @return the new CompletionStage
     */
    public <U, V> CompletionStage<V> thenCombineAsync(CompletionStage<? extends U> other,
        BiFunction<? super T, ? super U, ? extends V> fn);
  
    /**
     * Returns a new CompletionStage that, when this and the other given stage both complete normally,
     * is executed using the supplied executor, with the two results as arguments to the supplied
     * function.
     *
     * See the {@link CompletionStage} documentation for rules covering exceptional completion.
     *
     * @param other the other CompletionStage
     * @param fn the function to use to compute the value of the returned CompletionStage
     * @param executor the executor to use for asynchronous execution
     * @param <U> the type of the other CompletionStage's result
     * @param <V> the function's return type
     * @return the new CompletionStage
     */
    public <U, V> CompletionStage<V> thenCombineAsync(CompletionStage<? extends U> other,
        BiFunction<? super T, ? super U, ? extends V> fn, Executor executor);
  
    /**
     * Returns a new CompletionStage that, when this and the other given stage both complete normally,
     * is executed with the two results as arguments to the supplied action.
     *
     * See the {@link CompletionStage} documentation for rules covering exceptional completion.
     *
     * @param other the other CompletionStage
     * @param action the action to perform before completing the returned CompletionStage
     * @param <U> the type of the other CompletionStage's result
     * @return the new CompletionStage
     */
    public <U> CompletionStage<Void> thenAcceptBoth(CompletionStage<? extends U> other,
        BiConsumer<? super T, ? super U> action);
  
    /**
     * Returns a new CompletionStage that, when this and the other given stage both complete normally,
     * is executed using this stage's default asynchronous execution facility, with the two results as
     * arguments to the supplied action.
     *
     * See the {@link CompletionStage} documentation for rules covering exceptional completion.
     *
     * @param other the other CompletionStage
     * @param action the action to perform before completing the returned CompletionStage
     * @param <U> the type of the other CompletionStage's result
     * @return the new CompletionStage
     */
    public <U> CompletionStage<Void> thenAcceptBothAsync(CompletionStage<? extends U> other,
        BiConsumer<? super T, ? super U> action);
  
    /**
     * Returns a new CompletionStage that, when this and the other given stage both complete normally,
     * is executed using the supplied executor, with the two results as arguments to the supplied
     * action.
     *
     * See the {@link CompletionStage} documentation for rules covering exceptional completion.
     *
     * @param other the other CompletionStage
     * @param action the action to perform before completing the returned CompletionStage
     * @param executor the executor to use for asynchronous execution
     * @param <U> the type of the other CompletionStage's result
     * @return the new CompletionStage
     */
    public <U> CompletionStage<Void> thenAcceptBothAsync(CompletionStage<? extends U> other,
        BiConsumer<? super T, ? super U> action, Executor executor);
  
    /**
     * Returns a new CompletionStage that, when this and the other given stage both complete normally,
     * executes the given action.
     *
     * See the {@link CompletionStage} documentation for rules covering exceptional completion.
     *
     * @param other the other CompletionStage
     * @param action the action to perform before completing the returned CompletionStage
     * @return the new CompletionStage
     */
    public CompletionStage<Void> runAfterBoth(CompletionStage<?> other, Runnable action);
  
    /**
     * Returns a new CompletionStage that, when this and the other given stage both complete normally,
     * executes the given action using this stage's default asynchronous execution facility.
     *
     * See the {@link CompletionStage} documentation for rules covering exceptional completion.
     *
     * @param other the other CompletionStage
     * @param action the action to perform before completing the returned CompletionStage
     * @return the new CompletionStage
     */
    public CompletionStage<Void> runAfterBothAsync(CompletionStage<?> other, Runnable action);
  
    /**
     * Returns a new CompletionStage that, when this and the other given stage both complete normally,
     * executes the given action using the supplied executor.
     *
     * See the {@link CompletionStage} documentation for rules covering exceptional completion.
     *
     * @param other the other CompletionStage
     * @param action the action to perform before completing the returned CompletionStage
     * @param executor the executor to use for asynchronous execution
     * @return the new CompletionStage
     */
    public CompletionStage<Void> runAfterBothAsync(CompletionStage<?> other, Runnable action,
        Executor executor);
  
    /**
     * Returns a new CompletionStage that, when either this or the other given stage complete
     * normally, is executed with the corresponding result as argument to the supplied function.
     *
     * See the {@link CompletionStage} documentation for rules covering exceptional completion.
     *
     * @param other the other CompletionStage
     * @param fn the function to use to compute the value of the returned CompletionStage
     * @param <U> the function's return type
     * @return the new CompletionStage
     */
    public <U> CompletionStage<U> applyToEither(CompletionStage<? extends T> other,
        Function<? super T, U> fn);
  
    /**
     * Returns a new CompletionStage that, when either this or the other given stage complete
     * normally, is executed using this stage's default asynchronous execution facility, with the
     * corresponding result as argument to the supplied function.
     *
     * See the {@link CompletionStage} documentation for rules covering exceptional completion.
     *
     * @param other the other CompletionStage
     * @param fn the function to use to compute the value of the returned CompletionStage
     * @param <U> the function's return type
     * @return the new CompletionStage
     */
    public <U> CompletionStage<U> applyToEitherAsync(CompletionStage<? extends T> other,
        Function<? super T, U> fn);
  
    /**
     * Returns a new CompletionStage that, when either this or the other given stage complete
     * normally, is executed using the supplied executor, with the corresponding result as argument to
     * the supplied function.
     *
     * See the {@link CompletionStage} documentation for rules covering exceptional completion.
     *
     * @param other the other CompletionStage
     * @param fn the function to use to compute the value of the returned CompletionStage
     * @param executor the executor to use for asynchronous execution
     * @param <U> the function's return type
     * @return the new CompletionStage
     */
    public <U> CompletionStage<U> applyToEitherAsync(CompletionStage<? extends T> other,
        Function<? super T, U> fn, Executor executor);
  
    /**
     * Returns a new CompletionStage that, when either this or the other given stage complete
     * normally, is executed with the corresponding result as argument to the supplied action.
     *
     * See the {@link CompletionStage} documentation for rules covering exceptional completion.
     *
     * @param other the other CompletionStage
     * @param action the action to perform before completing the returned CompletionStage
     * @return the new CompletionStage
     */
    public CompletionStage<Void> acceptEither(CompletionStage<? extends T> other,
        Consumer<? super T> action);
  
    /**
     * Returns a new CompletionStage that, when either this or the other given stage complete
     * normally, is executed using this stage's default asynchronous execution facility, with the
     * corresponding result as argument to the supplied action.
     *
     * See the {@link CompletionStage} documentation for rules covering exceptional completion.
     *
     * @param other the other CompletionStage
     * @param action the action to perform before completing the returned CompletionStage
     * @return the new CompletionStage
     */
    public CompletionStage<Void> acceptEitherAsync(CompletionStage<? extends T> other,
        Consumer<? super T> action);
  
    /**
     * Returns a new CompletionStage that, when either this or the other given stage complete
     * normally, is executed using the supplied executor, with the corresponding result as argument to
     * the supplied action.
     *
     * See the {@link CompletionStage} documentation for rules covering exceptional completion.
     *
     * @param other the other CompletionStage
     * @param action the action to perform before completing the returned CompletionStage
     * @param executor the executor to use for asynchronous execution
     * @return the new CompletionStage
     */
    public CompletionStage<Void> acceptEitherAsync(CompletionStage<? extends T> other,
        Consumer<? super T> action, Executor executor);
  
    /**
     * Returns a new CompletionStage that, when either this or the other given stage complete
     * normally, executes the given action.
     *
     * See the {@link CompletionStage} documentation for rules covering exceptional completion.
     *
     * @param other the other CompletionStage
     * @param action the action to perform before completing the returned CompletionStage
     * @return the new CompletionStage
     */
    public CompletionStage<Void> runAfterEither(CompletionStage<?> other, Runnable action);
  
    /**
     * Returns a new CompletionStage that, when either this or the other given stage complete
     * normally, executes the given action using this stage's default asynchronous execution facility.
     *
     * See the {@link CompletionStage} documentation for rules covering exceptional completion.
     *
     * @param other the other CompletionStage
     * @param action the action to perform before completing the returned CompletionStage
     * @return the new CompletionStage
     */
    public CompletionStage<Void> runAfterEitherAsync(CompletionStage<?> other, Runnable action);
  
    /**
     * Returns a new CompletionStage that, when either this or the other given stage complete
     * normally, executes the given action using the supplied executor.
     *
     * See the {@link CompletionStage} documentation for rules covering exceptional completion.
     *
     * @param other the other CompletionStage
     * @param action the action to perform before completing the returned CompletionStage
     * @param executor the executor to use for asynchronous execution
     * @return the new CompletionStage
     */
    public CompletionStage<Void> runAfterEitherAsync(CompletionStage<?> other, Runnable action,
        Executor executor);
  
    /**
     * Returns a new CompletionStage that is completed with the same value as the CompletionStage
     * returned by the given function.
     *
     * <p>
     * When this stage completes normally, the given function is invoked with this stage's result as
     * the argument, returning another CompletionStage. When that stage completes normally, the
     * CompletionStage returned by this method is completed with the same value.
     *
     * <p>
     * To ensure progress, the supplied function must arrange eventual completion of its result.
     *
     * <p>
     * This method is analogous to {@link java.util.Optional#flatMap Optional.flatMap} and
     * {@link java.util.stream.Stream#flatMap Stream.flatMap}.
     *
     * <p>
     * See the {@link CompletionStage} documentation for rules covering exceptional completion.
     *
     * @param fn the function to use to compute another CompletionStage
     * @param <U> the type of the returned CompletionStage's result
     * @return the new CompletionStage
     */
    public <U> CompletionStage<U> thenCompose(Function<? super T, ? extends CompletionStage<U>> fn);
  
    /**
     * Returns a new CompletionStage that is completed with the same value as the CompletionStage
     * returned by the given function, executed using this stage's default asynchronous execution
     * facility.
     *
     * <p>
     * When this stage completes normally, the given function is invoked with this stage's result as
     * the argument, returning another CompletionStage. When that stage completes normally, the
     * CompletionStage returned by this method is completed with the same value.
     *
     * <p>
     * To ensure progress, the supplied function must arrange eventual completion of its result.
     *
     * <p>
     * See the {@link CompletionStage} documentation for rules covering exceptional completion.
     *
     * @param fn the function to use to compute another CompletionStage
     * @param <U> the type of the returned CompletionStage's result
     * @return the new CompletionStage
     */
    public <U> CompletionStage<U> thenComposeAsync(
        Function<? super T, ? extends CompletionStage<U>> fn);
  
    /**
     * Returns a new CompletionStage that is completed with the same value as the CompletionStage
     * returned by the given function, executed using the supplied Executor.
     *
     * <p>
     * When this stage completes normally, the given function is invoked with this stage's result as
     * the argument, returning another CompletionStage. When that stage completes normally, the
     * CompletionStage returned by this method is completed with the same value.
     *
     * <p>
     * To ensure progress, the supplied function must arrange eventual completion of its result.
     *
     * <p>
     * See the {@link CompletionStage} documentation for rules covering exceptional completion.
     *
     * @param fn the function to use to compute another CompletionStage
     * @param executor the executor to use for asynchronous execution
     * @param <U> the type of the returned CompletionStage's result
     * @return the new CompletionStage
     */
    public <U> CompletionStage<U> thenComposeAsync(
        Function<? super T, ? extends CompletionStage<U>> fn, Executor executor);
  
    /**
     * Returns a new CompletionStage that, when this stage completes either normally or exceptionally,
     * is executed with this stage's result and exception as arguments to the supplied function.
     *
     * <p>
     * When this stage is complete, the given function is invoked with the result (or {@code null} if
     * none) and the exception (or {@code null} if none) of this stage as arguments, and the
     * function's result is used to complete the returned stage.
     *
     * @param fn the function to use to compute the value of the returned CompletionStage
     * @param <U> the function's return type
     * @return the new CompletionStage
     */
    public <U> CompletionStage<U> handle(BiFunction<? super T, Throwable, ? extends U> fn);
  
    /**
     * Returns a new CompletionStage that, when this stage completes either normally or exceptionally,
     * is executed using this stage's default asynchronous execution facility, with this stage's
     * result and exception as arguments to the supplied function.
     *
     * <p>
     * When this stage is complete, the given function is invoked with the result (or {@code null} if
     * none) and the exception (or {@code null} if none) of this stage as arguments, and the
     * function's result is used to complete the returned stage.
     *
     * @param fn the function to use to compute the value of the returned CompletionStage
     * @param <U> the function's return type
     * @return the new CompletionStage
     */
    public <U> CompletionStage<U> handleAsync(BiFunction<? super T, Throwable, ? extends U> fn);
  
    /**
     * Returns a new CompletionStage that, when this stage completes either normally or exceptionally,
     * is executed using the supplied executor, with this stage's result and exception as arguments to
     * the supplied function.
     *
     * <p>
     * When this stage is complete, the given function is invoked with the result (or {@code null} if
     * none) and the exception (or {@code null} if none) of this stage as arguments, and the
     * function's result is used to complete the returned stage.
     *
     * @param fn the function to use to compute the value of the returned CompletionStage
     * @param executor the executor to use for asynchronous execution
     * @param <U> the function's return type
     * @return the new CompletionStage
     */
    public <U> CompletionStage<U> handleAsync(BiFunction<? super T, Throwable, ? extends U> fn,
        Executor executor);
  
    /**
     * Returns a new CompletionStage with the same result or exception as this stage, that executes
     * the given action when this stage completes.
     *
     * <p>
     * When this stage is complete, the given action is invoked with the result (or {@code null} if
     * none) and the exception (or {@code null} if none) of this stage as arguments. The returned
     * stage is completed when the action returns.
     *
     * <p>
     * Unlike method {@link #handle handle}, this method is not designed to translate completion
     * outcomes, so the supplied action should not throw an exception. However, if it does, the
     * following rules apply: if this stage completed normally but the supplied action throws an
     * exception, then the returned stage completes exceptionally with the supplied action's
     * exception. Or, if this stage completed exceptionally and the supplied action throws an
     * exception, then the returned stage completes exceptionally with this stage's exception.
     *
     * @param action the action to perform
     * @return the new CompletionStage
     */
    public CompletionStage<T> whenComplete(BiConsumer<? super T, ? super Throwable> action);
  
    /**
     * Returns a new CompletionStage with the same result or exception as this stage, that executes
     * the given action using this stage's default asynchronous execution facility when this stage
     * completes.
     *
     * <p>
     * When this stage is complete, the given action is invoked with the result (or {@code null} if
     * none) and the exception (or {@code null} if none) of this stage as arguments. The returned
     * stage is completed when the action returns.
     *
     * <p>
     * Unlike method {@link #handleAsync(BiFunction) handleAsync}, this method is not designed to
     * translate completion outcomes, so the supplied action should not throw an exception. However,
     * if it does, the following rules apply: If this stage completed normally but the supplied action
     * throws an exception, then the returned stage completes exceptionally with the supplied action's
     * exception. Or, if this stage completed exceptionally and the supplied action throws an
     * exception, then the returned stage completes exceptionally with this stage's exception.
     *
     * @param action the action to perform
     * @return the new CompletionStage
     */
    public CompletionStage<T> whenCompleteAsync(BiConsumer<? super T, ? super Throwable> action);
  
    /**
     * Returns a new CompletionStage with the same result or exception as this stage, that executes
     * the given action using the supplied Executor when this stage completes.
     *
     * <p>
     * When this stage is complete, the given action is invoked with the result (or {@code null} if
     * none) and the exception (or {@code null} if none) of this stage as arguments. The returned
     * stage is completed when the action returns.
     *
     * <p>
     * Unlike method {@link #handleAsync(BiFunction,Executor) handleAsync}, this method is not
     * designed to translate completion outcomes, so the supplied action should not throw an
     * exception. However, if it does, the following rules apply: If this stage completed normally but
     * the supplied action throws an exception, then the returned stage completes exceptionally with
     * the supplied action's exception. Or, if this stage completed exceptionally and the supplied
     * action throws an exception, then the returned stage completes exceptionally with this stage's
     * exception.
     *
     * @param action the action to perform
     * @param executor the executor to use for asynchronous execution
     * @return the new CompletionStage
     */
    public CompletionStage<T> whenCompleteAsync(BiConsumer<? super T, ? super Throwable> action,
        Executor executor);
  
    /**
     * Returns a new CompletionStage that, when this stage completes exceptionally, is executed with
     * this stage's exception as the argument to the supplied function. Otherwise, if this stage
     * completes normally, then the returned stage also completes normally with the same value.
     *
     * @param fn the function to use to compute the value of the returned CompletionStage if this
     *        CompletionStage completed exceptionally
     * @return the new CompletionStage
     */
    public CompletionStage<T> exceptionally(Function<Throwable, ? extends T> fn);
  
    /**
     * Returns a {@link CompletableFuture} maintaining the same completion properties as this stage.
     * If this stage is already a CompletableFuture, this method may return this stage itself.
     * Otherwise, invocation of this method may be equivalent in effect to {@code thenApply(x -> x)},
     * but returning an instance of type {@code CompletableFuture}.
     *
     * @return the CompletableFuture
     */
    public CompletableFuture<T> toCompletableFuture();
  }
  