/* The contents of this file are subject to the license and copyright terms
* detailed in the license directory at the root of the source tree (also
* available online at http://fedora-commons.org/license/).
*/
package org.fcrepo.server.observer;
import java.util.Set;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.CopyOnWriteArraySet;
import java.util.concurrent.LinkedBlockingQueue;
/**
* A threaded FIFO queue to improve performance of updates to Observers.
*
* @author Edwin Shin
* @version $Id$
* @see <a
* href="http://www.javaworld.com/javaworld/javatips/jw-javatip29.html">http://www.javaworld.com/javaworld/javatips/jw-javatip29.html</a>
*/
public class ObserverQueue
implements Publisher, Subscriber, Runnable {
private final Set<Subscriber> subscribers;
private BlockingQueue<Object> messages;
public ObserverQueue() {
subscribers = new CopyOnWriteArraySet<Subscriber>();
messages = new LinkedBlockingQueue<Object>();
}
public void update(Publisher o, Object arg) {
messages.add(arg);
}
/*
* (non-Javadoc)
*
* @see java.lang.Runnable#run()
*/
public void run() {
while (true) {
Object obj;
try {
obj = messages.take();
notifySubscribers(obj);
} catch (InterruptedException e) {
// restore interrupted status
Thread.currentThread().interrupt();
}
}
}
public void addSubscriber(Subscriber obs) {
subscribers.add(obs);
}
public void notifySubscribers() {
notifySubscribers(null);
}
/**
* Notify subscribers. Notifications are issued using a copy of the
* subscriber list. Therefore, Subscribers should not assume that a
* notification will not be received even after calling removeSubscriber.
* {@inheritDoc}
*/
public void notifySubscribers(Object o) {
for (Subscriber subscriber : subscribers) {
subscriber.update(this, o);
}
}
public void removeSubscriber(Subscriber obs) {
subscribers.remove(obs);
}
}