How to tell a process to create another process and keep track of it
distributed, erlang
Solution
Okay. Now, for purposes of learning, lets do a very basic example. Others will talk of `OTP Supervisors, Process dictionaries` e.t.c. but i want to keep it easy for learning purposes. With tis example, the generator can know how many processes it has created, their `Pids`, knows when they die e.t.c.
-module(generator).
-compile(export_all).
-define(ERROR(X),error_logger:error_report(X)).
start()->
register(generator,spawn(fun() -> generator() end)),
ok.
generator()->
ProcessBuffer = [],
process_flag(trap_exit,true),
loop(ProcessBuffer).
create(Module,Function,Args)->
generator ! {create_new_proc,{Module,Function,Args}},
ok.
send_to_kids(Message)->
generator ! {tell_kids,Message},
ok.
loop(Buffer)->
receive
{create_new_proc,{M,F,A}} ->
Pid = spawn(M,F,A),
link(Pid),
loop([Pid|Buffer]);
{tell_kids,Message} ->
[ Kid ! {broadcast,Message} || Kid <- Buffer],
loop(Buffer);
{'EXIT',SomePid,Reason} ->
?ERROR(["Child has crashed",{pid,SomePid},{reason,Reason}]),
loop(lists:delete(SomePid,Buffer));
_ -> loop(Buffer)
end.
child_loop()->
receive
{broadcast,Message} ->
io:format("\n\tChild: ~p got: ~p~n",[self(),Message]),
child_loop();
_ -> child_loop()
end.
Testing in shell
E:\Applications>erl
Eshell V5.9 (abort with ^G)
1> c(generator).
{ok,generator}
2> generator:start().
ok
3> generator:create(generator,child_loop,[]).
ok
4> [generator:create(generator,child_loop,[]) || _ <- lists:seq(1,5)],ok.
ok
5> generator:send_to_kids("Erlang is good !").
Child: <0.45.0> got: "Erlang is good !"
Child: <0.44.0> got: "Erlang is good !"
Child: <0.43.0> got: "Erlang is good !"
Child: <0.42.0> got: "Erlang is good !"
Child: <0.41.0> got: "Erlang is good !"
Child: <0.39.0> got: "Erlang is good !"
ok
6> generator:send_to_kids("1+1 = 2").
Child: <0.45.0> got: "1+1 = 2"
Child: <0.44.0> got: "1+1 = 2"
Child: <0.43.0> got: "1+1 = 2"
Child: <0.42.0> got: "1+1 = 2"
Child: <0.41.0> got: "1+1 = 2"
Child: <0.39.0> got: "1+1 = 2"
ok
7>
A process registered as `generator` is started and may be told to start any number of children processes. The child process is generically created from the `{M, F, A}` combination sent to the `generator`. The generator loop keeps a track record of the processes created. It can then be told to broadcast messages to all processes. However, in practice/ production, you might not to do this, because the `generator` loop may consume lots of memory as the list `Buffer` grows since thats where we keep all the `Pids` of our processes. You can also use `ETS Tables`, or `Mnesia` e.t.c but i havenot used them in the example because they will seem a little bit more advanced. Look at this question and its answer to understand more.
Problem
How can I tell a specific process (let's call it the generator) to create a new process in Erlang? Also, how can I keep track of all the processes that the generator has created?