package jalse.actions; import static jalse.actions.Actions.unschedulableActionContext; import java.util.concurrent.ScheduledThreadPoolExecutor; import java.util.concurrent.TimeUnit; import java.util.logging.Level; import java.util.logging.Logger; /** * An implementation of {@link ActionEngine} based on {@link ScheduledThreadPoolExecutor}. * * @author Elliot Ford * */ public class ThreadPoolActionEngine extends AbstractActionEngine { /** * Thread pool context. * * @author Elliot Ford * * @param <T> * Actor type. */ public class ThreadPoolContext<T> extends AbstractFutureActionContext<T>implements Runnable { private final ActionContext<T> unschedulable; /** * Creates new instance of ThreadPoolContext. * * @param action * Action this context is for. */ protected ThreadPoolContext(final Action<T> action) { super(ThreadPoolActionEngine.this, action, getBindings()); unschedulable = unschedulableActionContext(this); } @Override public void run() { try { getAction().perform(unschedulable); // Execute action } catch (final InterruptedException e) { Thread.currentThread().interrupt(); cancel(); // Just to be sure } catch (final Exception e) { logger.log(Level.WARNING, "Error performing action", e); if (!isPeriodicOnException()) { cancel(); } } } @Override public void schedule() { if (!isDone()) { final ScheduledThreadPoolExecutor stpe = (ScheduledThreadPoolExecutor) executorService; final long initialDelay = getInitialDelay(TimeUnit.NANOSECONDS); if (isPeriodic()) { setFuture(stpe.scheduleAtFixedRate(this, initialDelay, getPeriod(TimeUnit.NANOSECONDS), TimeUnit.NANOSECONDS)); // At rate } else { setFuture(stpe.schedule(this, initialDelay, TimeUnit.NANOSECONDS)); } } } } private static final Logger logger = Logger.getLogger(ThreadPoolActionEngine.class.getName()); /** * Creates a new instance of ThreadPoolActionEngine with the supplied core pool size. * * @param corePoolSize * Number of threads to process actions using. */ public ThreadPoolActionEngine(final int corePoolSize) { super(new ScheduledThreadPoolExecutor(corePoolSize)); } @Override public <T> ThreadPoolContext<T> newContext(final Action<T> action) { return new ThreadPoolContext<>(action); } }