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>