private boolean waitForOtherThreadsToFinishProcessing(@NotNull final Iterator<T> subClassIterator) {
    // Found nothing, have to wait for other threads because:
    // The first thread comes and takes a class off the queue to search for inheritors,
    // the second thread comes and sees there is no classes in the queue.
    // The second thread should not return nothing, it should wait for the first thread to finish instead.
    //
    // Wait within managedBlock to signal FJP this thread is locked (to avoid thread starvation and deadlocks)
    AtomicBoolean hasNext = new AtomicBoolean();
    try {
      ForkJoinPool.managedBlock(new ForkJoinPool.ManagedBlocker() {
        @Override
        public boolean block() {
          while (!currentlyProcessingClasses.isUp()) {
            ProgressManager.checkCanceled();
            currentlyProcessingClasses.waitFor(1); // wait until other threads process their classes before giving up
          }
          return isReleasable();
        }

        @Override
        public boolean isReleasable() {
          synchronized (lock) {
            // other thread produced something or all of them reached the end of list
            boolean producedSomething = subClassIterator.hasNext();
            hasNext.set(producedSomething); // store the result to avoid locking again after exit
            return producedSomething || !candidatesToFindSubclassesIterator.hasNext() || classesBeingProcessed.isEmpty();
          }
        }
      });
    }
    catch (InterruptedException e) {
      throw new RuntimeException(e);
    }
    return hasNext.get();
  }
private boolean waitForOtherThreadsToFinishProcessing(@NotNull final Iterator<T> subClassIterator)