/** * This is called once a task is ready to be executed (or if unable to execute immediately, * queued). In addition to the task itself, this function takes in any future which represents * task execution (if available, otherwise {@code null}). Passing in as a separate argument * allows us to avoid a {@code instanceof} check, but does require it to be specified for * pre-future listener completion support. * * @param task Task to be executed * @param future Future to represent task completion or {@code null} if not available */ protected void executeOrQueue(Runnable task, ListenableFuture<?> future) { if (limitFutureListenersExecution || future == null) { executeOrQueueWrapper(new LimiterRunnableWrapper(task)); } else { // we will release the limit restriction as soon as the future completes. // listeners should be invoked in order, so we just need to be the first listener here // We add a `SameThreadSubmitterExecutor` so that we get executed first as if it was async future.addListener(this::releaseExecutionLimit, SameThreadSubmitterExecutor.instance()); if (canRunTask()) { executor.execute(task); } else { addToQueue(new TransparentRunnableContainer(task)); } } }
/** * This is called once a task is ready to be executed (or if unable to execute immediately, * queued). In addition to the task itself, this function takes in any future which represents * task execution (if available, otherwise {@code null}). Passing in as a separate argument * allows us to avoid a {@code instanceof} check, but does require it to be specified for * pre-future listener completion support. * * @param task Task to be executed * @param future Future to represent task completion or {@code null} if not available */ protected void executeOrQueue(Runnable task, ListenableFuture<?> future) { if (limitFutureListenersExecution || future == null) { executeOrQueueWrapper(new LimiterRunnableWrapper(task)); } else { // we will release the limit restriction as soon as the future completes. // listeners should be invoked in order, so we just need to be the first listener here // We add a `SameThreadSubmitterExecutor` so that we get executed first as if it was async future.addListener(this::releaseExecutionLimit, SameThreadSubmitterExecutor.instance()); if (canRunTask()) { executor.execute(task); } else { addToQueue(new TransparentRunnableContainer(task)); } } }