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).
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
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