Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Erlang - Dining Philosophers errors [closed]

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.

like image 374
Rickard Avatar asked Nov 10 '11 01:11

Rickard


People also ask

What is the main problem that you can observed in the dining philosophers problem?

Difficulty with the solution The above solution makes sure that no two neighboring philosophers can eat at the same time. But this solution can lead to a deadlock. This may happen if all the philosophers pick their left chopstick simultaneously. Then none of them can eat and deadlock occurs.

Can deadlock occur in the dining philosophers problem?

Deadlock could occur if every philosopher holds a left chopstick and waits perpetually for a right chopstick (or vice versa). Originally used as a means of illustrating the problem of deadlock, this system reaches deadlock when there is a 'cycle of unwarranted requests'.

How can we avoid the deadlock in the dining philosophers problem?

Strategy: Every philosopher must request each of their (shared) chopsticks from a waiter, who may refuse the request at first in order to avoid a deadlock. For convenience, we assume that all philosophers request their left chopstick first, then their right chopstick.

What is the problem if all philosophers simultaneously pick up their left fork?

Problem with this solution : This solution may lead to a deadlock under an interleaving that has all the philosophers pick up their left forks before any of them tries to pick up a right fork. In this case, all the Philosophers are waiting for the right fork but no one will execute a single instruction.


2 Answers

I think the problem is that you've got three modules: dinner, eater, and chopstick, but try to call philospher:start in your dinner:init/0 function. Try eater:start instead.

The second problem is the order of module and function name when generating random numbers; replace uniform:random with random:uniform in your eater.erl:

1> dinner:start().
<0.35.0>
Confucios received a chopstick
Confucios received a chopstick
Confucios started eating
Confucios put back two chopsticks
Confucios received a chopstick
Confucios received a chopstick
Confucios started eating
Confucios put back two chopsticks
Confucios received a chopstick
Confucios received a chopstick
Confucios started eating
Confucios put back two chopsticks
Confucios received a chopstick
Confucios received a chopstick
Confucios started eating
Confucios put back two chopsticks
Confucios received a chopstick
Confucios received a chopstick
Confucios started eating
Confucios put back two chopsticks
Avicenna received a chopstick
Avicenna received a chopstick
Avicenna started eating
...

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.erl so that the start() function reads:

start(Hungry, Right, Left, Name, Ctrl) ->
    spawn_link(fun() -> dream(Hungry, Right, Left, Name, Ctrl) end).

Now it works as intended:

1> dinner:start().
<0.35.0>
Confucios received a chopstick
Plato received a chopstick
Confucios received a chopstick
Confucios started eating
Descartes received a chopstick
Kant received a chopstick
Confucios put back two chopsticks
Avicenna received a chopstick
...

Thanks. This was good fun.

like image 164
sarnold Avatar answered Nov 15 '22 11:11

sarnold


change wherever you are calling: uniform:random/1 to random:uniform/1 and the exception will be gone

like image 22
Muzaaya Joshua Avatar answered Nov 15 '22 12:11

Muzaaya Joshua