Home Schedule Reading Projects People
Mac Logo Windows Logo Minix Logo Sun Solaris Logo Linux Logo

 

Dining Philosophers Using Locks and Condition Variables: Design Document

Ethan Miller
Fall 2007

Purpose

The purpose of this project is to design the dining philosopher monitor using Lock and Condition only.

Available Resources

We can use both the Lock and Condition classes to solve the dining philosophers problem. The dining philosopher class has the following public interfaces that we must support:

class PhilMonitor {
   Public:
     PhilMonitor();
     ~PhilMonitor ();
     void PickUp(int i);      // must be called before eating to make sure that i
                              // can take the forks to my left and right hand side
     void PutDown(int i);     // must be called after eating to put down the
                              // forks i used to eat with
     void Test(int i);        // make sure phil 'i' can eat.
  Private:
     // I need some more in here
};

All I have to do in my design is describe the private members of the class and how they are used in the three main functions: PickUp(), PutDown(), and Test(). Note that I will not be saying anything about Lock and Condition as they were given to me.

Design

The overall design is to have a single thread for each philosopher. Each philosopher calls PickUp() before starting to eat and PutDown() after getting full. There's a single function—Test()—that is used to determine whether a particular philosopher can eat at the current time. This function determines whether a particular philosopher can eat; if so, the philosopher is awakened. Test() never puts a philosopher to sleep, and the wakeup is done by condition variables so it's OK to call Test() from the thread of the philosopher being "tested" (any signal on the condition variable will be discarded).

Private members and public functions are explained below.

New private members

int State[5]       // Each phil. has his own state. 0 = thinking, 1 = hungry,
                   // 2 = eating.
Condition self[5]  // Each phil. has his own condition variable.
Lock L             // Lock to enter and leave the monitor.

Design of each function

void PickUp(int i)
  Acquire the lock L 
  Set my state to Hungry
  Test to see if I can get the forks to my right and left [see Test()]
  If I am not Eating, then I have to wait on my condition variable 'self'
  Release the lock L
void PutDown(int i)
  Acquire the lock L 
  Set my state to Thinking
  Test to see if my left neighbor is Hungry [see Test()]
  Test to see if my right neighbor is Hungry [see Test()]
  Release the lock L

void Test(int i)
  No lock is needed since Test is called within PickUp and PutDown. 
  If phil. 'i' is hungry and neither of his neighbors is eating then
    Set phil. i's state to Eating
    Wake up phil. i from his condition variable sleep

We also need to implement the code for each philosopher thread as follows:

Phil (int i)
  forever:
    PickUp (i)
    // Wait for some time while eating...
    PutDown (i)
    // Wait for some time while thinking...

Testing

The test strategy for this design will be to try this out with varying interrupt behavior. Basically, we can run this many times and make sure that it works. Another test we may want to run is to vary the think time and eating time for different philosophers, making sure that reducing thinking time still keeps things fair (and working).


Last updated 28 Sep 2009 by Maria Hybinette and 29 Sep 2008 by Darrell Long and perhaps by Jeff LeFevre