package ibis.ipl.registry.central.client;
import ibis.ipl.registry.central.Member;
import ibis.util.ThreadPool;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Sends events to clients from the server.
*/
final class IterativeEventPusher extends Thread {
private static final int THREADS = 10;
private class WorkQ {
private List<Member> q;
private int count;
WorkQ(Member[] work) {
// Arrays.asList list does not support remove, so do this "trick"
q = new LinkedList<Member>();
q.addAll(Arrays.asList(work));
count = this.q.size();
}
synchronized Member next() {
if (q.isEmpty()) {
return null;
}
return q.remove(0);
}
synchronized void doneJob() {
count--;
if (count <= 0) {
notifyAll();
}
}
synchronized void waitUntilDone() {
while (count > 0) {
try {
wait();
} catch (InterruptedException e) {
// IGNORE
}
}
}
}
private class EventPusherThread implements Runnable {
WorkQ workQ;
EventPusherThread(WorkQ workQ) {
this.workQ = workQ;
ThreadPool.createNew(this, "event pusher thread");
}
public void run() {
while (true) {
Member work = workQ.next();
if (work == null) {
// done pushing
return;
}
logger.debug("pushing to " + work);
commHandler.forward(work.getIbis());
workQ.doneJob();
}
}
}
private static final Logger logger = LoggerFactory.getLogger(IterativeEventPusher.class);
private final Pool pool;
private final CommunicationHandler commHandler;
IterativeEventPusher(Pool pool, CommunicationHandler commHandler) {
this.pool = pool;
this.commHandler = commHandler;
}
public void run() {
while (!pool.isStopped()) {
int eventTime = pool.getTime();
Member[] children = pool.getChildren();
logger.debug("updating " + children.length +
" children in pool to event-time " + eventTime);
WorkQ workQ = new WorkQ(children);
int threads = Math.min(THREADS, children.length);
for (int i = 0; i < threads; i++) {
new EventPusherThread(workQ);
}
workQ.waitUntilDone();
logger.debug("DONE updating nodes in pool to event-time "
+ eventTime);
pool.waitForEventTime(eventTime + 1, 1000);
}
}
}