private boolean processFilesConcurrently(
      @NotNull Set<VirtualFile> files,
      @NotNull final ProgressIndicator indicator,
      @NotNull final Processor<VirtualFile> processor) {
    final List<VirtualFile> fileList = new ArrayList<VirtualFile>(files);
    // fine but grabs all CPUs
    // return JobLauncher.getInstance().invokeConcurrentlyUnderProgress(fileList, indicator, false,
    // false, processor);

    int parallelism = CacheUpdateRunner.indexingThreadCount();
    final Callable<Boolean> processFileFromSet =
        () -> {
          final boolean[] result = {true};
          ProgressManager.getInstance()
              .executeProcessUnderProgress(
                  () -> {
                    while (true) {
                      ProgressManager.checkCanceled();
                      VirtualFile file;
                      synchronized (fileList) {
                        file = fileList.isEmpty() ? null : fileList.remove(fileList.size() - 1);
                      }
                      if (file == null) {
                        break;
                      }
                      if (!processor.process(file)) {
                        result[0] = false;
                        break;
                      }
                    }
                  },
                  indicator);
          return result[0];
        };
    List<Future<Boolean>> futures =
        ContainerUtil.map(
            Collections.nCopies(parallelism, ""),
            s -> myApplication.executeOnPooledThread(processFileFromSet));

    List<Boolean> results =
        ContainerUtil.map(
            futures,
            future -> {
              try {
                return future.get();
              } catch (Exception e) {
                LOG.error(e);
              }
              return false;
            });

    return !ContainerUtil.exists(
        results,
        result -> {
          return result != null && !result; // null means PCE
        });
  }