Exercise 4-2: The Process Ring (continued)

144 views
Skip to first unread message

Ivan Uemlianin

unread,
Mar 7, 2010, 5:27:28 PM3/7/10
to Erlang Programming
Dear All

Apologies for opening a new topic. I don't seem to be able to reply
to the existing thread:

http://groups.google.com/group/erlang-programming-book/browse_thread/thread/1e5a7fe0f96a2cc6

Here is my solution. I don't know if I understood the question
properly: I set up a process ring of N processes, then I send a single
message N steps along the ring.

Each messenger process is registered with a name derived from its
position in the list (eg the third in the list is given the atom name
'3'). This simplifies creating the ring a little, but I don't know if
it's bad practice.

It's very interesting to read all the different solutions!

Best wishes

Ivan


-module(ring).
-export([start/3, messenger/2]).

start(MSteps, NMessengers, Message) ->
MessengerList = createMessengerList(NMessengers, self()),
[Starter | _Rest] = MessengerList,
Starter ! {send, MSteps, Message},
receive
{stop, _Pid} ->
broadcast({stop, self()}, MessengerList)
end,
ok.

messenger(Supervisor, Target) ->
receive
{stop, Supervisor} ->
io:format("~w: Received stop~n", [self()]);
{send, 0, _Message} ->
io:format("~w: Sending stop to Supervisor.~n", [self()]),
Supervisor ! {stop, self()},
messenger(Supervisor, Target);
{send, N, Message} ->
io:format("~w: Sending ~w to ~p~n", [self(), Message,
whereis(Target)]),
Target ! {send, N-1, Message},
messenger(Supervisor, Target)
end,
ok.

% private functions

createMessengerList(N, SupId) ->
% todo: where N > 1
SrcAtom = atomFromInt(N),
register(SrcAtom, spawn(ring, messenger, [SupId, atomFromInt(1)])),
cml(N-1, SupId, [SrcAtom], SrcAtom).

cml(0, _SupId, List, _TgtAtom) ->
List;

cml(N, SupId, List, TgtAtom) ->
SrcAtom = atomFromInt(N),
register(SrcAtom, spawn(ring, messenger, [SupId, TgtAtom])),
cml(N-1, SupId, [ SrcAtom | List], SrcAtom).

atomFromInt(N) ->
list_to_atom(integer_to_list(N)).

broadcast(_, []) -> [];
broadcast(Message, [H|T]) ->
H ! Message,
broadcast(Message, T).

Hynek Vychodil

unread,
Mar 8, 2010, 5:09:37 AM3/8/10
to erlang-prog...@googlegroups.com
On Sun, Mar 7, 2010 at 11:27 PM, Ivan Uemlianin <iv...@llaisdy.com> wrote:
> Dear All
>
> Apologies for opening a new topic.  I don't seem to be able to reply
> to the existing thread:
>
> http://groups.google.com/group/erlang-programming-book/browse_thread/thread/1e5a7fe0f96a2cc6
>
> Here is my solution.  I don't know if I understood the question
> properly: I set up a process ring of N processes, then I send a single
> message N steps along the ring.
>
> Each messenger process is registered with a name derived from its
> position in the list (eg the third in the list is given the atom name
> '3').  This simplifies creating the ring a little, but I don't know if
> it's bad practice.

No, it is bad practice. Registered process is something like global
variable. Making atoms is bad practice too. If you can avoid it, do
it.

> --
> Erlang Programming Website:
> http://www.erlangprogramming.org/
>

It can be solved in far simpler way.

-module(ring).

-export([start/3]).

start(M, N, Msg) when
is_integer(M), M > 0,
is_integer(N), N > 0 ->
First = start_ring(N, self()),
debug_msg(M, 1, Msg),
First ! {msg, M, Msg},
last_loop(First).

start_ring(1, Next) -> Next;
start_ring(N, Next) ->
start_ring(N - 1, spawn(fun() -> loop(Next, N) end)).

loop(Next, N) ->
receive
{msg, 1, Msg} = Message ->
debug_msg(1, N, Msg),
Next ! Message;
{msg, M, Msg} = Message ->
debug_msg(M, N, Msg),
Next ! Message, loop(Next, N)
end.

last_loop(First) ->
receive
{msg, 1, _Msg} -> ok;
{msg, M, Msg} ->
debug_msg(M - 1, 1, Msg),
First ! {msg, M - 1, Msg},
last_loop(First)
end.

debug_msg(M, N, Msg) ->
io:format("~p. process sending: ~p. ~p~n", [N, M, Msg]).

--
--Hynek (Pichi) Vychodil

Analyze your data in minutes. Share your insights instantly. Thrill
your boss. Be a data hero!
Try GoodData now for free: www.gooddata.com

Ivan Uemlianin

unread,
Mar 9, 2010, 3:30:30 AM3/9/10
to Erlang Programming
Dear Hynek

On Mar 8, 10:09 am, Hynek Vychodil <vychodil.hy...@gmail.com> wrote:
> No, it is bad practice. Registered process is something like global
> variable. Making atoms is bad practice too. If you can avoid it, do
> it.

Alas, I feared as much. The global variable metaphor is a good one.
Thanks for your comment and your code.

Best wishes

Ivan

Reply all
Reply to author
Forward
0 new messages