The Dining Philosophers Problem.Part 2. TPhilosopher class.


© Lyapin Ilya
Articles in this Topic    Discussions in this Topic

This article starts the detailed program explanation. Now let's look at the philosopher.pas module that defines TPhilosopher class.

TPhilosopher class definition.

TPilosopher represents a philosopher's lifecycle. The main program creates five instances of the TPhilosopher and run them concurrently. TPhilosopher is derived from the TThread class (see previous articles for TThread details) and overrides Execute method.

TPhilosopher class is defined like following:

const
   NUMBER_OF_PHILOSOPHERS = 5; // number of philosophers
type
// type for a status of a philosopher
TPhilosopherStatus = (stUnknown,stThinking,stEating,stWaitingForLeftFork,stWaitingForRightFork);

// the philosopher's life cycle - thinking, waiting for fork, eating
TPhilosopher = class (TThread)
private
   // the status of the philosopher
   FStatus: TPhilosopherStatus;
   // the number of the philosopher
   FNumber: Integer;
   // pointer to the fork manager
   FForks: TForks;
protected
   // the thread procedure
   procedure Execute;override;
public
   // constructor - initializes FNumber and FForks fields and creates the suspended thread
   constructor Create(iNumber:integer;Forks:TForks);
   // Status of the philosopher - read only property
   property Status:TPhilosopherStatus read FStatus;
   // number of the philosopher - read only property
   property Number: integer read FNumber;
end;

Philosopher.pas globals.

Each philosopher eats and thinks the same time. In order to change eating and thinking time each pass we should use two global variables of type DWORD.

var
    EatingTime,
    ThinkingTime:DWORD;

Procedure SetTimes changes eating and thinking time.

procedure SetTimes(dwEatingTime,dwThinkingTime:DWORD);
begin
    EatingTime := dwEatingTime;
    ThinkingTime:= dwThinkingTime;
end;

TPhilosopher class implementation.

Constructor TPhilosopher.Create initializes FNumber and FForks fields and creates the suspended thread using inherited constructor.

constructor TPhilosopher.Create(iNumber: integer; Forks: TForks);
begin
    // store the number of the philosopher
    FNumber := iNumber;
    // store the pointer to the fork manager
    FForks := Forks;
    // create suspended thread
    inherited Create(true);
    // the program will free philosopher object manually
    FreeOnTerminate := false;
end;

The thread procedure implements the lifecycle of the philosopher.
While terminated property is not signaled, the philosopher fulfils the following actions:

  1. Think (sleep) a random time based on the ThinkingTime constant
  2. Call the fork manager to acquire left fork
  3. When the fork is granted call the fork manager to acquire right fork
  4. Eat (sleep) a random time based on the EatingTime constant

procedure TPhilosopher.Execute;
var
    lf,rf:integer;
begin
    // while thread is not terminated
    while not terminated do
    begin // philosopher is 'alive'
        // Think a little
        fStatus := stThinking;
        Sleep(Random(ThinkingTime));
        // Philosopher is hungry
        // He sits at the table
       fStatus :=stWaitingForLeftFork;
        lf := FNumber - 2;
        if lf<0 then
            lf := NUMBER_OF_PHILOSOPHERS -1;
        // ... And tries to take the left fork
        if FForks.TakeFork(lf,INFINITE) then
        begin
            // fork granted - let's take the right fork

Go To Page: 1 2


Post this Article to facebook Add this Article to del.icio.us! Digg this Article furl this Article Add this Article to Reddit Add this Article to Technorati Add this Article to Newsvine Add this Article to Windows Live Add this Article to Yahoo Add this Article to StumbleUpon Add this Article to BlinkLists Add this Article to Spurl Add this Article to Google Add this Article to Ask Add this Article to Squidoo