package im.actor.runtime.actors.dispatch.queue; import java.util.ArrayList; import java.util.HashMap; import java.util.LinkedList; import java.util.List; import im.actor.runtime.threading.AtomicIntegerCompat; public class QueueCollection<T> { private AtomicIntegerCompat NEXT_ID = im.actor.runtime.Runtime.createAtomicInt(0); private HashMap<Integer, Queue<T>> queues = new HashMap<>(); private LinkedList<Queue<T>> pending = new LinkedList<>(); private ArrayList<QueueCollectionListener> listeners = new ArrayList<>(); public synchronized void addListener(QueueCollectionListener listener) { if (!listeners.contains(listener)) { listeners.add(listener); } } public synchronized void removeListener(QueueCollectionListener listener) { listeners.remove(listener); } public synchronized int spawnQueue() { int id = NEXT_ID.getAndIncrement(); queues.put(id, new Queue<T>(id)); return id; } public synchronized void disposeQueue(int id) { Queue<T> q = queues.remove(id); if (q != null) { pending.remove(q); } } public synchronized void post(int id, T value) { post(id, value, false); } public synchronized void post(int id, T value, boolean isFirst) { Queue<T> queue = queues.get(id); if (queue == null) { return; } boolean wasEmptyPending = pending.isEmpty(); boolean wasEmpty = queue.getQueue().isEmpty(); if (isFirst) { queue.getQueue().add(0, value); } else { queue.getQueue().add(value); } if (wasEmpty && !queue.isLocked()) { pending.add(queue); } if (wasEmptyPending) { for (QueueCollectionListener l : listeners) { l.onChanged(); } } } public synchronized QueueFetchResult<T> fetch() { if (pending.isEmpty()) { return null; } Queue<T> queue = pending.remove(0); queue.setIsLocked(true); T val = queue.getQueue().remove(0); return new QueueFetchResult<>(queue.getId(), val); } public synchronized void returnQueue(QueueFetchResult<T> res) { Queue<T> queue = queues.get(res.getId()); if (queue == null) { return; } queue.setIsLocked(false); if (!queue.getQueue().isEmpty()) { boolean wasEmptyPending = pending.isEmpty(); pending.add(queue); if (wasEmptyPending) { for (QueueCollectionListener l : listeners) { l.onChanged(); } } } } public synchronized List<T> getAllPending(int id) { Queue<T> queue = queues.get(id); if (queue == null) { return new ArrayList<>(); } return new ArrayList<>(queue.getQueue()); } }