4

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?

user1301428
  • 1,743
  • 3
  • 25
  • 57

2 Answers2

4

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.
Community
  • 1
  • 1
Muzaaya Joshua
  • 7,736
  • 3
  • 47
  • 86
  • Thank you! Where is exactly though does the process generate a new one? And to keep track of the generated processes, couldn't I just use a variable? – user1301428 Dec 05 '12 at 08:45
  • using the function `generator:create/3`, you ask the `generator` process to spawn a new process which will execute the provided `{M,F,A}`. follow the generator `loop/1` when it receives a message `{create_new_proc,{M,F,A}}` and then see how i use the function `create/3` in shell – Muzaaya Joshua Dec 05 '12 at 13:31
  • 1
    If my eyes are correct .. then this won't work as expected under crashes. There is no `trap_exit` process flag so the `'EXIT'` will never arrive. Also, sometimes you want to use `spawn_link` or perhaps even `spawn_monitor` to keep track of the error state of processes if they crash. A more complete example would maybe keep the processes spawned in a simple_one_for_one supervisor tree. – I GIVE CRAP ANSWERS Dec 05 '12 at 15:50
  • true. yet, like i said. the person who asked the question didnot need complex topics included. All they needed was an illustration of a small concept. but you are right, i have edited the answer to include a line `process_flag(trap_exit,true).` – Muzaaya Joshua Dec 06 '12 at 05:36
1

You can check: http://www.erlang.org/doc/design_principles/des_princ.html In terms os Erlang "Generator" was a "Supervisor"

couchemar
  • 1,927
  • 19
  • 22
  • Thank you for your help, but unfortunately I find it very difficult to understand that part of the documentation. Can you show me some actual code? – user1301428 Dec 05 '12 at 07:09