102 lines
2.2 KiB
Plaintext
102 lines
2.2 KiB
Plaintext
program dining_philosophers3;
|
|
{$mode objfpc}{$H+}
|
|
uses
|
|
{$IFDEF UNIX}
|
|
cthreads,
|
|
{$ENDIF}
|
|
Classes, SysUtils, SyncObjs;
|
|
const
|
|
PHIL_COUNT = 5;
|
|
LIFESPAN = 7;
|
|
DELAY_RANGE = 950;
|
|
DELAY_LOW = 50;
|
|
PHIL_NAMES: array[1..PHIL_COUNT] of string = ('Aristotle', 'Kant', 'Spinoza', 'Marx', 'Russell');
|
|
type
|
|
TFork = TCriticalSection;
|
|
TPhilosopher = class;
|
|
var
|
|
Forks: array[1..PHIL_COUNT] of TFork;
|
|
Philosophers: array[1..PHIL_COUNT] of TPhilosopher;
|
|
type
|
|
TPhilosopher = class(TThread)
|
|
private
|
|
FName: string;
|
|
FLeftFork, FRightFork: TFork;
|
|
protected
|
|
procedure Execute; override;
|
|
public
|
|
constructor Create(const aName: string; aForkIdx1, aForkIdx2: Integer);
|
|
end;
|
|
|
|
procedure TPhilosopher.Execute;
|
|
var
|
|
LfSpan: Integer = LIFESPAN;
|
|
begin
|
|
while LfSpan > 0 do
|
|
begin
|
|
Dec(LfSpan);
|
|
WriteLn(FName, ' sits down at the table');
|
|
repeat
|
|
FLeftFork.Acquire;
|
|
if not FRightFork.TryEnter then
|
|
begin
|
|
FLeftFork.Release;
|
|
Sleep(Random(DELAY_RANGE));
|
|
continue;
|
|
end;
|
|
break;
|
|
until False;
|
|
WriteLn(FName, ' eating');
|
|
Sleep(Random(DELAY_RANGE) + DELAY_LOW);
|
|
FRightFork.Release;
|
|
FLeftFork.Release;
|
|
WriteLn(FName, ' is full and leaves the table');
|
|
if LfSpan = 0 then
|
|
continue;
|
|
WriteLn(FName, ' thinking');
|
|
Sleep(Random(DELAY_RANGE) + DELAY_LOW);
|
|
WriteLn(FName, ' is hungry');
|
|
end;
|
|
end;
|
|
|
|
constructor TPhilosopher.Create(const aName: string; aForkIdx1, aForkIdx2: Integer);
|
|
begin
|
|
inherited Create(True);
|
|
FName := aName;
|
|
FLeftFork := Forks[aForkIdx1];
|
|
FRightFork := Forks[aForkIdx2];
|
|
end;
|
|
|
|
procedure DinnerBegin;
|
|
var
|
|
I: Integer;
|
|
Phil: TPhilosopher;
|
|
begin
|
|
for I := 1 to PHIL_COUNT do
|
|
Forks[I] := TFork.Create;
|
|
for I := 1 to PHIL_COUNT do
|
|
Philosophers[I] := TPhilosopher.Create(PHIL_NAMES[I], I, Succ(I mod PHIL_COUNT));
|
|
for Phil in Philosophers do
|
|
Phil.Start;
|
|
end;
|
|
|
|
procedure WaitForDinnerOver;
|
|
var
|
|
Phil: TPhilosopher;
|
|
Fork: TFork;
|
|
begin
|
|
for Phil in Philosophers do
|
|
begin
|
|
Phil.WaitFor;
|
|
Phil.Free;
|
|
end;
|
|
for Fork in Forks do
|
|
Fork.Free;
|
|
end;
|
|
|
|
begin
|
|
Randomize;
|
|
DinnerBegin;
|
|
WaitForDinnerOver;
|
|
end.
|