Agreeing to Toby (<a href="http://www.erlang.org/pipermail/erlang-questions/2007-July/028133.html" target="_blank" onclick="return top.js.OpenExtLink(window,event,this)">http://www.erlang.org/pipermail/erlang-questions/2007-July/028133.html
</a>) I got the following:<br><br>-module(conc_problems).
<br>-export([start/2,start_server<div id="mb_0">/0]).<br><br>%% 2> c(conc_problems).<br>%% {ok,conc_problems}<br>%% 3> conc_problems:start_server(). This starts the registration server (A singleton)<br>
%% true<br>%%
4> conc_problems:start(foo2, fun area_server1:loop/0). This calls
the registration method on the above singleton server
<br>%% Received:{foo2,#Fun<area_server1.loop.0>}<br>%% Undef:foo2<br>%% {foo2,#Fun<area_server1.loop.0>,{success,<0.46.0>}}<br>%% 5> conc_problems:start(foo2, fun area_server1:loop/0).<br>
%% Received:{foo2,#Fun<area_server1.loop.0>}<br>%% Def: <0.46.0>:{foo2,#Fun<area_server1.loop.0>}<br>%% {foo2,#Fun<area_server1.loop.0>,{fail,<0.46.0>}}<br>%% 6> foo2 ! {self(),{circle, 9}}.
<br>%% {<0.31.0>,{circle,9}}Server: Area of circle is 254.469<br><br><br>%% start/2<br>%% start(AnAtom, Fun) to register AnAtom as spawn(Fun).<br>%% Make sure your program works correctly in the case when two
<br>%% parallel processes simultaneously evaluate start/2. In this case,<br>%% you must guarantee that one of these processes succeeds and the<br>%% other fails.<br>start(AnAtom,Fun) -> <br> rpc(starter, {AnAtom,Fun}).
<br><br>%% start_server()<br>%% Starts the server loop and registers<br>%% the process as starter<br>start_server() -><br> register(starter,spawn(fun() -> loop([]) end)).<br><br>%% rpc(Pid, Request)
<br>%% Forwards Request to Server Pid<br>%% Makes process wait for Response from Server<br>rpc(Pid, Request) -><br> Pid ! {self(), Request},<br> receive<br> {Pid, Response} -><br> Response
<br> after 3000 -><br> io:format("Rpc timed out") <br> end.<br><br>%% start_fun<br>%% Starts fun Fun and registers<br>%% it as AnAtom if undefined<br>%% Returns:<br>%% {success, PID} if undefined
<br>%% {fail, PID} if allready registered<br>start_fun(undefined,{AnAtom,Fun}) -> <br> io:format("Undef:~p~n" ,[AnAtom]),<br> PID = spawn(Fun),<br> register(AnAtom,PID),<br> {success,PID};
<br>start_fun(PID,X) -> <br> io:format("Def: ~p:~p~n", [PID,X]),<br> {fail,PID}.<br><br>%% loop(x)<br>%% Processes messages send to the server<br>%% Prints the message out<br>loop(X) ->
<br> receive<br> {Pid, {AnAtom, Fun}} -><br> io:format("Received:~p~n" ,[{AnAtom, Fun}]),<br> REG = whereis(AnAtom),<br> Status = start_fun(REG, {AnAtom,Fun}),<br> %% self() has to be replaced by starter
<br> %% because self() == starter evaluates to false<br> %% rpc waits for {starter, Response}<br> Pid ! {starter,{AnAtom, Fun, Status}},<br> loop(X)<br> end.<br><br><br><br>
The circle: (Without timer)
<br>-module(conc_problems_ring).<br>-compile(export_all).<br><br>%% start_ring(N,M, Mesg)<br>%% N number of processes in Ring<br>%% M number of roundings<br>%% Mesg the message to transport<br>start_ring(N,M,Mesg) ->
<br> [Head|Pids] = [ start() || _ <- lists:seq(1,N)],<br> Head ! {self(), {Pids, [], M}, Mesg}.<br><br>%% start()<br>%% Starts the server loop<br>start() -> spawn(fun() -> loop([]) end).<br><br>%% rpc(Pid, Request)
<br>%% Forwards Request to Server Pid<br>%% Makes process wait for Response from Server<br>rpc(Pid, Request) -><br> Pid ! {self(), Request},<br> receive<br> {Pid, Response} -><br> Response
<br> end.<br><br>%% loop(x)<br>%% Processes messages send to the server<br>%% Prints the message out<br>loop(X) -><br> receive<br> {_, {Pids,VisitedPids,Rounds}, Message} -><br> io:format("~nReceived: ~p Pid: ~p Round: ~p~n" ,[Message, self(), Rounds]),
<br> {TagNP, {NPs, NVPs, NRounds}} = next_pid(Pids, VisitedPids, Rounds),<br> case {TagNP, NRounds} of<br> {last,_} -><br> io:format(" finished last~n"),
<br> true;<br> {NP,0} -><br> io:format(" finished~n"), <br> NP ! {self(), {NPs, NVPs, NRounds}, Message},<br> true;
<br> {NP,_} -><br> io:format(" pass on~n"), <br> NP ! {self(), {NPs, NVPs, NRounds}, Message}, <br> loop(X)
<br> end<br> end.<br><br>%% next_pid(NextPids, PassedPids, Rounds)<br>%% Returns the next Pid out of the NextPids list<br>%% If NextPids is empty, we finished a round<br>%% and decrease the value of Rounds.
<br>%% We can then restart by taking PassedPids as next Pids<br>next_pid([],_,0) -> {last,{[],[],[]}};<br>next_pid([],[NP|R],M) -> {NP,{R,[self()],M-1}};<br>next_pid([NP|R],X,M) -> {NP,{R,[self()|X],M}}.<br><br>
<br>Session:<br>1> c(conc_problems_ring).<br>{ok,conc_problems_ring}<br>2> conc_problems_ring:start_ring(3,2,"Hi").<br>{<0.31.0>,{[<0.39.0>,<0.40.0>],[],2},"Hi"}<br>Received: "Hi" Pid: <
0.38.0> Round: 2<br><br> pass on<br><br>Received: "Hi" Pid: <0.39.0> Round: 2<br> pass on<br> <br>Received: "Hi" Pid: <0.40.0> Round: 2<br> pass on<br> <br>Received: "Hi" Pid: <
0.39.0> Round: 1<br> pass on<br> <br>Received: "Hi" Pid: <0.38.0> Round: 1<br> finished<br> <br>Received: "Hi" Pid: <0.39.0> Round: 0<br> finished<br> <br>Received: "Hi" Pid: <
0.40.0> Round: 0<br> finished last<br>3> <br><br><br>Enjoy David Stokar</div>