package countedLinda;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.locks.Lock;
import linda.LindaArgs;
import myLinda.MyTupleSpace;
public class CountedTupleSpace extends MyTupleSpace {
private HashMap<LindaArgs, CountedWaitRoom> waitRoom = new HashMap<LindaArgs, CountedWaitRoom>();
private HashMap<List<Integer>, LindaArgs> newTuples = new HashMap<List<Integer>, LindaArgs>();
@Override
protected void signalTuple(List<Integer> typesPath, LindaArgs newTuple) {
CountedWaitRoom room = chooseRoom(waitingRooms(newTuple));
if (room == null) {
return;
}
newTuples.put(newTuple.getTypesPath(), newTuple);
room.decrement();
room.getChanges().signal();
}
@Override
protected void awaitTuple(List<Integer> typesPath, LindaArgs pattern) {
// First element in room?
if (!waitRoom.containsKey(pattern)) {
Lock lock = getLock(typesPath);
waitRoom.put(pattern, new CountedWaitRoom(lock.newCondition()));
}
CountedWaitRoom room = waitRoom.get(pattern);
room.increment();
room.getChanges().awaitUninterruptibly();
}
protected void notifyNext(List<Integer> typesPath) {
LindaArgs newTupleForwarded = newTuples.get(typesPath);
signalTuple(typesPath, newTupleForwarded);
}
private CountedWaitRoom chooseRoom(List<CountedWaitRoom> waitingRooms) {
// Get only those rooms where somebody awaits.
Iterator<CountedWaitRoom> it = waitingRooms.iterator();
while(it.hasNext()) {
CountedWaitRoom room = it.next();
if (room.isEmpty()) {
it.remove();
}
}
// Nobody awaits for this tuple? Sooo sad.
if (waitingRooms.isEmpty()) {
return null;
}
// Pick random tuple so everybody could have a chance.
Collections.shuffle(waitingRooms);
return waitingRooms.get(0);
}
private List<CountedWaitRoom> waitingRooms(LindaArgs newTuple) {
List<CountedWaitRoom> rooms = new ArrayList<CountedWaitRoom>();
if (newTuple != null) {
List<LindaArgs> allPatterns = newTuple.generateSubPatterns();
for (LindaArgs pattern : allPatterns) {
if (waitRoom.containsKey(pattern)) {
rooms.add(waitRoom.get(pattern));
}
}
}
return rooms;
}
}