package de.tum.in.www1.jReto.util;
import java.util.concurrent.Executor;
/**
* A RepeatedExecutor executes an action repeatedly with a certain delay. On demand, the action can also be triggered immediately or after a short delay.
* */
public class RepeatedExecutor {
private final Runnable action;
private final double regularDelay;
private final double shortDelay;
private final Executor executor;
private boolean isStarted = false;
private Timer timer;
/**
* Constructs a new RepeatableExecutor.
*
* @param action The action to execute.
* @param regularDelay The delay in which the action is executed by default.
* @param shortDelay The delay used when runActionInShortDelay is called.
* @param executor The executor to execute the action with.
* */
public RepeatedExecutor(Runnable action, double regularDelay, double shortDelay, Executor executor) {
this.action = action;
this.regularDelay = regularDelay;
this.shortDelay = shortDelay;
this.executor = executor;
}
/**
* Starts executing the action in regular delays.
* */
public void start() {
if (this.isStarted) return;
this.isStarted = true;
this.resume();
}
/**
* Stops executing the action in regular delays.
* */
public void stop() {
if (!this.isStarted) return;
this.isStarted = false;
this.interrupt();
}
/**
* Runs the action immediately. Resets the timer; the next execution of the action will occur after the regular delay.
* */
public void runActionNow() {
this.resetTimer();
this.executor.execute(new Runnable() {
@Override
public void run() {
RepeatedExecutor.this.action.run();
}
});
}
/**
* Runs the action after the short delay. After this, actions are executed in regular intervals again.
* */
public void runActionInShortDelay() {
this.interrupt();
this.timer = Timer.delay(this.shortDelay, this.executor, new Runnable() {
@Override
public void run() {
RepeatedExecutor.this.action.run();
RepeatedExecutor.this.resume();
}
});
}
private void interrupt() {
if (this.timer != null) this.timer.stop();
this.timer = null;
}
private void resume() {
if (!this.isStarted) return;
this.timer = Timer.repeat(this.regularDelay, this.executor, new Timer.Action() {
@Override
public void run(Timer timer, int executionCount) {
RepeatedExecutor.this.action.run();
}
});
}
private void resetTimer() {
this.interrupt();
this.resume();
}
}