public JobHandle submit( Group group, Runnable job, long initialDelayNanos, long reschedulingDelayNanos ) { long now = clock.nanos(); long nextDeadlineNanos = now + initialDelayNanos; ScheduledJobHandle task = new ScheduledJobHandle( this, group, job, nextDeadlineNanos, reschedulingDelayNanos ); enqueueTask( task ); return task; }
ScheduledJobHandle( TimeBasedTaskScheduler scheduler, Group group, Runnable task, long nextDeadlineNanos, long reschedulingDelayNanos ) { this.group = group; this.nextDeadlineNanos = nextDeadlineNanos; handleRelease = new BinaryLatch(); cancelListeners = new CopyOnWriteArrayList<>(); this.task = () -> { try { task.run(); // Use compareAndSet to avoid overriding any cancellation state. if ( compareAndSet( SUBMITTED, RUNNABLE ) && reschedulingDelayNanos > 0 ) { // We only reschedule if the rescheduling delay is greater than zero. // A rescheduling delay of zero means this is a delayed task. // If the rescheduling delay is greater than zero, then this is a recurring task. this.nextDeadlineNanos += reschedulingDelayNanos; scheduler.enqueueTask( this ); } } catch ( Throwable e ) { lastException = e; set( FAILED ); } }; }
@Override public void waitTermination() throws ExecutionException, InterruptedException { handleRelease.await(); JobHandle handleDelegate = this.latestHandle; if ( handleDelegate != null ) { handleDelegate.waitTermination(); } if ( get() == FAILED ) { Throwable exception = this.lastException; if ( exception != null ) { throw new ExecutionException( exception ); } else { throw new CancellationException(); } } }
void submitIfRunnable( ThreadPoolManager pools ) { if ( compareAndSet( RUNNABLE, SUBMITTED ) ) { latestHandle = pools.submit( group, task ); handleRelease.release(); } }
private long scheduleDueTasks( long now ) { if ( delayedTasks.isEmpty() ) { // We have no tasks to run. Park until we're woken up by an enqueueTask() call. return NO_TASKS_PARK; } while ( !stopped && !delayedTasks.isEmpty() && delayedTasks.peek().nextDeadlineNanos <= now ) { ScheduledJobHandle task = delayedTasks.poll(); task.submitIfRunnable( pools ); } return delayedTasks.isEmpty() ? NO_TASKS_PARK : delayedTasks.peek().nextDeadlineNanos - now; }
@Override public void cancel( boolean mayInterruptIfRunning ) { set( FAILED ); JobHandle handle = latestHandle; if ( handle != null ) { handle.cancel( mayInterruptIfRunning ); } for ( CancelListener cancelListener : cancelListeners ) { cancelListener.cancelled( mayInterruptIfRunning ); } // Release the handle to allow waitTermination() to observe the cancellation. handleRelease.release(); }
void submitIfRunnable( ThreadPoolManager pools ) { if ( compareAndSet( RUNNABLE, SUBMITTED ) ) { latestHandle = pools.submit( group, task ); handleRelease.release(); } }
private long scheduleDueTasks( long now ) { if ( delayedTasks.isEmpty() ) { // We have no tasks to run. Park until we're woken up by an enqueueTask() call. return NO_TASKS_PARK; } while ( !stopped && !delayedTasks.isEmpty() && delayedTasks.peek().nextDeadlineNanos <= now ) { ScheduledJobHandle task = delayedTasks.poll(); task.submitIfRunnable( pools ); } return delayedTasks.isEmpty() ? NO_TASKS_PARK : delayedTasks.peek().nextDeadlineNanos - now; }
@Override public void cancel( boolean mayInterruptIfRunning ) { set( FAILED ); JobHandle handle = latestHandle; if ( handle != null ) { handle.cancel( mayInterruptIfRunning ); } for ( CancelListener cancelListener : cancelListeners ) { cancelListener.cancelled( mayInterruptIfRunning ); } // Release the handle to allow waitTermination() to observe the cancellation. handleRelease.release(); }
ScheduledJobHandle( TimeBasedTaskScheduler scheduler, Group group, Runnable task, long nextDeadlineNanos, long reschedulingDelayNanos ) { this.group = group; this.nextDeadlineNanos = nextDeadlineNanos; handleRelease = new BinaryLatch(); cancelListeners = new CopyOnWriteArrayList<>(); this.task = () -> { try { task.run(); // Use compareAndSet to avoid overriding any cancellation state. if ( compareAndSet( SUBMITTED, RUNNABLE ) && reschedulingDelayNanos > 0 ) { // We only reschedule if the rescheduling delay is greater than zero. // A rescheduling delay of zero means this is a delayed task. // If the rescheduling delay is greater than zero, then this is a recurring task. this.nextDeadlineNanos += reschedulingDelayNanos; scheduler.enqueueTask( this ); } } catch ( Throwable e ) { lastException = e; set( FAILED ); } }; }
public JobHandle submit( Group group, Runnable job, long initialDelayNanos, long reschedulingDelayNanos ) { long now = clock.nanos(); long nextDeadlineNanos = now + initialDelayNanos; ScheduledJobHandle task = new ScheduledJobHandle( this, group, job, nextDeadlineNanos, reschedulingDelayNanos ); enqueueTask( task ); return task; }
@Override public void waitTermination() throws ExecutionException, InterruptedException { handleRelease.await(); JobHandle handleDelegate = this.latestHandle; if ( handleDelegate != null ) { handleDelegate.waitTermination(); } if ( get() == FAILED ) { Throwable exception = this.lastException; if ( exception != null ) { throw new ExecutionException( exception ); } else { throw new CancellationException(); } } }