next up previous contents
Next: The entity class Up: The process-oriented approach Previous: The process-oriented approach

The entity philosopher

Consider the following definition and implementation of the entity philosopher

 
   enum {EATING,THINKING,WAITING};      // phases of a philosopher
  
   class philosopher : public entity
   {
   public :
     philosopher(int ph,int i);  // constructor, taking phase and id
     virtual int operator()();   // function operator
     int eat();                  // eat event
     int think();                // think event
     int await();                // await event
   private :
     int id;
     generator* g;
   };
  
   philosopher::philosopher(int ph,int i) : entity(ph)
   {
     id = i;                  // set phase and identity
     g = new generator(20,10,999);
   }
  
   int philosopher::operator()()
   {
     switch (phase())         // what phase is the philosopher in ?
     {
     case EATING :
       return eat();          // the philosopher eats
     case THINKING :
       return think();        // the philosopher thinks
     case WAITING :
       return await();        // the philosopher waits
     }
     return FALSE;
   }
  
   int philosopher::eat()
   {
     double t = g -> exponential(eatingtime);    // determine eating time
     sim -> wait(t);            // schedule this philosopher thinking
     phase(THINKING);                   // set phase to thinking
     return OK;
   }
  
   int philosopher::think()
   {
     chopstick[id] -> release();            // release left chopstick
     chopstick[(id+1)%number] -> release(); // release right
     double t = g -> exponential(thinkingtime);   // determine thinking time
     thinking -> sample(id,t/duration*100);       // sample (%)
     sim -> wait(t);              // schedule this philosopher waiting
     phase(WAITING);                        // set phase on waiting
     return OK;
   }
 
   int philosopher::await()
   {
     if ( (chopstick[id] -> available()) &&    // available ?
        (chopstick[(id+1)%number] -> available()) )
     {
       chopstick[id] -> acquire();          // acquire left chopstick
       chopstick[(id+1)%number] -> acquire();      // acquire right
       sim -> passivate(this);         // make passive
       sim -> activate(this);          // activate as eating
       phase(EATING);                  // set phase on eating
     }
     else if (!conditional())       
       sim -> hold(this);                  // add to conditional
     return OK;
   }

Dependent on the phase the philosopher is in, the appropriate action on the simulation environment is taken. These actions closely resemble the events, described in the event-based approach of this problem. The main difference is in the use of phase. If, for example, a philosopher finishes eating, his/her phase is set to THINKING and s/he is scheduled after t time units, whereas in the event-based approach a think event is scheduled and the eat event is explicitly terminated. So, in the process-oriented solution a philosopher exists for the entire simulation. In the session::main function the simulation is set up by scheduling the five philosophers, initially waiting, instead of scheduling five await events.



A Eliens
Tue Oct 31 09:27:21 MET 1995