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.SingleThreadScheduler; import org.threadly.concurrent.TaskPriority; import org.threadly.concurrent.ThreadlyInternalAccessor; import org.threadly.concurrent.future.ListenableFutureTask; import org.threadly.concurrent.future.ListenableScheduledFuture; import org.threadly.concurrent.future.ScheduledFutureDelegate; import org.threadly.concurrent.wrapper.PrioritySchedulerDefaultPriorityWrapper; /** * This is a wrapper for {@link SingleThreadScheduler} 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 2.0.0 at org.threadly.concurrent) */ public class SingleThreadSchedulerServiceWrapper extends AbstractExecutorServiceWrapper { protected final SingleThreadScheduler singleThreadScheduler; protected final TaskPriority taskPriority; /** * Constructs a new wrapper to adhere to the * {@link java.util.concurrent.ScheduledExecutorService} interface. * * @param scheduler scheduler implementation to rely on */ public SingleThreadSchedulerServiceWrapper(SingleThreadScheduler scheduler) { this(scheduler, null); } /** * Constructs a new wrapper to adhere to the * {@link java.util.concurrent.ScheduledExecutorService} interface. * * @param scheduler scheduler implementation to rely on * @param taskPriority Priority for all tasks submitted to the parent scheduler */ public SingleThreadSchedulerServiceWrapper(SingleThreadScheduler scheduler, TaskPriority taskPriority) { super(taskPriority == null || taskPriority == scheduler.getDefaultPriority() ? scheduler : new PrioritySchedulerDefaultPriorityWrapper(scheduler, taskPriority)); this.singleThreadScheduler = scheduler; this.taskPriority = taskPriority == null ? scheduler.getDefaultPriority() : taskPriority; } @Override public void shutdown() { singleThreadScheduler.shutdown(); } @Override public List<Runnable> shutdownNow() { return singleThreadScheduler.shutdownNow(); } @Override public boolean isTerminated() { return singleThreadScheduler.isTerminated(); } @Override public boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException { return singleThreadScheduler.awaitTermination(unit.toMillis(timeout)); } @Override protected ListenableScheduledFuture<?> schedule(Runnable task, long delayInMillis) { ListenableFutureTask<Void> lft = new ListenableFutureTask<>(false, task); Delayed d = ThreadlyInternalAccessor.doScheduleAndGetDelayed(singleThreadScheduler, lft, taskPriority, delayInMillis); return new ScheduledFutureDelegate<>(lft, d); } @Override protected <V> ListenableScheduledFuture<V> schedule(Callable<V> callable, long delayInMillis) { ListenableFutureTask<V> lft = new ListenableFutureTask<>(false, callable); Delayed d = ThreadlyInternalAccessor.doScheduleAndGetDelayed(singleThreadScheduler, lft, taskPriority, delayInMillis); return new ScheduledFutureDelegate<>(lft, d); } @Override protected ListenableScheduledFuture<?> scheduleWithFixedDelay(Runnable task, long initialDelay, long delayInMillis) { // wrap the task to ensure the correct behavior on exceptions task = new ThrowableHandlingRecurringRunnable(scheduler, task); ListenableFutureTask<Void> lft = new CancelRemovingListenableFutureTask<>(scheduler, true, task); Delayed d = ThreadlyInternalAccessor.doScheduleWithFixedDelayAndGetDelayed(singleThreadScheduler, lft, taskPriority, initialDelay, delayInMillis); 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(scheduler, task); ListenableFutureTask<Void> lft = new CancelRemovingListenableFutureTask<>(scheduler, true, task); Delayed d = ThreadlyInternalAccessor.doScheduleAtFixedRateAndGetDelayed(singleThreadScheduler, lft, taskPriority, initialDelay, periodInMillis); return new ScheduledFutureDelegate<>(lft, d); } }