@Override
  public <T> boolean invokeConcurrentlyUnderProgress(@NotNull List<? extends T> things,
                                                     ProgressIndicator progress,
                                                     boolean runInReadAction,
                                                     boolean failFastOnAcquireReadAction,
                                                     @NotNull Processor<? super T> thingProcessor) throws ProcessCanceledException {
    // supply our own indicator even if we haven't given one - to support cancellation
    // use StandardProgressIndicator by default to avoid assertion in SensitiveProgressWrapper() ctr later
    ProgressIndicator wrapper = progress == null ? new StandardProgressIndicatorBase() : new SensitiveProgressWrapper(progress);

    Boolean result = processImmediatelyIfTooFew(things, wrapper, runInReadAction, thingProcessor);
    if (result != null) return result;

    ProgressManager pm = ProgressManager.getInstance();
    Processor<? super T> processor = ((CoreProgressManager)pm).isCurrentThreadPrioritized()
                                     ? t -> pm.computePrioritized(() -> thingProcessor.process(t))
                                     : thingProcessor;
    processor = FileBasedIndex.getInstance().inheritCurrentDumbAccessType(processor);
    processor = ClientId.decorateProcessor(processor);

    List<ApplierCompleter<T>> failedSubTasks = Collections.synchronizedList(new ArrayList<>());
    ApplierCompleter<T> applier = new ApplierCompleter<>(null, runInReadAction, failFastOnAcquireReadAction, wrapper, things, processor, 0, things.size(), failedSubTasks, null);
    try {
      if (progress != null && isAlreadyUnder(progress)) {
        // there must be nested invokeConcurrentlies.
        // In this case, try to avoid placing tasks to the FJP queue because extra applier.get() or pool.invoke() can cause pool over-compensation with too many workers
        applier.compute();
      }
      else {
        ForkJoinPool.commonPool().execute(applier);
      }
      // call checkCanceled a bit more often than .invoke()
      while (!applier.isDone()) {
        ProgressManager.checkCanceled();
        try {
          if (joinWithoutTimeout) {
            applier.get();
          } else {
            // does automatic compensation against starvation (in ForkJoinPool.awaitJoin)
            applier.get(10, TimeUnit.MILLISECONDS);
          }
        }
        catch (TimeoutException ignored) {
        }
        catch (ExecutionException e) {
          throw e.getCause();
        }
      }
      if (applier.throwable != null) {
        throw applier.throwable;
      }
    }
    catch (ApplierCompleter.ComputationAbortedException e) {
      // one of the processors returned false
      return false;
    }
    catch (ApplicationUtil.CannotRunReadActionException e) {
      // failFastOnAcquireReadAction==true and one of the processors called runReadAction() during the pending write action
      throw e;
    }
    catch (ProcessCanceledException e) {
      // We should distinguish between genuine 'progress' cancellation and optimization when
      // task1.processor returns false and the task cancels the indicator then task2 calls checkCancel() and get here.
      // The former requires to re-throw PCE, the latter should just return false.
      if (progress != null) {
        progress.checkCanceled();
      }
      ProgressManager.checkCanceled();
      return false;
    }
    catch (RuntimeException | Error e) {
      throw e;
    }
    catch (Throwable e) {
      throw new RuntimeException(e);
    }
    return applier.completeTaskWhichFailToAcquireReadAction();
  }
@Override
  public <T> boolean invokeConcurrentlyUnderProgress(@NotNull List<? extends T> things,
                                                     ProgressIndicator progress,
                                                     boolean runInReadAction,
                                                     boolean failFastOnAcquireReadAction,
                                                     @NotNull Processor<? super T> thingProcessor)