// $Id: SpreadAndWait.java,v 1.6 2007-07-08 17:02:48 tigran Exp $
package diskCacheV111.util;
import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.Futures;
import java.io.Serializable;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.Map;
import dmg.cells.nucleus.CellPath;
import org.dcache.cells.CellStub;
public class SpreadAndWait<T extends Serializable>
{
private final CellStub _stub;
private final Map<CellPath,T> _replies = new LinkedHashMap<>();
private int _pending;
public SpreadAndWait(CellStub stub)
{
_stub = stub;
}
public synchronized void send(final CellPath destination, Class<? extends T> type, Serializable msg) {
Futures.addCallback(_stub.send(destination, msg, type),
new FutureCallback<T>()
{
@Override
public void onSuccess(T answer)
{
SpreadAndWait.this.success(destination, answer);
}
@Override
public void onFailure(Throwable t)
{
SpreadAndWait.this.failure();
}
});
_pending++;
}
private synchronized void success(CellPath destination, T answer)
{
_pending--;
_replies.put(destination, answer);
notifyAll();
}
private synchronized void failure()
{
_pending--;
notifyAll();
}
public synchronized void waitForReplies() throws InterruptedException {
while (_pending > 0) {
wait();
}
}
public Map<CellPath, T> getReplies() {
return Collections.unmodifiableMap(_replies);
}
public int getReplyCount() {
return _replies.size();
}
public synchronized T next() throws InterruptedException {
//
// pending replies what
// yes == 0 wait
// yes > 0 return elementAt(0)
// no == 0 null
// no > 0 return elementAt(0)
//
while ((_pending > 0) && _replies.isEmpty() ) {
wait();
}
if ((_pending == 0) && _replies.isEmpty() ) {
return null;
}
return _replies.remove(_replies.keySet().iterator().next());
}
}