package me.km.scheduler; import java.util.Iterator; import java.util.concurrent.ConcurrentLinkedQueue; import me.hammerle.snuviscript.code.ISnuviLogger; import me.hammerle.snuviscript.code.ISnuviScheduler; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; @OnlyIn(Dist.DEDICATED_SERVER) public class SnuviScheduler implements ISnuviScheduler { private final ISnuviLogger logger; private final ConcurrentLinkedQueue tasks = new ConcurrentLinkedQueue<>(); private final AsyncWorker worker = new AsyncWorker(); private boolean noAdding = false; public SnuviScheduler(ISnuviLogger logger) { this.logger = logger; worker.start(); } public void stop() { noAdding = true; long endTime = System.nanoTime() + 60_000_000_000l; logger.print("Waiting until end of synchronized tasks ..."); while(!tasks.isEmpty() && System.nanoTime() < endTime) { tick(1000); } logger.print("Waiting until end of asynchronous tasks ..."); while(worker.hasWork() && System.nanoTime() < endTime) { try { Thread.sleep(250); } catch(InterruptedException ex) { } } worker.stop(); logger.print("the scheduler is now stopped"); } public void scheduleRepeatingTask(Runnable r, long ticks, long rtimer) { if(noAdding) { return; } tasks.add(new SnuviTask(r, ticks, rtimer)); } @Override public void scheduleTask(Runnable r, long delay) { scheduleRepeatingTask(r, delay, 0); } public void tick() { tick(1); } private void tick(int ticks) { System.out.println("Ticking scheduler"); Iterator iter = tasks.iterator(); long endTime = System.currentTimeMillis() + 25; while(iter.hasNext()) { if(System.currentTimeMillis() > endTime) { logger.print("scheduler has run longer than 25 ms"); break; } SnuviTask task = iter.next(); try { if(task.tick(ticks, noAdding)) { iter.remove(); } } catch(Exception ex) { logger.print("scheduler exception - task will be removed", ex, null, null, null, null); iter.remove(); } } System.out.println("Finished ticking scheduler"); } public void scheduleAsyncTask(Runnable r) { if(noAdding) { return; } worker.add(r); } public boolean hasAsyncWork() { return worker.hasWork(); } }