public class DrinkMutex extends Process implements Lock {
private static final int tranquil = 0, thirsty = 1, drinking = 2;
Boolean bottle[] = null, requestBottle[] = null, needBottle[] = null; /* needBottle = required resources */
DinMutex din;
int myState = tranquil;
public DrinkMutex(MsgHandler 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 : neighbors)
if (myId > i) {
bottle[i] = false; requestBottle[i] = true;
} else {
bottle[i] = true; requestBottle[i] = false;
}
}
public synchronized void requestCS() {
myState = thirsty;
needBottle[myId] = true; /* this for testing only - pass in required resources array instead */
if (haveBottles()) myState = drinking;
else {
din.requestCS(); /* force diner to hungry state */
for (int i : neighbors)
if (needBottle[i] && requestBottle[i] && !bottle[i])
sendBool(i, "Request", requestBottle[i]);
}
while (myState != drinking) myWait();
}
public synchronized void releaseCS() {
myState = tranquil;
din.releaseCS(); /* force diner to thinking state */
for (int i : neighbors) {
needBottle[i] = false; /* clear required resources array */
if (requestBottle[i]) sendBool(i, "Bottle", bottle[i]);
}
}
boolean haveBottles() {
for (int i : neighbors)
if (needBottle[i] && !bottle[i]) return false;
return true;
}
void sendBool(int dest, String tag, Boolean b) {
sendMsg(dest, tag); b = false;
}
public synchronized void handleMsg(Msg m, int src, String tag) {
if (tag.equals("Request")) {
requestBottle[src] = true;
if (!needBottle[src])
sendBool(src, "Bottle", bottle[src]);
else if ((myState != drinking) && !din.fork[src]) {
sendBool(src, "Bottle", bottle[src]);
if (needBottle[src])
sendBool(src, "Request", requestBottle[src]);
}
}
else if (tag.equals("Bottle")) {
bottle[src] = true;
if (haveBottles()) myState = drinking;
}
}
}