package myLinda;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import linda.ITupleSpace;
import linda.LindaArgs;
public class MyTupleSpace implements ITupleSpace {
protected HashMap<List<Integer>, TupleSpaceTree> root = new HashMap<List<Integer>, TupleSpaceTree>();
protected HashMap<List<Integer>, Lock> locks = new HashMap<List<Integer>, Lock>();
protected HashMap<List<Integer>, Condition> conditions = new HashMap<List<Integer>, Condition>();
public Condition getCondition(List<Integer> typesPath, LindaArgs pattern) {
if (!conditions.containsKey(typesPath)) {
conditions.put(typesPath, locks.get(typesPath).newCondition());
}
return conditions.get(typesPath);
}
public Lock getLock(List<Integer> typesPath) {
if (!locks.containsKey(typesPath)) {
locks.put(typesPath, new ReentrantLock());
}
return locks.get(typesPath);
}
protected void signalTuple(List<Integer> typesPath, LindaArgs args) {
getCondition(typesPath, args).signalAll();
}
protected void awaitTuple(List<Integer> typesPath, LindaArgs pattern) {
getCondition(typesPath, pattern).awaitUninterruptibly();
}
protected void notifyNext(List<Integer> typesPath) {
return;
}
public void insert(LindaArgs args) {
List<Integer> typesPath = args.getTypesPath();
// Create node for specific type path.
TupleSpaceTree typePathSpace;
synchronized (root) {
if (!root.containsKey(typesPath)) {
root.put(typesPath, new TupleSpaceTree(null));
}
typePathSpace = root.get(typesPath);
}
// Path specifies content of tuple
// Leaf holds whole tuple.
Lock lock = getLock(typesPath);
lock.lock();
try {
LindaArgs temp = new LindaArgs(args);
TupleSpaceTree leaf = typePathSpace.update_values(temp);
leaf.setValue(args);
leaf.increment();
// Poke waiting threads.
signalTuple(typesPath, args);
} finally {
lock.unlock();
}
}
private boolean getAuxiliary(LindaArgs pattern, boolean decrement, boolean nonBlocking) {
List<Integer> typesPath = pattern.getTypesPath();
// Create node for specific type path.
TupleSpaceTree typePathSpace;
synchronized (root) {
if (!root.containsKey(typesPath)) {
root.put(typesPath, new TupleSpaceTree(null));
}
typePathSpace = root.get(typesPath);
}
// Look for specified tuple
TupleSpaceTree leaf;
Lock lock = getLock(typesPath);
lock.lock();
try {
while (true) {
LindaArgs temp = new LindaArgs(pattern);
leaf = typePathSpace.find(temp);
if (leaf != null) {
if (decrement) {
leaf.decrement();
} else {
notifyNext(typesPath);
}
break;
}
if (nonBlocking) {
return false;
}
awaitTuple(typesPath, pattern);
}
} finally {
lock.unlock();
}
pattern.applyResult(new LindaArgs(leaf.getValue()));
return true;
}
public void get(LindaArgs args) {
this.getAuxiliary(args, false, false);
}
public void getAndRemove(LindaArgs args) {
this.getAuxiliary(args, true, false);
}
public boolean getNonBlocking(LindaArgs args) {
return this.getAuxiliary(args, false, true);
}
public boolean getAndRemoveNonBlocking(LindaArgs args) {
return this.getAuxiliary(args, true, true);
}
}