package org.sef4j.core.helpers.senders;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import org.sef4j.core.api.EventSender;
/**
* in-memory cyclic buffer EventSender : append events in cyclic array
* this class is thread-safe, and offer operation to atomically "clearAndGet" event list
*
*/
public class InMemoryCyclicEventSender<T> implements EventSender<T> {
public static final int DEFAUT_LEN = 50;
private Object lock = new Object();
private int maxEventLen;
private int currIndex;
private int currEventsLen;
private Object/*T*/[] events;
// ------------------------------------------------------------------------
public InMemoryCyclicEventSender() {
this(DEFAUT_LEN);
}
public InMemoryCyclicEventSender(int len) {
this.maxEventLen = len;
this.events = new Object[len];
}
// ------------------------------------------------------------------------
public int getMaxEventLen() {
return maxEventLen;
}
@Override
public void sendEvent(T event) {
synchronized(lock) {
doSendEvent(event);
}
}
@Override
public void sendEvents(Collection<T> events) {
synchronized(lock) {
for(T event : events) {
doSendEvent(event);
}
}
}
protected void doSendEvent(T event) {
currIndex = modulo(currIndex + 1);
if (events[currIndex] == null) {
currEventsLen++;
}
events[currIndex] = event;
}
@SuppressWarnings("unchecked") //TODO: use typed field "T[] events"
public List<T> clearAndGet() {
synchronized(lock) {
List<T> res = new ArrayList<T>(currEventsLen);
if (currEventsLen != 0) {
int index = modulo(currIndex - currEventsLen + 1);
for (int c = 0; c < currEventsLen; c++, index=modulo(index+1)) {
res.add((T) events[index]);
events[index] = null;
}
currEventsLen = 0;
currIndex=0;
}
return res;
}
}
@SuppressWarnings("unchecked") //TODO: use typed field "T[] events"
public List<T> getCopy() {
synchronized(lock) {
List<T> res = new ArrayList<T>(currEventsLen);
if (currEventsLen != 0) {
int index = modulo(currIndex - currEventsLen + 1);
for (int c = 0; c < currEventsLen; c++, index=modulo(index+1)) {
res.add((T) events[index]);
}
}
return res;
}
}
private int modulo(int i) {
if (i < 0) return i+maxEventLen;
else if (i >= maxEventLen) return i-maxEventLen;
else return i;
}
}