Dining philosophers: Difference between revisions
Content deleted Content added
Added haskell |
Added Oz. |
||
Line 608:
getLine
</lang>
=={{header|Oz}}==
Using first-class computation spaces as transactions on dataflow variables. Computations spaces are normally used to implement constraint search engines. But here we use them to bind two variables atomically.
<lang oz>declare
Philosophers = [aristotle kant spinoza marx russell]
proc {Start}
Forks = {MakeN {Length Philosophers} NewFork}
in
for
Name in Philosophers
LeftFork in Forks
RightFork in {RightShift Forks}
do
thread
{Philosopher Name LeftFork RightFork}
end
end
end
proc {Philosopher Name LeftFork RightFork}
for do
{ShowInfo Name#" is hungry."}
{TakeForks [LeftFork RightFork]}
{ShowInfo Name#" got forks."}
{WaitRandom}
{ReleaseFork LeftFork}
{ReleaseFork RightFork}
{ShowInfo Name#" is thinking."}
{WaitRandom}
end
end
proc {WaitRandom}
{Delay 1000 + {OS.rand} mod 4000} %% 1-5 seconds
end
proc {TakeForks Forks}
{ForAll Forks WaitForFork}
case {TryAtomically proc {$}
{ForAll Forks TakeFork}
end}
of true then
{ForAll Forks InitForkNotifier}
[] false then
{TakeForks Forks}
end
end
%%
%% Fork type
%%
%% A fork is a mutable reference to a pair
fun {NewFork}
{NewCell
unit(taken:_ %% a fork is taken by setting this value to a unique value
notify:unit %% to wait for a taken fork
)}
end
proc {TakeFork F}
(@F).taken = {NewName}
end
proc {InitForkNotifier F}
%% we cannot do this in TakeFork
%% because side effect are not allowed in subordinate spaces
New Old
in
{Exchange F Old New}
New = unit(taken:Old.taken notify:_)
end
proc {ReleaseFork F}
New Old
in
{Exchange F Old New}
New = unit(taken:_ notify:unit)
Old.notify = unit %% notify waiters
end
proc {WaitForFork F}
{Wait (@F).notify} %% returns immediatly if fork is free, otherwise blocks
end
%%
%% Helpers
%%
%% Implements transactions on data flow variables
%% with computation spaces. Returns success.
fun {TryAtomically P}
try
S = {Space.new
proc {$ Sync}
{P}
Sync = unit
end}
in
{Space.askVerbose S} \= failed = true
{Wait {Space.merge S}}
true
catch _ then
false
end
end
%% Calls Fun N times and returns the result as a list.
fun {MakeN N Fun}
case N of 0 then nil
else {Fun}|{MakeN N-1 Fun}
end
end
fun {RightShift Xs} %% circular
case Xs of nil then nil
else {Append Xs.2 [Xs.1]}
end
end
ShowInfo = System.showInfo
in
{Start}</lang>
=={{header|Python}}==
|