The process-oriented approach

With the process-oriented approach the components of the model consist of entities, which represent the existence of some object in the system such as a philosopher. An entity receives a user-defined phase that determines the behavior of the entity.

The entity class is derived from the event class. It may be regarded as a compound event, that is it maintains an additional phase variable to record the actual phase it is in.

We first identify the entities (or the types) in the model. The events are represented as methods of an entity. The function operator calls these events based on the phase the entity is in, as illustrated in the definition of a 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 he/she 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 application::main function the simulation is set up by scheduling the five philosophers, initially waiting, instead of scheduling five await events.