/** Fork pool used by the philosophers */ class Forks { private bool[] fork = new bool[5]; // initially false, i.e. not used private Cond cond = new Cond (); private Mutex mutex = new Mutex (); // Try to pick up the forks with the designated numbers public void pick_up (int left, int right) { mutex.lock (); while (fork[left] || fork[right]) { cond.wait (mutex); } fork[left] = true; fork[right] = true; mutex.unlock (); } // Lay down the forks with the designated numbers public void lay_down (int left, int right) { mutex.lock (); fork[left] = false; fork[right] = false; cond.broadcast (); mutex.unlock (); } } /** A dining philosopher */ class Philosopher { private int number; // this philosopher's number private int think_delay; // how long does this philosopher think? private int eat_delay; // how long does this philosopher eat? private int left; // left fork number private int right; // right fork number private Forks forks; // forks used by all philosophers public Philosopher (int number, int think_delay, int eat_delay, Forks forks) { this.number = number; this.think_delay = think_delay; this.eat_delay = eat_delay; this.forks = forks; this.left = number == 0 ? 4 : number - 1; this.right = (number + 1) % 5; } public void* run () { while (true) { Thread.usleep (think_delay); forks.pick_up (left, right); stdout.printf ("Philosopher %d starts eating...\n", number); Thread.usleep (eat_delay); forks.lay_down (left, right); stdout.printf ("Philosopher %d stops eating...\n", number); } } } int main (string[] args) { if (!Thread.supported ()) { error ("Cannot run without thread support."); } var forks = new Forks (); Philosopher[] philos = { new Philosopher (0, 100000, 500000, forks), new Philosopher (1, 200000, 400000, forks), new Philosopher (2, 300000, 300000, forks), new Philosopher (3, 400000, 200000, forks), new Philosopher (4, 500000, 100000, forks) }; try { foreach (var philosopher in philos) { Thread.create (philosopher.run, false); } } catch (ThreadError e) { error ("%s\n", e.message); } new MainLoop ().run (); return 0; }