package ch.x42.terye.observation;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class ObservationDispatcher implements Runnable {
private final Logger logger = LoggerFactory.getLogger(getClass());
private Thread thread;
private BlockingQueue<EventCollection> queue;
private Set<EventConsumer> consumers;
private Object lock;
public ObservationDispatcher() {
thread = new Thread(this, "ObservationManager");
thread.setDaemon(true);
queue = new LinkedBlockingQueue<EventCollection>();
consumers = new HashSet<EventConsumer>();
lock = new Object();
thread.start();
}
protected void addConsumer(EventConsumer consumer) {
synchronized (lock) {
consumers.add(consumer);
}
}
protected void removeConsumer(EventConsumer consumer) {
synchronized (lock) {
consumers.remove(consumer);
}
}
protected void dispatchEvents(EventCollection events) {
try {
queue.put(events);
} catch (InterruptedException e) {
logger.warn("Interrupted while putting to event queue");
}
}
protected Set<EventConsumer> getConsumers() {
return Collections.unmodifiableSet(consumers);
}
@Override
public void run() {
while (true) {
try {
EventCollection events = queue.take();
// XXX: don't lock during whole notification process?
synchronized (lock) {
for (EventConsumer consumer : consumers) {
try {
consumer.consume(events);
} catch (Throwable e) {
logger.warn("Consumer threw an exception: {}", e);
}
}
}
} catch (InterruptedException e) {
logger.warn("Interrupted while taking from event queue");
}
}
}
}