public class DrinkMutex extends Process implements Lock {
private static final int tranquil = 0, thirsty = 1, drinking = 2;
boolean bottle[] = null, requestBottle[] = null, needBottle[] = null;
DinMutex din;
int myState = tranquil;
boolean eating = false;
public DrinkMutex(Linker initComm) {
super(initComm);
din = new DinMutex(initComm); /* create diner instance for each drinker */
bottle = new boolean[N];
requestBottle = new boolean[N];
needBottle = new boolean[N];
for (int i = 0; i < N; i++) {
if ((myId > i) && (isNeighbor(i))) {
bottle[i] = false; requestBottle[i] = true;
} else {
bottle[i] = true; requestBottle[i] = false;
}
}
}
public synchronized void requestCS() {
myState = thirsty;
/* following for testing only - pass in required resources array instead */
needBottle[myId] = true;
if (haveBottles()) myState = drinking;
else {
din.requestCS(); /* force diner to hungry state */
eating = true;
for (int i = 0; i < N; i++)
if (needBottle[i] && requestBottle[i] && !bottle[i]) {
sendMsg(i, "Request");
requestBottle[i] = false;
}
}
while (myState != drinking) myWait();
}
public synchronized void releaseCS() {
myState = tranquil;
if (eating) {
eating = false;
din.releaseCS(); /* force diner to thinking state */
}
for (int i = 0; i < N; i++) {
needBottle[i] = false; /* clear required resources array */
if (requestBottle[i]) {
sendMsg(i, "Bottle");
bottle[i] = false;
}
}
}
boolean haveBottles() {
for (int i = 0; i < N; i++)
if (needBottle[i] && !bottle[i]) return false;
return true;
}
public synchronized void handleMsg(Msg m, int source, String tag) {
if (tag.equals("Request")) {
requestBottle[source] = true;
if (!needBottle[source]) {
sendMsg(source, "Bottle");
bottle[source] = false;
}
else if ((myState != drinking) && !din.fork[source]) {
sendMsg(source, "Bottle");
bottle[source] = false;
if (needBottle[source]){
sendMsg(source, "Request");
requestBottle[source] = false;
}
}
}
else if (tag.equals("Bottle")) {
bottle[source] = true;
if (haveBottles()) {
myState = drinking;
notify();
}
}
}
}