package org.threadly.concurrent.wrapper.compatibility;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.Delayed;
import java.util.concurrent.TimeUnit;
import org.threadly.concurrent.PriorityScheduler;
import org.threadly.concurrent.TaskPriority;
import org.threadly.concurrent.ThreadlyInternalAccessor;
import org.threadly.concurrent.future.ListenableFutureTask;
import org.threadly.concurrent.future.ListenableRunnableFuture;
import org.threadly.concurrent.future.ListenableScheduledFuture;
import org.threadly.concurrent.future.ScheduledFutureDelegate;
import org.threadly.concurrent.wrapper.PrioritySchedulerDefaultPriorityWrapper;
/**
* This is a wrapper for {@link PriorityScheduler} to be a drop in replacement for any
* {@link java.util.concurrent.ScheduledExecutorService} (AKA the
* {@link java.util.concurrent.ScheduledThreadPoolExecutor}
* interface). It does make some performance sacrifices to adhere to this interface, but those are
* pretty minimal. The largest compromise in here is easily scheduleAtFixedRate (which you should
* read the javadocs for if you need).
*
* @since 4.6.0 (since 1.0.0 as org.threadly.concurrent.PriorityScheduledExecutorServiceWrapper)
*/
public class PrioritySchedulerServiceWrapper extends AbstractExecutorServiceWrapper {
protected final PriorityScheduler pScheduler;
protected final TaskPriority taskPriority;
/**
* Constructs a new wrapper to adhere to the
* {@link java.util.concurrent.ScheduledExecutorService} interface.
*
* @param scheduler {@link PriorityScheduler} implementation to rely on
*/
public PrioritySchedulerServiceWrapper(PriorityScheduler scheduler) {
this(scheduler, null);
}
/**
* Constructs a new wrapper to adhere to the
* {@link java.util.concurrent.ScheduledExecutorService} interface.
*
* @param scheduler {@link PriorityScheduler} implementation to rely on
* @param taskPriority Priority for all tasks submitted to the parent scheduler
*/
public PrioritySchedulerServiceWrapper(PriorityScheduler scheduler, TaskPriority taskPriority) {
super(taskPriority == null || taskPriority == scheduler.getDefaultPriority() ?
scheduler : new PrioritySchedulerDefaultPriorityWrapper(scheduler, taskPriority));
this.pScheduler = scheduler;
this.taskPriority = taskPriority == null ? scheduler.getDefaultPriority() : taskPriority;
}
@Override
public void shutdown() {
pScheduler.shutdown();
}
/**
* This call will stop the processor as quick as possible. Any tasks which are awaiting
* execution will be canceled and returned as a result to this call.
* <p>
* Unlike {@link java.util.concurrent.ExecutorService} implementation there is no attempt to
* stop any currently execution tasks.
* <p>
* This method does not wait for actively executing tasks toterminate. Use
* {@link #awaitTermination awaitTermination} to do that.
*
* @return list of tasks that never commenced execution
*/
@Override
public List<Runnable> shutdownNow() {
return pScheduler.shutdownNow();
}
@Override
public boolean isTerminated() {
return scheduler.isShutdown() &&
pScheduler.getCurrentPoolSize() == 0;
}
@Override
public boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException {
return pScheduler.awaitTermination(unit.toMillis(timeout));
}
@Override
protected ListenableScheduledFuture<?> schedule(Runnable task, long delayInMillis) {
ListenableRunnableFuture<Void> taskFuture = new ListenableFutureTask<>(false, task);
Delayed d = ThreadlyInternalAccessor.doScheduleAndGetDelayed(pScheduler, taskFuture,
taskPriority, delayInMillis);
return new ScheduledFutureDelegate<>(taskFuture, d);
}
@Override
protected <V> ListenableScheduledFuture<V> schedule(Callable<V> callable, long delayInMillis) {
ListenableRunnableFuture<V> taskFuture = new ListenableFutureTask<>(false, callable);
Delayed d = ThreadlyInternalAccessor.doScheduleAndGetDelayed(pScheduler, taskFuture,
taskPriority, delayInMillis);
return new ScheduledFutureDelegate<>(taskFuture, d);
}
@Override
protected ListenableScheduledFuture<?> scheduleWithFixedDelay(Runnable task,
long initialDelay, long delayInMs) {
// wrap the task to ensure the correct behavior on exceptions
task = new ThrowableHandlingRecurringRunnable(scheduler, task);
ListenableRunnableFuture<Void> lft = new CancelRemovingListenableFutureTask<>(scheduler, true, task);
Delayed d = ThreadlyInternalAccessor.doScheduleWithFixedDelayAndGetDelayed(pScheduler,
lft, taskPriority,
initialDelay,
delayInMs);
return new ScheduledFutureDelegate<>(lft, d);
}
@Override
protected ListenableScheduledFuture<?> scheduleAtFixedRate(Runnable task,
long initialDelay, long periodInMillis) {
// wrap the task to ensure the correct behavior on exceptions
task = new ThrowableHandlingRecurringRunnable(pScheduler, task);
ListenableRunnableFuture<Void> lft = new CancelRemovingListenableFutureTask<>(scheduler, true, task);
Delayed d = ThreadlyInternalAccessor.doScheduleAtFixedRateAndGetDelayed(pScheduler,
lft, taskPriority,
initialDelay,
periodInMillis);
return new ScheduledFutureDelegate<>(lft, d);
}
}