home *** CD-ROM | disk | FTP | other *** search
- {$R-,S-,I-,D-,F-,V-,B-,N-,L- }
- {$M 16384,0,655360 }
- PROGRAM Philo;
-
- { Lösung des Dining-Philosophers-Problems
-
- Stand: 01/89
- Autor: Christian Philipps Software-Technik
- Düsseldorfer Str. 316
- 4130 Moers 1
- }
-
- USES {.U-} Crt, CpMulti;
-
- TYPE PhiloStateType = (denkend, hungrig, essend);
-
- CONST Philosophers = 8;
- PhiloPos : ARRAY[1..Philosophers] OF RECORD
- left, top,
- right, bottom : byte;
- END
- = ((left:35;top:1;right:45;bottom:3),
- (left:56;top:3;right:66;bottom:5),
- (left:65;top:9;right:75;bottom:11),
- (left:56;top:15;right:66;bottom:17),
- (left:35;top:17;right:45;bottom:19),
- (left:14;top:15;right:24;bottom:17),
- (left:5;top:9;right:15;bottom:11),
- (left:14;top:3;right:24;bottom:5));
-
- VAR PhiloState : ARRAY[1..Philosophers] OF PhiloStateType;
- PhiloSem : ARRAY[1..Philosophers] OF Pointer;
- Critical : Pointer; {Semaphore}
- Critical1 : Pointer; {Semaphore}
- N : Byte;
-
- {-------------------------------------------------------------------}
-
- PROCEDURE Normal;
-
- BEGIN {Normal}
- TextColor(White);
- TextBackground(Black);
- END; {Normal}
-
- {-------------------------------------------------------------------}
-
- PROCEDURE NormalBlink;
-
- BEGIN {NormalBlink}
- TextColor(White+Blink);
- TextBackground(Black);
- END; {NormalBlink}
-
- {-------------------------------------------------------------------}
-
- PROCEDURE Reverse;
-
- BEGIN {Reverse}
- TextColor(Black);
- TextBackground(White);
- END; {Reverse}
-
- {-------------------------------------------------------------------}
-
- PROCEDURE Frame (X1,Y1,X2,Y2:BYTE);
-
- VAR N : BYTE;
-
- BEGIN { Frame }
- GotoXY(X1,Y1);
- Write('╔');
- FOR N := 1 TO X2-X1-1 DO
- Write('═');
- Write('╗');
- FOR N := 1 TO Y2-Y1-1 DO
- BEGIN
- GotoXY(X1,Y1+N);
- Write('║');
- GotoXY(X2,Y1+N);
- Write('║');
- END;
- GotoXY(X1,Y2);
- Write('╚');
- FOR N := 1 TO X2-X1-1 DO
- Write('═');
- Write('╝');
- END; { Frame }
-
- {-------------------------------------------------------------------}
-
- FUNCTION Left(P:Byte):Byte;
-
- { Ermitteln des linken Nachbarn eines Philiosophen }
-
- BEGIN {Left}
- IF P = 1
- THEN Left := Philosophers
- ELSE Left := Pred(P);
- END; {Left}
-
- {-------------------------------------------------------------------}
-
- FUNCTION Right(P:Byte):Byte;
-
- { Ermitteln des rechten Nachbarn eines Philiosophen }
-
- BEGIN {Right}
- IF P = Philosophers
- THEN Right := 1
- ELSE Right := Succ(P);
- END; {Right}
-
- {-------------------------------------------------------------------}
-
- PROCEDURE DenkeNach(PhilNo:Byte);
-
- { Diese Prozedur wird durchlaufen, wenn ein Philosoph nachdenkt }
-
- BEGIN {DenkeNach}
- WITH PhiloPos[PhilNo] DO
- BEGIN
- SemWait(Critical1);
- Normal;
- GotoXY(Succ(Left),Succ(Top));
- Write(' DENK!!! ');
- SemSignal(Critical1);
- END;
- Sleep(Seconds(3));
- END; {DenkeNach}
-
- {-------------------------------------------------------------------}
-
- PROCEDURE Iss(PhilNo:Byte);
-
- { Diese Prozedur wird durchlaufen, wenn ein Philosoph ißt }
-
- BEGIN {Iss}
- WITH PhiloPos[PhilNo] DO
- BEGIN
- SemWait(Critical1);
- Reverse;
- GotoXY(Succ(Left),Succ(Top));
- Write(' MAMPF!! ');
- SemSignal(Critical1);
- END;
- Sleep(Seconds(2));
- END; {Iss}
-
- {-------------------------------------------------------------------}
-
- PROCEDURE Ueberpruefe(PhilNo:Byte);
-
- { Überprüfe die Nachbarn des Philosophen, um festzustellen,
- ob die Gabeln frei sind. Dies ist immer dann der Fall,
- wenn beide Nachbarn gerade nicht essen }
-
- BEGIN {Ueberpruefe}
- IF PhiloState[PhilNo] <> hungrig {wir sind beschäftigt}
- THEN Exit;
-
- IF (PhiloState[Left(PhilNo)] <> essend) AND
- (PhiloState[Right(PhilNo)] <> essend)
- THEN BEGIN
- PhiloState[PhilNo] := essend; {O.K. wir können essen}
- SemSignal(PhiloSem[PhilNo]); {erhöhe Signal-Count}
- END;
- END; {Ueberpruefe}
-
- {-------------------------------------------------------------------}
-
- PROCEDURE NimmGabeln(PhilNo:Byte);
-
- { Aufheben der Gabeln, die rechts und links vom Teller der
- Philosophen liegen. Ist eine Gabel gerade nicht
- verfügbar, so verfällt der Philosoph in den Wartezustand
- und ist schlicht und ergreifend furchtbar hungrig! }
-
- BEGIN {NimmGabeln}
- SemWait(Critical); {kritischen Bereich abriegeln}
- WITH PhiloPos[PhilNo] DO
- BEGIN
- NormalBlink;
- GotoXY(Succ(Left),Succ(Top));
- Write(' HUNGER! ');
- Sleep(Seconds(1) SHR 1);
- END;
- PhiloState[PhilNo] := hungrig; {wir sind hungrig}
- Ueberpruefe(PhilNo); {können wir essen?}
- SemSignal(Critical); {kritischen Bereich freigeben}
- SemWait(PhiloSem[PhilNo]); {wenn nicht, dann warten wir}
- END; {NimmGabeln}
-
- {-------------------------------------------------------------------}
-
- PROCEDURE LegGabelnHin(PhilNo:Byte);
-
- { Ablegen der Gabeln und freigeben der Nachbarn, falls diese
- nun essen können}
-
- BEGIN {LegGabelnHin}
- SemWait(Critical); {kritischer Bereich}
- PhiloState[PhilNo] := denkend; {wir denken nun wieder nach}
- Ueberpruefe(Left(PhilNo)); {teste linken Nachbarn}
- Ueberpruefe(Right(PhilNo)); {teste rechten Nachbarn}
- SemSignal(Critical); {Ende des kritischen Bereiches}
- END; {LegGabelnHin}
-
- {-------------------------------------------------------------------}
-
- {$F+}
- PROCEDURE Philosoph(P:Pointer);
-
- { Der Körper des Philosophen.
- Diese Prozedur demonstriert, daß Turbo-Pascal-Tasks
- prinzipiell sogar im Code-Sharing ablaufen können.
- Voraussetzung ist, daß jeder Philosoph seinen eigenen
- Stack besitzt, und dies ist durch CreateTask
- gewährleistet}
-
- VAR MyNo : Byte;
-
- BEGIN {Philosoph}
- MyNo := Byte(P);
- WITH PhiloPos[MyNo] DO
- BEGIN
- SemWait(Critical1);
- Normal;
- Frame(left,top,right,bottom);
- GotoXY(Succ(left),Succ(Top));
- Write(' DENK!!! ');
- SemSignal(Critical1);
- END;
- REPEAT {Das Leben eines Philosophen:}
- DenkeNach(MyNo); {wir denken ein wenig...}
- NimmGabeln(MyNo); {...greifen zum Werkzeug...}
- Iss(MyNo); {...essen ein paar Happen...}
- LegGabelnHin(MyNo); {...und kommen ins Grübeln.}
- UNTIL False;
- END; {Philosoph}
- {$F-}
-
- {-------------------------------------------------------------------}
-
- PROCEDURE DrawTable;
-
- { Aufbau der Anzeige }
-
- BEGIN {DrawTable}
- Normal;
- ClrScr;
- Frame(20,6,60,14);
- Window(22,8,58,13);
- Writeln(' The Dining-Philosophers Problem');
- Writeln(' ─────────────────────────');
- Writeln(' (Dijkstra 1965)'^J);
- Writeln(' Autor: Christian Philipps 6/88');
- Window(1,20,80,25);
- Writeln('Jeder Philosoph hat einen Teller mit Spaghetti vor sich stehen. Zwischen je');
- Writeln('zwei Tellern liegt eine Gabel. Nun benötigt jeder Philosoph zwei Gabeln, wenn');
- Writeln('er von seinen schlüpfrigen Spaghetti essen möchte!! - That''s it!');
- Writeln('Ein Philosoph denkt je 3 Sekunden und ißt je 2 Sekunden. Die Übergangsphase');
- Write ('(Hungern) ist zu Demonstrationszwecken mindestens 1/2 Sekunde lang!');
- Window(1,1,80,25);
- END; {DrawTable}
-
- {-------------------------------------------------------------------}
-
- BEGIN {Main}
- DrawTable;
- IF CreateSem(Critical) <> Sem_Ok
- THEN BEGIN
- Writeln('Fehler beim Erzeugen der Critical-Semaphore');
- Halt;
- END;
- IF CreateSem(Critical1) <> Sem_Ok
- THEN BEGIN
- Writeln('Fehler beim Erzeugen der Critical-Semaphore 1');
- Halt;
- END;
- FOR N := 1 TO Philosophers DO
- BEGIN
- PhiloState[n] := denkend;
- IF CreateSem(PhiloSem[n]) <> Sem_Ok
- THEN BEGIN
- Writeln('Fehler beim Erzeugen der Semaphore: ',n);
- Halt;
- END
- ELSE SemClear(PhiloSem[n]);
- END;
- FOR N := 1 TO Philosophers DO
- IF CreateTask(Philosoph,Pointer(n),Pri_User,500) < 0
- THEN BEGIN
- Writeln('Fehler beim Erzeugen des Philosophen: ',n);
- Halt;
- END;
- REPEAT
- Sleep(Seconds(1));
- UNTIL KeyPressed;
- Normal;
- END. {Main}