@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); }