code: @CanIgnoreReturnValue
    // TODO(cpovirk): Consider calling getDone() in our own code.
    public static <V> V getDone(Future<V> 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);
    }
docs: Returns the result of the input {@code Future}, which must have already completed.
  
  <p>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}.
  
  <p>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