com.ocadotechnology.event.scheduling.EventScheduler Maven / Gradle / Ivy
/*
* Copyright © 2017-2023 Ocado (Ocava)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.ocadotechnology.event.scheduling;
import java.util.function.Consumer;
import com.ocadotechnology.time.TimeProvider;
public interface EventScheduler {
double ONE_CLOCK_CYCLE = 0.001;
boolean hasOnlyDaemonEvents();
/**
* Signal to the scheduler that a "safe shutdown" should be started.
*
* Once called, doAt events will be rejected (return null) and existing doAt events will NOT be executed.
* doNow events are unaffected (will continue to execute and can be scheduled).
* This allows existing events to 'flush' through (including scheduling more doNow events),
* and other processes to schedule doNow events as part of the shutdown sequence.
*
* The scheduler will continue to run like this until {@link #stop()} is called, at which point
* when the doNow queue becomes empty, the scheduler will actually stop.
*
* Calling prepareToStop more than once has no additional effect.
*/
void prepareToStop();
/**
* Default (previous) behaviour: calling stop will prevent any more "now" or "at" events from starting.
* Calls to doNow and doAt will return null until the scheduler is set to idle.
*
* New behaviour: if {@link #prepareToStop()} has been called (and {@link #isStopping()} returns true,
* then existing "now" events will be called until the "now" queue is empty (flushing phase).
* If more "now" events are added during this time, they will also run.
* Calls to doNow will (obviously) succeed, but calls to doAt will return null.
* Once the "now" queue is empty, the scheduler will stop (and doNow calls will also return null).
* The new behaviour is intended as a "safe shutdown".
*
* Calling stop more than once has no additional effect.
*/
void stop();
/** @return true if {@link #prepareToStop()} has been called, but {@link #stop()} has not (yet). */
boolean isStopping();
TimeProvider getTimeProvider();
default Cancelable doNow(Runnable r) {
return doNow(r, r.getClass().getName());
}
default Cancelable doAt(double time, Runnable r) {
return doAt(time, r, r.getClass().getName());
}
default Cancelable doAtOrNow(double time, Runnable r) {
return doAtOrNow(time, r, r.getClass().getName());
}
Cancelable doNow(Runnable r, String description);
default Cancelable doAt(double time, Runnable r, String description) {
return doAt(time, r, description, false);
}
/**
* Creates a Cancelable Event using the provided Runnable, and glags the Event as a 'daemon' task. Does NOT imply
* any repetition on the event. Use {@link RepeatingRunnable} to create repeating events.
*
* @param time - the time of the event
* @param r - the action to perform at the indicated time
* @param description - Human-readable String description for the task. Important for debugging.
* @return the Cancellable event created.
*/
default Cancelable doAtDaemon(double time, Runnable r, String description) {
return doAt(time, r, description, true);
}
Cancelable doAt(double time, Runnable r, String description, boolean isDaemon);
long getThreadId();
EventSchedulerType getType();
default Cancelable doIn(double delay, Runnable r) {
return doIn(delay, r, r.getClass().getName());
}
default Cancelable doIn(double delay, Runnable r, String description) {
return doIn(delay, t -> r.run(), description);
}
default Cancelable doIn(double delay, Consumer eventTimeConsumingAction, String description) {
double eventTime = getTimeProvider().getTime() + delay;
return doAt(eventTime, () -> eventTimeConsumingAction.accept(eventTime), description);
}
default Cancelable doInDaemon(double delay, Runnable r) {
return doInDaemon(delay, r, r.getClass().getName());
}
default Cancelable doInDaemon(double delay, Runnable r, String description) {
return doInDaemon(delay, t -> r.run(), description);
}
default Cancelable doInDaemon(double delay, Consumer eventTimeConsumingAction, String description) {
double eventTime = getTimeProvider().getTime() + delay;
return doAtDaemon(eventTime, () -> eventTimeConsumingAction.accept(eventTime), description);
}
default Cancelable doAtOrNow(double time, Runnable r, String description) {
return doAtOrNow(time, t -> r.run(), description);
}
default Cancelable doAtOrNow(double time, Consumer eventTimeConsumingAction, String description) {
double now = getTimeProvider().getTime();
if (time > now) {
return doAt(time, () -> eventTimeConsumingAction.accept(time), description);
} else {
return doNow(() -> eventTimeConsumingAction.accept(now), description);
}
}
default boolean isThreadHandoverRequired() {
return Thread.currentThread().getId() != getThreadId();
}
default double getMinimumTimeDelta() {
return ONE_CLOCK_CYCLE;
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy