Dining philosophers: Difference between revisions
Content added Content deleted
(Added haskell) |
(Added Oz.) |
||
Line 608: | Line 608: | ||
getLine |
getLine |
||
</lang> |
</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}}== |
=={{header|Python}}== |