package com.sibo.concurrent;
public interface EventQueue<T> {
void put(T event);
EventBuffer<T> swap(EventBuffer<T> eventBuffer);
boolean isEmpty();
int size();
}
package com.sibo.concurrent;
import java.util.ArrayList;
public class EventBuffer<T> {
private ArrayList<T> events = new ArrayList<>();
public int size() {
return events.size();
}
public T get(int index) {
return events.get(index);
}
public void add(T event) {
events.add(event);
}
public boolean isEmpty() {
return events.isEmpty();
}
public void clear() {
events.clear();
}
}
package com.sibo.concurrent;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class CappedBlockingEventQueue<T> implements EventQueue<T> {
private final Lock lock = new ReentrantLock();
private final Condition empty = lock.newCondition();
private final Condition full = lock.newCondition();
private EventBuffer<T> queue = new EventBuffer<>();
private final int cap;
public CappedBlockingEventQueue(int maxQueueSize) {
this.cap = maxQueueSize;
}
@Override
public void put(T event) {
lock.lock();
try {
while (queue.size() >= cap) {
try {
full.await();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
queue.add(event);
empty.signal();
} finally {
lock.unlock();
}
}
@Override
public EventBuffer<T> swap(EventBuffer<T> eventBuffer) {
lock.lock();
try {
while (queue.isEmpty()) {
try {
empty.await();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
EventBuffer<T> toReturn = queue;
queue = eventBuffer;
full.signalAll();
return toReturn;
} finally {
lock.unlock();
}
}
@Override
public boolean isEmpty() {
lock.lock();
try {
return queue.isEmpty();
} finally {
lock.unlock();
}
}
@Override
public int size() {
lock.lock();
try {
return queue.size();
} finally {
lock.unlock();
}
}
}