import java.net.*; import java.io.*; import Utilities.*; import Synchronization.*; class Philosopher extends MyObject implements Runnable { private static int id = 0; private static int napThink = 0; // both are in private static int napEat = 0; // seconds private static Rendezvous r = null; private Philosopher(String name) { super(name); new Thread(this).start(); } private void think() { int napping; napping = 1 + (int) random(1000*napThink); System.out.println("age()=" + age() + ", " + getName() + " is thinking for " + napping + " ms"); nap(napping); } private void eat() { int napping; napping = 1 + (int) random(1000*napEat); System.out.println("age()=" + age() + ", " + getName() + " is eating for " + napping + " ms"); nap(napping); } public void run() { while (true) { think(); System.out.println("age()=" + age() + ", " + getName() + " wants to eat"); try { r.clientMakeRequestAwaitReply(new Integer(id)); // takeForks(id); eat(); r.clientMakeRequestAwaitReply(new Integer(-id-1));// putForks(id); } catch (MessagePassingException e) { System.err.println("age()=" + age() + ", " + getName() + ":" + e); r.close(); System.exit(1); } } } public static void main(String[] args) { // parse command line options, if any, to override defaults GetOpt go = new GetOpt(args, "Ui:t:e:s:p:"); go.optErr = true; String usage = "Usage: -i id -t napThink -e napEat -s server -p port"; int ch = -1; id = 0; napThink = 8; // defaults are napEat = 2; // both in seconds String diningServer = "localhost"; int port = 9999; while ((ch = go.getopt()) != go.optEOF) { if ((char)ch == 'U') { System.out.println(usage); System.exit(0); } else if ((char)ch == 'i') id = go.processArg(go.optArgGet(), id); else if ((char)ch == 't') napThink = go.processArg(go.optArgGet(), napThink); else if ((char)ch == 'e') napEat = go.processArg(go.optArgGet(), napEat); else if ((char)ch == 's') diningServer = go.optArgGet(); else if ((char)ch == 'p') port = go.processArg(go.optArgGet(), port); else { System.err.println(usage); System.exit(1); } } System.out.println("Philosopher: id=" + id + " napThink=" + napThink + " napEat=" + napEat + " diningServer=" + diningServer + " port=" + port); // create a rendezvous to the DiningServer object EstablishRendezvous er = null; try { er = new EstablishRendezvous(diningServer, port); r = er.clientToServer(); System.out.println("Connected to " + diningServer + " on port " + port); } catch (MessagePassingException e) { System.err.println("Philosopher id=" + id + " e=" + e); System.exit(1); } // tell the dining server that this philosopher is alive r.clientMakeRequestAwaitReply(new Integer(id)); // start the Philosopher thread new Philosopher("Philosopher " + id); System.out.println("Philosopher thread " + id + " started"); } } class DiningServer extends MyObject implements Runnable { private static final int THINKING = 0, HUNGRY = 1, EATING = 2; private static int numPhils = 0; private static int[] state = null; private static BinarySemaphore[] self = null; private static BinarySemaphore mutex = null; private int philosopherID = -1; private Rendezvous r = null; private DiningServer(int philosopherID, Rendezvous r) { this.philosopherID = philosopherID; this.r = r; new Thread(this).start(); } private static final int left(int i) { return (numPhils+i-1) % numPhils; } private static final int right(int i) { return (i+1) % numPhils; } private static void takeForks(int i) { P(mutex); state[i] = HUNGRY; test(i); V(mutex); P(self[i]); } private static void putForks(int i) { P(mutex); state[i] = THINKING; test(left(i)); test(right(i)); V(mutex); } private static void test(int k) { if (state[left(k)] != EATING && state[right(k)] != EATING && state[k] == HUNGRY) { state[k] = EATING; V(self[k]); } } public void run() { int message = 0; while (true) { System.out.println("age=" + age() + " waiting for message from philosopher " + philosopherID); message = ((Integer) r.serverGetRequest()).intValue(); if (message == -philosopherID-1) { System.out.println("age=" + age() + " putForks from philosopher " + philosopherID); putForks(philosopherID); // acknowledge the release of the forks r.serverMakeReply(new Integer(0)); } else if (message == philosopherID) { System.out.println("age=" + age() + " takeForks from philosopher " + philosopherID); takeForks(philosopherID); System.out.println("age=" + age() + " forks available for philosopher " + philosopherID); // release the philosopher when forks available r.serverMakeReply(new Integer(0)); } else { System.err.println("philosopherID=" + philosopherID + ", illegal message=" + message); } } } public static void main(String[] args) { // parse command line options, if any, to override defaults GetOpt go = new GetOpt(args, "Un:p:R:"); go.optErr = true; String usage = "Usage: -n numPhils -p port -R runTime"; int ch = -1; numPhils = 5; // default int port = 9999; // values int runTime = 60; // seconds while ((ch = go.getopt()) != go.optEOF) { if ((char)ch == 'U') { System.out.println(usage); System.exit(0); } else if ((char)ch == 'n') numPhils = go.processArg(go.optArgGet(), numPhils); else if ((char)ch == 'p') port = go.processArg(go.optArgGet(), port); else if ((char)ch == 'R') runTime = go.processArg(go.optArgGet(), runTime); else { System.err.println(usage); System.exit(1); } } state = new int[numPhils]; for (int i = 0; i < numPhils; i++) state[i] = THINKING; self = new BinarySemaphore[numPhils]; for (int i = 0; i < numPhils; i++) self[i] = new BinarySemaphore(0); mutex = new BinarySemaphore(1); System.out.println("DiningServer: numPhils=" + numPhils + ", port=" + port + ", runTime=" + runTime); // accept connections from the philosophers // and start a message passing thread for each philosopher EstablishRendezvous er = null; try { er = new EstablishRendezvous(port); System.out.println("Waiting for connection on port " + port); } catch (MessagePassingException e) { System.err.println("DiningServer:" + e); System.exit(1); } Rendezvous[] r = new Rendezvous[numPhils]; for (int i = 0; i < numPhils; i++) { try { r[i] = er.serverToClient(); } catch (MessagePassingException e) { System.err.println("DiningServer:" + e); } int id = ((Integer) r[i].serverGetRequest()).intValue(); new DiningServer(id, r[i]); System.out.println("Accepted connection from philosopher " + id); } System.out.println("DiningServer: all philosophers connected"); for (int i = 0; i < numPhils; i++) // let the philosophers start eating r[i].serverMakeReply(new Integer(0)); // let the Philosophers run for a while nap(runTime*1000); System.out.println("age()=" + age() + ", time to stop the Philosophers and exit"); for (int i = 0; i < numPhils; i++) r[i].close(); er.close(); System.exit(0); } } /* ............... Example compile and run(s) % javac dpmm.java % java DiningServer -n5 -R20 & DiningServer: numPhils=5, port=9999, runTime=20 // on jubjub Waiting for connection on port 9999 % sleep 5; rsh bander "java Philosopher -s jubjub -i0" & Philosopher: id=0 napThink=8 napEat=2 diningServer=jubjub port=9999 Connected to jubjub on port 9999 Accepted connection from philosopher 0 age=5880 waiting for message from philosopher 0 % sleep 5; rsh cheshire "java Philosopher -s jubjub -i1" & Philosopher: id=1 napThink=8 napEat=2 diningServer=jubjub port=9999 Connected to jubjub on port 9999 Accepted connection from philosopher 1 age=9500 waiting for message from philosopher 1 % sleep 5; rsh humpty "java Philosopher -s jubjub -i2" & Philosopher: id=2 napThink=8 napEat=2 diningServer=jubjub port=9999 Connected to jubjub on port 9999 Accepted connection from philosopher 2 age=12740 waiting for message from philosopher 2 % sleep 5; rsh queen "java Philosopher -s jubjub -i3" & Philosopher: id=3 napThink=8 napEat=2 diningServer=jubjub port=9999 Connected to jubjub on port 9999 Accepted connection from philosopher 3 age=15870 waiting for message from philosopher 3 % sleep 5; rsh king "java Philosopher -s jubjub -i4" Philosopher: id=4 napThink=8 napEat=2 diningServer=jubjub port=9999 Connected to jubjub on port 9999 Accepted connection from philosopher 4 age=18780 waiting for message from philosopher 4 DiningServer: all philosophers connected // Philosopher output deleted age=20100 takeForks from philosopher 4 // from here on age=20100 forks available for philosopher 4 age=20100 waiting for message from philosopher 4 age=20430 takeForks from philosopher 2 age=20430 forks available for philosopher 2 age=20430 waiting for message from philosopher 2 age=21530 putForks from philosopher 4 age=21530 waiting for message from philosopher 4 age=22190 putForks from philosopher 2 age=22190 waiting for message from philosopher 2 age=23070 takeForks from philosopher 4 age=23070 forks available for philosopher 4 age=23070 waiting for message from philosopher 4 age=24170 putForks from philosopher 4 age=24170 waiting for message from philosopher 4 age=26310 takeForks from philosopher 2 age=26310 forks available for philosopher 2 age=26310 waiting for message from philosopher 2 age=26690 takeForks from philosopher 0 age=26690 forks available for philosopher 0 age=26690 waiting for message from philosopher 0 age=26750 takeForks from philosopher 3 age=27410 takeForks from philosopher 1 age=27900 putForks from philosopher 2 age=27900 forks available for philosopher 3 age=27900 waiting for message from philosopher 3 age=27960 waiting for message from philosopher 2 age=28510 putForks from philosopher 3 age=28510 waiting for message from philosopher 3 age()=28830, time to stop the Philosophers and exit ... end of example run(s) */