dynmap-neoforge/src/main/java/org/dynmap/AsynchronousQueue.java

112 lines
2.9 KiB
Java

package org.dynmap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.NoSuchElementException;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
public class AsynchronousQueue<T> {
protected static final Logger log = Logger.getLogger("Minecraft");
protected static final String LOG_PREFIX = "[dynmap] ";
private Object lock = new Object();
private Thread thread;
private LinkedList<T> queue = new LinkedList<T>();
private Set<T> set = new HashSet<T>();
private Handler<T> handler;
private int dequeueTime;
public AsynchronousQueue(Handler<T> handler, int dequeueTime) {
this.handler = handler;
this.dequeueTime = dequeueTime;
}
public boolean push(T t) {
synchronized (lock) {
if (set.add(t)) {
queue.addLast(t);
return true;
}
return false;
}
}
private T pop() {
synchronized (lock) {
try {
T t = queue.removeFirst();
if (!set.remove(t)) {
// This should never happen.
}
return t;
} catch (NoSuchElementException e) {
return null;
}
}
}
public int size() {
return set.size();
}
public void start() {
synchronized (lock) {
thread = new Thread(new Runnable() {
@Override
public void run() {
running();
}
});
thread.start();
try {
thread.setPriority(Thread.MIN_PRIORITY);
} catch (SecurityException e) {
log.info(LOG_PREFIX + "Failed to set minimum priority for worker thread!");
}
}
}
public void stop() {
synchronized (lock) {
if (thread == null)
return;
Thread oldThread = thread;
thread = null;
log.info(LOG_PREFIX + "Stopping map renderer...");
oldThread.interrupt();
try {
oldThread.join(1000);
} catch (InterruptedException e) {
log.info(LOG_PREFIX + "Waiting for map renderer to stop is interrupted");
}
}
}
private void running() {
try {
while (Thread.currentThread() == thread) {
T t = pop();
if (t != null) {
handler.handle(t);
}
sleep(dequeueTime);
}
} catch (Exception ex) {
log.log(Level.SEVERE, LOG_PREFIX + "Exception on rendering-thread", ex);
}
}
private boolean sleep(int time) {
try {
Thread.sleep(time);
} catch (InterruptedException e) {
return false;
}
return true;
}
}