package com.replaymod.render.utils; import com.google.common.base.Preconditions; import java.util.Collection; import java.util.HashSet; import java.util.Iterator; import java.util.Set; import java.util.concurrent.PriorityBlockingQueue; import java.util.concurrent.TimeUnit; public class JailingQueue extends PriorityBlockingQueue { private final PriorityBlockingQueue delegate; private final Set jailed = new HashSet(); public JailingQueue(PriorityBlockingQueue delegate) { this.delegate = delegate; } public synchronized void jail(int atLeast) { while (jailed.size() < atLeast) { try { wait(); } catch (InterruptedException e) { Thread.interrupted(); } } } public synchronized void free(Thread thread) { Preconditions.checkState(jailed.remove(thread), "Thread is not jailed."); thread.interrupt(); } public synchronized void freeAll() { jailed.clear(); notifyAll(); } private synchronized void tryAccess() { jailed.add(Thread.currentThread()); notifyAll(); while (jailed.contains(Thread.currentThread())) { try { wait(); } catch (InterruptedException e) { Thread.interrupted(); } } } @Override public Iterator iterator() { tryAccess(); return delegate.iterator(); } @Override public int size() { tryAccess(); return delegate.size(); } @Override public void put(T t) { tryAccess(); delegate.put(t); } @Override public boolean offer(T t, long timeout, TimeUnit unit) { tryAccess(); return delegate.offer(t, timeout, unit); } @Override public T take() throws InterruptedException { tryAccess(); return delegate.take(); } @Override public T poll(long timeout, TimeUnit unit) throws InterruptedException { tryAccess(); return delegate.poll(timeout, unit); } @Override public int remainingCapacity() { tryAccess(); return delegate.remainingCapacity(); } @Override public int drainTo(Collection c) { tryAccess(); return delegate.drainTo(c); } @Override public int drainTo(Collection c, int maxElements) { tryAccess(); return delegate.drainTo(c, maxElements); } @Override public boolean offer(T t) { tryAccess(); return delegate.offer(t); } @Override public T poll() { tryAccess(); return delegate.poll(); } @Override public T peek() { tryAccess(); return delegate.peek(); } }