I apologize if the code is hard to follow.
This is the classic dining philosophers problem, where 5 philosophers are eating, but there are only 5 sticks – and you need two to eat.
These are the instructions, if anyone is interested:
http://www.kth.se/polopoly_fs/1.260940!/Menu/general/column-content/attachment/philosophers.pdf
Anyways, here is the code, the chopstick process code:
-module(chopstick).
-export([start/0]).
start() ->
spawn_link(fun() -> init() end).
init() ->
available().
available() ->
receive
{request, From} ->
From ! granted,
gone();
quit ->
ok
end.
gone() ->
receive
returned ->
available();
quit ->
ok
end.
The philosopher process code:
-module(eater).
-import(timer, [sleep/1]).
-import(random, [uniform/1]).
-export([start/5, dream/5, eat/5, wait/5]).
start(Hungry, Right, Left, Name, Ctrl) ->
dream(Hungry, Right, Left, Name, Ctrl).
**%This was wrong, it should say start(Hungry, Right, Left, Name, Ctrl) ->
spawn_link(fun() -> dream(Hungry, Right, Left, Name, Ctrl) end).**
dream(Hungry, Right, Left, Name, Ctrl) ->
Time = 500+uniform:random(500), **%This was wrong, it should say random:uniform**
timer:sleep(Time),
Right! {request, self()},
Left! {request, self()},
%skicka {request, self()} till två pinnar
wait(Hungry, Right, Left, Name, Ctrl).
wait(Hungry, Right, Left, Name, Ctrl) ->
receive
granted ->
io:format("~s received a chopstick~n", [Name]),
receive
granted ->
io:format("~s received a chopstick~n", [Name]),
io:format("~s started eating~n", [Name]),
eat(Hungry, Right, Left, Name, Ctrl)
end;
_ -> wait(Hungry, Right, Left, Name, Ctrl)
end.
eat(Hungry, Right, Left, Name, Ctrl) ->
Time = 500+uniform:random(500), **%This was wrong, it should say random:uniform**
timer:sleep(Time),
Right! returned,
Left! returned,
io:format("~s put back two chopsticks~n", [Name]),
if
Hungry =< 1 ->
Ctrl ! done;
true ->
dream(Hungry-1, Right, Left, Name, Ctrl)
end.
And finally the host process:
-module(dinner).
-export([start/0]).
start() ->
spawn(fun() -> init() end).
init() ->
C1 = chopstick:start(),
C2 = chopstick:start(),
C3 = chopstick:start(),
C4 = chopstick:start(),
C5 = chopstick:start(),
Ctrl = self(),
eater:start(5, C1, C2, "Confucios", Ctrl), **% This is where it crashes**
eater:start(5, C2, C3, "Avicenna", Ctrl),
eater:start(5, C3, C4, "Plato", Ctrl),
eater:start(5, C4, C5, "Kant", Ctrl),
eater:start(5, C5, C1, "Descartes", Ctrl),
wait(5, [C1, C2, C3, C4, C5]).
wait(0, Chopsticks) ->
lists:foreach(fun(C) -> C ! quit end, Chopsticks);
wait(N, Chopsticks) ->
receive
done ->
wait(N-1, Chopsticks);
abort ->
erlang:exit(abort)
end.
Output:
11> dinner:start().
<0.85.0>
12>
=ERROR REPORT==== 10-Nov-2011::02:19:10 ===
Error in process <0.85.0> with exit value: {undef,[{uniform,random,[500]}, {eater,dream,5},{dinner,init,0}]}
Thanks a lot if you even read through all of this, I haven’t learnt how to read the error reports of erlang yet. If you can, and want to tell me what it means please do.
I think the problem is that you’ve got three modules:
dinner,eater, andchopstick, but try to callphilospher:startin yourdinner:init/0function. Tryeater:startinstead.The second problem is the order of module and function name when generating random numbers; replace
uniform:randomwithrandom:uniformin youreater.erl:This pretty quickly shows the third problem — something we should have spotted from the first error report — that the eaters aren’t actually in their own processes. So edit
eater.erlso that thestart()function reads:Now it works as intended:
Thanks. This was good fun.