class FailsafeFuture<R> extends CompletableFuture<R> {
  private final BiConsumer<ExecutionResult<R>, ExecutionContext<R>> completionHandler;

  // Mutable state guarded by "this"

  // The most recent execution attempt
  private ExecutionInternal<R> newestExecution;
  // Functions to apply when this future is cancelled for each policy index, in descending order
  private Map<Integer, BiConsumer<Boolean, ExecutionResult<R>>> cancelFunctions;
  // Whether a cancel with interrupt has already occurred
  private boolean cancelledWithInterrupt;

  public FailsafeFuture(BiConsumer<ExecutionResult<R>, ExecutionContext<R>> completionHandler) {
    this.completionHandler = completionHandler;
  }

  /**
   * If not already completed, completes  the future with the {@code value}, calling the complete and success handlers.
   */
  @Override
  public synchronized boolean complete(R value) {
    return completeResult(ExecutionResult.success(value));
  }

  /**
   * If not already completed, completes the future with the {@code exception}, calling the complete and failure
   * handlers.
   */
  @Override
  public synchronized boolean completeExceptionally(Throwable exception) {
    return completeResult(ExecutionResult.exception(exception));
  }

  /**
   * Cancels the future along with any dependencies.
   */
  @Override
  public synchronized boolean cancel(boolean mayInterruptIfRunning) {
    if (isDone())
      return false;

    this.cancelledWithInterrupt = mayInterruptIfRunning;
    newestExecution.cancel();
    boolean cancelResult = super.cancel(mayInterruptIfRunning);
    cancelDependencies(null, mayInterruptIfRunning, null);
    ExecutionResult<R> result = ExecutionResult.exception(new CancellationException());
    super.completeExceptionally(result.getException());
    completionHandler.accept(result, newestExecution);
    newestExecution = null;
    cancelFunctions = null;
    return cancelResult;
  }

  /**
   * Completes the execution with the {@code result} and calls the completion handler.
   */
  public synchronized boolean completeResult(ExecutionResult<R> result) {
    if (isDone())
      return false;

    Throwable exception = result.getException();
    boolean completed;
    if (exception == null)
      completed = super.complete(result.getResult());
    else
      completed = super.completeExceptionally(exception);
    if (completed)
      completionHandler.accept(result, newestExecution);
    newestExecution = null;
    cancelFunctions = null;
    return completed;
  }

  /**
   * Applies any {@link #setCancelFn(PolicyExecutor, BiConsumer) cancel functions} with the {@code cancelResult} for
   * PolicyExecutors whose policyIndex is < the policyIndex of the {@code cancellingPolicyExecutor}.
   *
   * @param cancellingPolicyExecutor the PolicyExecutor that is requesting the cancellation of inner policy executors
   */
  public synchronized void cancelDependencies(PolicyExecutor<R> cancellingPolicyExecutor, boolean mayInterrupt,
    ExecutionResult<R> cancelResult) {<FILL_FUNCTION_BODY>}

  /**
   * Sets the {@code execution} representing the most recent attempt, which will be cancelled if this future is
   * cancelled.
   */
  public synchronized void setExecution(ExecutionInternal<R> execution) {
    this.newestExecution = execution;
  }

  /**
   * Sets a {@code cancelFn} to be called when a PolicyExecutor {@link #cancelDependencies(PolicyExecutor, boolean,
   * ExecutionResult) cancels dependencies} with a policyIndex > the given {@code policyIndex}, or when this future is
   * {@link #cancel(boolean) cancelled}.
   */
  public synchronized void setCancelFn(int policyIndex, BiConsumer<Boolean, ExecutionResult<R>> cancelFn) {
    if (cancelFunctions == null)
      cancelFunctions = new TreeMap<>(Collections.reverseOrder());
    cancelFunctions.put(policyIndex, cancelFn);
  }

  /**
   * Sets a {@code cancelFn} to be called when a PolicyExecutor {@link #cancelDependencies(PolicyExecutor, boolean,
   * ExecutionResult) cancels dependencies} with a policyIndex > the policyIndex of the given {@code policyExecutor}, or
   * when this future is {@link #cancel(boolean) cancelled}.
   */
  public synchronized void setCancelFn(PolicyExecutor<R> policyExecutor,
    BiConsumer<Boolean, ExecutionResult<R>> cancelFn) {
    setCancelFn(policyExecutor.getPolicyIndex(), cancelFn);
  }

  /**
   * Propogates any previous cancellation to the {@code future}, either by cancelling it immediately or setting a cancel
   * function to cancel it later.
   */
  public synchronized void propagateCancellation(Future<R> future) {
    if (isCancelled())
      future.cancel(cancelledWithInterrupt);
    else
      setCancelFn(-2, (mayInterrupt, cancelResult) -> future.cancel(mayInterrupt));
  }
}

    if (cancelFunctions != null) {
      int cancellingPolicyIndex =
        cancellingPolicyExecutor == null ? Integer.MAX_VALUE : cancellingPolicyExecutor.getPolicyIndex();
      Iterator<Entry<Integer, BiConsumer<Boolean, ExecutionResult<R>>>> it = cancelFunctions.entrySet().iterator();

      /* This iteration occurs in descending order to ensure that the {@code cancelResult} can be supplied to outer
      cancel functions before the inner supplier is cancelled, which would cause PolicyExecutors to complete with
      CancellationException rather than the expected {@code cancelResult}. */
      while (it.hasNext()) {
        Map.Entry<Integer, BiConsumer<Boolean, ExecutionResult<R>>> entry = it.next();
        if (cancellingPolicyIndex > entry.getKey()) {
          try {
            entry.getValue().accept(mayInterrupt, cancelResult);
          } catch (Exception ignore) {
          }
          it.remove();
        }
      }
    }
  
<methods>public void <init>() ,public CompletableFuture<java.lang.Void> acceptEither(CompletionStage<? extends R>, Consumer<? super R>) ,public CompletableFuture<java.lang.Void> acceptEitherAsync(CompletionStage<? extends R>, Consumer<? super R>) ,public CompletableFuture<java.lang.Void> acceptEitherAsync(CompletionStage<? extends R>, Consumer<? super R>, java.util.concurrent.Executor) ,public static transient CompletableFuture<java.lang.Void> allOf(CompletableFuture<?>[]) ,public static transient CompletableFuture<java.lang.Object> anyOf(CompletableFuture<?>[]) ,public CompletableFuture<U> applyToEither(CompletionStage<? extends R>, Function<? super R,U>) ,public CompletableFuture<U> applyToEitherAsync(CompletionStage<? extends R>, Function<? super R,U>) ,public CompletableFuture<U> applyToEitherAsync(CompletionStage<? extends R>, Function<? super R,U>, java.util.concurrent.Executor) ,public boolean cancel(boolean) ,public boolean complete(R) ,public CompletableFuture<R> completeAsync(Supplier<? extends R>) ,public CompletableFuture<R> completeAsync(Supplier<? extends R>, java.util.concurrent.Executor) ,public boolean completeExceptionally(java.lang.Throwable) ,public CompletableFuture<R> completeOnTimeout(R, long, java.util.concurrent.TimeUnit) ,public static CompletableFuture<U> completedFuture(U) ,public static CompletionStage<U> completedStage(U) ,public CompletableFuture<R> copy() ,public java.util.concurrent.Executor defaultExecutor() ,public static java.util.concurrent.Executor delayedExecutor(long, java.util.concurrent.TimeUnit) ,public static java.util.concurrent.Executor delayedExecutor(long, java.util.concurrent.TimeUnit, java.util.concurrent.Executor) ,public CompletableFuture<R> exceptionally(Function<java.lang.Throwable,? extends R>) ,public CompletableFuture<R> exceptionallyAsync(Function<java.lang.Throwable,? extends R>) ,public CompletableFuture<R> exceptionallyAsync(Function<java.lang.Throwable,? extends R>, java.util.concurrent.Executor) ,public CompletableFuture<R> exceptionallyCompose(Function<java.lang.Throwable,? extends CompletionStage<R>>) ,public CompletableFuture<R> exceptionallyComposeAsync(Function<java.lang.Throwable,? extends CompletionStage<R>>) ,public CompletableFuture<R> exceptionallyComposeAsync(Function<java.lang.Throwable,? extends CompletionStage<R>>, java.util.concurrent.Executor) ,public static CompletableFuture<U> failedFuture(java.lang.Throwable) ,public static CompletionStage<U> failedStage(java.lang.Throwable) ,public R get() throws java.lang.InterruptedException, java.util.concurrent.ExecutionException,public R get(long, java.util.concurrent.TimeUnit) throws java.lang.InterruptedException, java.util.concurrent.ExecutionException, java.util.concurrent.TimeoutException,public R getNow(R) ,public int getNumberOfDependents() ,public CompletableFuture<U> handle(BiFunction<? super R,java.lang.Throwable,? extends U>) ,public CompletableFuture<U> handleAsync(BiFunction<? super R,java.lang.Throwable,? extends U>) ,public CompletableFuture<U> handleAsync(BiFunction<? super R,java.lang.Throwable,? extends U>, java.util.concurrent.Executor) ,public boolean isCancelled() ,public boolean isCompletedExceptionally() ,public boolean isDone() ,public R join() ,public CompletionStage<R> minimalCompletionStage() ,public CompletableFuture<U> newIncompleteFuture() ,public void obtrudeException(java.lang.Throwable) ,public void obtrudeValue(R) ,public CompletableFuture<R> orTimeout(long, java.util.concurrent.TimeUnit) ,public CompletableFuture<java.lang.Void> runAfterBoth(CompletionStage<?>, java.lang.Runnable) ,public CompletableFuture<java.lang.Void> runAfterBothAsync(CompletionStage<?>, java.lang.Runnable) ,public CompletableFuture<java.lang.Void> runAfterBothAsync(CompletionStage<?>, java.lang.Runnable, java.util.concurrent.Executor) ,public CompletableFuture<java.lang.Void> runAfterEither(CompletionStage<?>, java.lang.Runnable) ,public CompletableFuture<java.lang.Void> runAfterEitherAsync(CompletionStage<?>, java.lang.Runnable) ,public CompletableFuture<java.lang.Void> runAfterEitherAsync(CompletionStage<?>, java.lang.Runnable, java.util.concurrent.Executor) ,public static CompletableFuture<java.lang.Void> runAsync(java.lang.Runnable) ,public static CompletableFuture<java.lang.Void> runAsync(java.lang.Runnable, java.util.concurrent.Executor) ,public static CompletableFuture<U> supplyAsync(Supplier<U>) ,public static CompletableFuture<U> supplyAsync(Supplier<U>, java.util.concurrent.Executor) ,public CompletableFuture<java.lang.Void> thenAccept(Consumer<? super R>) ,public CompletableFuture<java.lang.Void> thenAcceptAsync(Consumer<? super R>) ,public CompletableFuture<java.lang.Void> thenAcceptAsync(Consumer<? super R>, java.util.concurrent.Executor) ,public CompletableFuture<java.lang.Void> thenAcceptBoth(CompletionStage<? extends U>, BiConsumer<? super R,? super U>) ,public CompletableFuture<java.lang.Void> thenAcceptBothAsync(CompletionStage<? extends U>, BiConsumer<? super R,? super U>) ,public CompletableFuture<java.lang.Void> thenAcceptBothAsync(CompletionStage<? extends U>, BiConsumer<? super R,? super U>, java.util.concurrent.Executor) ,public CompletableFuture<U> thenApply(Function<? super R,? extends U>) ,public CompletableFuture<U> thenApplyAsync(Function<? super R,? extends U>) ,public CompletableFuture<U> thenApplyAsync(Function<? super R,? extends U>, java.util.concurrent.Executor) ,public CompletableFuture<V> thenCombine(CompletionStage<? extends U>, BiFunction<? super R,? super U,? extends V>) ,public CompletableFuture<V> thenCombineAsync(CompletionStage<? extends U>, BiFunction<? super R,? super U,? extends V>) ,public CompletableFuture<V> thenCombineAsync(CompletionStage<? extends U>, BiFunction<? super R,? super U,? extends V>, java.util.concurrent.Executor) ,public CompletableFuture<U> thenCompose(Function<? super R,? extends CompletionStage<U>>) ,public CompletableFuture<U> thenComposeAsync(Function<? super R,? extends CompletionStage<U>>) ,public CompletableFuture<U> thenComposeAsync(Function<? super R,? extends CompletionStage<U>>, java.util.concurrent.Executor) ,public CompletableFuture<java.lang.Void> thenRun(java.lang.Runnable) ,public CompletableFuture<java.lang.Void> thenRunAsync(java.lang.Runnable) ,public CompletableFuture<java.lang.Void> thenRunAsync(java.lang.Runnable, java.util.concurrent.Executor) ,public CompletableFuture<R> toCompletableFuture() ,public java.lang.String toString() ,public CompletableFuture<R> whenComplete(BiConsumer<? super R,? super java.lang.Throwable>) ,public CompletableFuture<R> whenCompleteAsync(BiConsumer<? super R,? super java.lang.Throwable>) ,public CompletableFuture<R> whenCompleteAsync(BiConsumer<? super R,? super java.lang.Throwable>, java.util.concurrent.Executor) <variables>static final int ASYNC,private static final java.util.concurrent.Executor ASYNC_POOL,static final int NESTED,private static final java.lang.invoke.VarHandle NEXT,static final java.util.concurrent.CompletableFuture.AltResult NIL,private static final java.lang.invoke.VarHandle RESULT,private static final java.lang.invoke.VarHandle STACK,static final int SYNC,private static final boolean USE_COMMON_POOL,volatile java.lang.Object result,volatile java.util.concurrent.CompletableFuture.Completion stack