@Override
 public void submit() {
   //            final FibersMonitor monitor = fiber.getMonitor();
   //            if (monitor != null & fiber.getState() != Strand.State.STARTED)
   //                monitor.fiberResumed();
   if (getPool() == fjPool) fork();
   else fjPool.submit(this);
 }
  private FiberForkJoinScheduler(
      ForkJoinPool fjPool, FiberTimedScheduler timeService, boolean detailedInfo) {
    super(
        fjPool instanceof MonitoredForkJoinPool ? ((MonitoredForkJoinPool) fjPool).getName() : null,
        (fjPool instanceof MonitoredForkJoinPool
                && ((MonitoredForkJoinPool) fjPool).getMonitor() != null)
            ? MonitorType.JMX
            : MonitorType.NONE,
        detailedInfo);
    if (!fjPool.getAsyncMode()) throw new IllegalArgumentException("ForkJoinPool is not async");
    this.fjPool = fjPool;

    this.timer = timeService != null ? timeService : createTimer(fjPool, getMonitor());
  }
 // waits for the job to finish execution (when called on a canceled job in the middle of the
 // execution, wait for finish)
 @Override
 public void waitForCompletion(int millis)
     throws InterruptedException, ExecutionException, TimeoutException {
   while (!isDone()) {
     try {
       myForkJoinTask.get(millis, TimeUnit.MILLISECONDS);
       break;
     } catch (CancellationException e) {
       // was canceled in the middle of execution
       // can't do anything but wait. help other tasks in the meantime
       if (Thread.currentThread()
           instanceof
           ForkJoinWorkerThread) { // if called outside FJP the FJTask.fork() starts up
         // commonPool which is undesirable
         pool.awaitQuiescence(millis, TimeUnit.MILLISECONDS);
       }
     }
   }
 }
  @Override
  public <T> boolean invokeConcurrentlyUnderProgress(
      @NotNull final List<T> things,
      ProgressIndicator progress,
      boolean runInReadAction,
      boolean failFastOnAcquireReadAction,
      @NotNull final Processor<? super T> thingProcessor)
      throws ProcessCanceledException {
    // supply our own indicator even if we haven't given one - to support cancellation
    final ProgressIndicator wrapper =
        progress == null
            ? new AbstractProgressIndicatorBase()
            : new SensitiveProgressWrapper(progress);

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

    ApplierCompleter<T> applier =
        new ApplierCompleter<>(
            null, runInReadAction, wrapper, things, thingProcessor, 0, things.size(), null);
    try {
      pool.invoke(applier);
      if (applier.throwable != null) throw applier.throwable;
    } catch (ApplierCompleter.ComputationAbortedException e) {
      return false;
    } catch (ProcessCanceledException e) {
      // task1.processor returns false and the task cancels the indicator
      // then task2 calls checkCancel() and get here
      return false;
    } catch (RuntimeException | Error e) {
      throw e;
    } catch (Throwable e) {
      throw new RuntimeException(e);
    }
    assert applier.isDone();
    return applier.completeTaskWhichFailToAcquireReadAction();
  }
 @Override
 protected int getQueueLength() {
   return fjPool.getQueuedSubmissionCount();
 }
  /**
   * Process all elements from the {@code failedToProcess} and then {@code things} concurrently in
   * the underlying pool. Processing happens concurrently maintaining {@code
   * JobSchedulerImpl.CORES_COUNT} parallelism. Stop when {@code tombStone} element is occurred. If
   * was unable to process some element, add it back to the {@code failedToProcess} queue.
   *
   * @return true if all elements processed successfully, false if at least one processor returned
   *     false or exception occurred
   */
  public <T> boolean processQueue(
      @NotNull final BlockingQueue<T> things,
      @NotNull final Queue<T> failedToProcess,
      @NotNull final ProgressIndicator progress,
      @NotNull final T tombStone,
      @NotNull final Processor<? super T> thingProcessor) {
    class MyTask implements Callable<Boolean> {
      private final int mySeq;
      private boolean result;

      private MyTask(int seq) {
        mySeq = seq;
      }

      @Override
      public Boolean call() throws Exception {
        ProgressManager.getInstance()
            .executeProcessUnderProgress(
                () -> {
                  try {
                    while (true) {
                      progress.checkCanceled();
                      T element = failedToProcess.poll();
                      if (element == null) element = things.take();

                      if (element == tombStone) {
                        things.offer(element);
                        result = true;
                        break;
                      }
                      try {
                        if (!thingProcessor.process(element)) {
                          result = false;
                          break;
                        }
                      } catch (RuntimeException e) {
                        failedToProcess.add(element);
                        throw e;
                      }
                    }
                  } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                  }
                },
                progress);
        return result;
      }

      @Override
      public String toString() {
        return super.toString() + " seq=" + mySeq;
      }
    }

    boolean isSmallEnough = things.contains(tombStone);
    if (isSmallEnough) {
      try {
        // do not distribute for small queues
        return new MyTask(0).call();
      } catch (RuntimeException e) {
        throw e;
      } catch (Exception e) {
        throw new RuntimeException(e);
      }
    }

    List<ForkJoinTask<Boolean>> tasks = new ArrayList<>();
    for (int i = 0; i < JobSchedulerImpl.CORES_COUNT; i++) {
      tasks.add(pool.submit(new MyTask(i)));
    }

    boolean result = true;
    RuntimeException exception = null;
    for (ForkJoinTask<Boolean> task : tasks) {
      try {
        result &= task.join();
      } catch (RuntimeException e) {
        exception = e;
      }
    }
    if (exception != null) {
      throw exception;
    }
    return result;
  }
 private void submit() {
   pool.submit(myForkJoinTask);
 }