diff --git a/src/main/java/org/dynmap/AsynchronousQueue.java b/src/main/java/org/dynmap/AsynchronousQueue.java index de6bb44c..c84207ad 100644 --- a/src/main/java/org/dynmap/AsynchronousQueue.java +++ b/src/main/java/org/dynmap/AsynchronousQueue.java @@ -16,12 +16,15 @@ public class AsynchronousQueue { private int dequeueTime; private int accelDequeueTime; private int accelDequeueThresh; + private int pendingcnt; + private int pendinglimit; - public AsynchronousQueue(Handler handler, int dequeueTime, int accelDequeueThresh, int accelDequeueTime) { + public AsynchronousQueue(Handler handler, int dequeueTime, int accelDequeueThresh, int accelDequeueTime, int pendinglimit) { this.handler = handler; this.dequeueTime = dequeueTime; this.accelDequeueTime = accelDequeueTime; this.accelDequeueThresh = accelDequeueThresh; + this.pendinglimit = pendinglimit; } public boolean push(T t) { @@ -42,6 +45,16 @@ public class AsynchronousQueue { return t; } } + + public boolean remove(T t) { + synchronized (lock) { + if (set.remove(t)) { + queue.remove(t); + return true; + } + } + return false; + } public int size() { return set.size(); @@ -95,8 +108,23 @@ public class AsynchronousQueue { private void running() { try { while (Thread.currentThread() == thread) { + synchronized(lock) { + while(pendingcnt >= pendinglimit) { + try { + lock.wait(accelDequeueTime); + } catch (InterruptedException ix) { + if(Thread.currentThread() != thread) + return; + throw ix; + } + } + } T t = pop(); if (t != null) { + synchronized(lock) { + pendingcnt++; + } + Log.info("handle(" + t + ")"); handler.handle(t); } if(set.size() >= accelDequeueThresh) @@ -118,4 +146,12 @@ public class AsynchronousQueue { } return true; } + + public void done(T t) { + Log.info("done(" + t + ")"); + synchronized (lock) { + if(pendingcnt > 0) pendingcnt--; + lock.notifyAll(); + } + } } diff --git a/src/main/java/org/dynmap/MapManager.java b/src/main/java/org/dynmap/MapManager.java index 7507218b..319fcb8d 100644 --- a/src/main/java/org/dynmap/MapManager.java +++ b/src/main/java/org/dynmap/MapManager.java @@ -207,6 +207,7 @@ public class MapManager { FullWorldRenderState(MapTile t) { world = getWorld(t.getWorld().getName()); tile0 = t; + Log.info("job(" + t + ")"); cxmin = czmin = Integer.MIN_VALUE; cxmax = czmax = Integer.MAX_VALUE; } @@ -315,6 +316,9 @@ public class MapManager { active_renders.remove(world.world.getName()); } } + else { + tileQueue.done(tile0); + } } public void run() { long tstart = System.currentTimeMillis(); @@ -506,6 +510,8 @@ public class MapManager { tile.render(cache, null); } else { + /* Remove tile from tile queue, since we're processing it already */ + tileQueue.remove(tile); /* Switch to not checking if rendered tile is blank - breaks us on skylands, where tiles can be nominally blank - just work off chunk cache empty */ if (cache.isEmpty() == false) { tile.render(cache, mapname); @@ -626,7 +632,7 @@ public class MapManager { }, (int) (configuration.getDouble("renderinterval", 0.5) * 1000), configuration.getInteger("renderacceleratethreshold", 30), - (int)(configuration.getDouble("renderaccelerateinterval", 0.2) * 1000)); + (int)(configuration.getDouble("renderaccelerateinterval", 0.2) * 1000), 1); /* On dedicated thread, so default to no delays */ timeslice_int = (long)(configuration.getDouble("timesliceinterval", 0.0) * 1000); @@ -1121,6 +1127,10 @@ public class MapManager { ", updated=" + tot.updatedcnt + ", transparent=" + tot.transparentcnt); sender.sendMessage(" Cache hit rate: " + sscache.getHitRate() + "%"); sender.sendMessage(" Triggered update queue size: " + tileQueue.size()); + String act = ""; + for(String wn : active_renders.keySet()) + act += wn + " "; + sender.sendMessage(" Active render jobs: " + act); } /** * Reset statistics