Data commit
This commit is contained in:
parent
7387c8f97b
commit
cb5bb5e222
199093 changed files with 3378972 additions and 0 deletions
101
Task/Dining-philosophers/Modula-3/dining-philosophers.mod3
Normal file
101
Task/Dining-philosophers/Modula-3/dining-philosophers.mod3
Normal file
|
|
@ -0,0 +1,101 @@
|
|||
MODULE DiningPhilosophers EXPORTS Main;
|
||||
|
||||
IMPORT IO, Random, Thread;
|
||||
|
||||
CONST
|
||||
|
||||
PartySize = 5; (* modify for more/fewer philosophers *)
|
||||
|
||||
TYPE
|
||||
|
||||
Closure = Thread.Closure OBJECT
|
||||
(* thread information *)
|
||||
which: [1..PartySize]; (* identifies the thread *)
|
||||
OVERRIDES
|
||||
apply := Live; (* procedure to execute *)
|
||||
END;
|
||||
|
||||
VAR
|
||||
|
||||
(* how long to eat/think *)
|
||||
random: Random.T;
|
||||
|
||||
(* controls access to resources *)
|
||||
test := NEW(MUTEX);
|
||||
forks := NEW(Thread.Condition); (* condition variable, used for signaling *)
|
||||
forkAvailable := ARRAY[1..PartySize] OF BOOLEAN {
|
||||
TRUE, TRUE, TRUE, TRUE, TRUE
|
||||
};
|
||||
(* the philosophers/tasks *)
|
||||
thread: ARRAY[1..PartySize] OF Thread.T;
|
||||
name := ARRAY[1..PartySize] OF TEXT {
|
||||
"Aristotle", "Kant", "Spinoza", "Marx", "Russell"
|
||||
};
|
||||
|
||||
PROCEDURE PlaceAvailable(): CARDINAL =
|
||||
(*
|
||||
Determines whether a place is available at the table.
|
||||
If so, returns the place number. Otherwise, returns 0.
|
||||
We consider a place available if and only if *both* forks are free.
|
||||
*)
|
||||
BEGIN
|
||||
FOR i := 1 TO PartySize DO
|
||||
IF forkAvailable[i] AND forkAvailable[((i+1) MOD PartySize) + 1] THEN
|
||||
RETURN i;
|
||||
END;
|
||||
END;
|
||||
RETURN 0;
|
||||
END PlaceAvailable;
|
||||
|
||||
PROCEDURE Live(philosopher: Closure): REFANY =
|
||||
(* philosophers eat, sleep, ... and that's about it *)
|
||||
VAR
|
||||
place: CARDINAL;
|
||||
BEGIN
|
||||
WITH which = philosopher.which DO
|
||||
WHILE TRUE DO
|
||||
(* first make sure a place is available: both forks must be free! *)
|
||||
LOCK test DO
|
||||
place := PlaceAvailable();
|
||||
(* if not, release mutex and use condition variable to wait for one *)
|
||||
WHILE place = 0 DO
|
||||
IO.Put(name[which]); IO.Put(" starving!\n");
|
||||
Thread.Wait(test, forks);
|
||||
(* in Modula-3 we arrive here only if we have the lock again *)
|
||||
place := PlaceAvailable();
|
||||
END;
|
||||
(* a place has come available! seize the forks while mutex is locked *)
|
||||
forkAvailable[place] := FALSE;
|
||||
forkAvailable[(place MOD PartySize) + 1] := FALSE;
|
||||
IO.Put(name[which]); IO.Put(" eating at place "); IO.PutInt(place);
|
||||
IO.PutChar('\n');
|
||||
END;
|
||||
Thread.Pause(FLOAT(random.integer(1,3), LONGREAL));
|
||||
(* put down the forks *)
|
||||
forkAvailable[place] := TRUE;
|
||||
forkAvailable[(place MOD PartySize) + 1] := TRUE;
|
||||
Thread.Signal(forks); (* signal the condition variable *)
|
||||
LOCK test DO
|
||||
IO.Put(name[which]); IO.Put(" thinking\n");
|
||||
END;
|
||||
Thread.Pause(FLOAT(random.integer(1,3), LONGREAL));
|
||||
END; (* WHILE *)
|
||||
END; (* WITH *)
|
||||
RETURN NIL;
|
||||
END Live;
|
||||
|
||||
BEGIN
|
||||
random := NEW(Random.Default).init();
|
||||
(* bring philosophers to life *)
|
||||
FOR i := 1 TO PartySize DO
|
||||
thread[i] := Thread.Fork(NEW(Closure, apply := Live, which := i));
|
||||
END;
|
||||
(*
|
||||
We need to wait, otherwise the program will terminate,
|
||||
and the philosophers with it. Technically we could wait
|
||||
for just one philosopher, but in the interest of symmetry...
|
||||
*)
|
||||
FOR i := 1 TO PartySize DO
|
||||
EVAL Thread.Join(thread[i]);
|
||||
END;
|
||||
END DiningPhilosophers.
|
||||
Loading…
Add table
Add a link
Reference in a new issue