public static <T> T awaitWithCheckCanceled(@NotNull Future<T> future, @Nullable ProgressIndicator indicator) {
    int rejectedExecutions = 0;
    while (true) {
      checkCancelledEvenWithPCEDisabled(indicator);
      try {
        return future.get(ConcurrencyUtil.DEFAULT_TIMEOUT_MS, TimeUnit.MILLISECONDS);
      }
      catch (TimeoutException ignore) {
      }
      //TODO RC: in a non-cancellable section we could still (re-)throw a (P)CE if the _awaited_ code gets cancelled
      //         (nowadays it is mistakenly considered an error) -- [Danila et all, private conversation]
      catch (RejectedExecutionException ree) {
        //EA-225412: FJP throws REE (which propagates through futures) e.g. when FJP reaches max
        // threads while compensating for too many managedBlockers -- or when it is shutdown.

        //This branch creates a risk of infinite loop -- i.e. if the current thread itself is somehow
        // responsible for FJP resource exhaustion, hence can't release anything, each consequent
        // future.get() will throw the same REE again and again. So let's limit retries:
        rejectedExecutions++;
        if (rejectedExecutions > MAX_REJECTED_EXECUTIONS_BEFORE_CANCELLATION) {
          //RC: It would be clearer to rethrow ree itself -- but I doubt many callers are ready for it,
          //    while all callers are ready for PCE, hence...
          throw new ProcessCanceledException(ree);
        }
      }
      catch (InterruptedException e) {
        throw new ProcessCanceledException(e);
      }
      catch (Throwable e) {
        Throwable cause = e.getCause();
        if (cause instanceof ProcessCanceledException) {
          throw (ProcessCanceledException)cause;
        }
        if (cause instanceof CancellationException) {
          throw new ProcessCanceledException(cause);
        }
        ExceptionUtil.rethrow(e);
      }
    }
  }
public static <T> T awaitWithCheckCanceled(@NotNull Future<T> future, @Nullable ProgressIndicator indicator)