net.diversionmc.async.schedule.Scheduler Maven / Gradle / Ivy
package net.diversionmc.async.schedule;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Consumer;
import static java.lang.System.nanoTime;
import static java.util.concurrent.TimeUnit.NANOSECONDS;
import static net.diversionmc.async.schedule.ThreadPoolScheduler.SCHEDULER;
/**
* Scheduler assigns a thread to perform an action in.
*/
@FunctionalInterface
public interface Scheduler {
/**
* Schedule to immediately run a task.
*
* @param asyncAction Action to perform.
*/
Future> schedule(Runnable asyncAction);
/**
* Schedule to repeatedly run a task.
* Default implementation is using {@link #schedule(Runnable)} and blocking the thread the task used there.
*
* @param period Period between iterations.
* @param unit Period unit.
* @param asyncAction Action to perform.
*/
default Future> scheduleRepeating(long period, TimeUnit unit, Consumer asyncAction) {
return schedule(() -> {
var iter = new AtomicInteger();
var loop = new LoopState(iter);
while (true) {
long start = nanoTime();
try {
asyncAction.accept(loop);
} catch (Throwable t) {
loop.stop(); // mark as stopped for non-pure function leaky bois
//noinspection ProhibitedExceptionThrown
throw t;
}
if (loop.stopped()) break;
long time = NANOSECONDS.convert(period, unit);
long delta = nanoTime() - start;
if (delta < time) try {
var lock = SCHEDULER.runLock();
if (lock.tryLock(time - delta, NANOSECONDS)) {
loop.stop();
lock.unlock();
break;
}
} catch (InterruptedException ignored) {
}
iter.getAndIncrement();
}
});
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy