1
votes

I have simple erlang module and I want to rewrite it based on OTP principles. But I can not determine what opt template I should use.

Module's code:

-module(main).

-export([start/0, loop/0]).

start() -> 
    Mypid = spawn(main, loop, []),
    register( main, Mypid).

loop() ->
    receive
        [Pid, getinfo] -> Pid! [self(), welcome],
            io:fwrite( "Got ~p.~n", [Pid] ),
            // spawn new process here
            loop();
        quit -> ok;
        X ->
            io:fwrite( "Got ~p.~n", [ X ] ),
            // spawn new process here
            loop()
    end.
1

1 Answers

3
votes

gen_server would be fine.

Couple things:

  • it is a bad practice to send message to yourself
  • messages are usually tuples not lists because they are not dynamic
  • despite your comment, you do not spawn the new process. Call to loop/0 enters the same loop.

Gen_server init would hold your start/0 body. API calls sequence and proxy your calls via gen_server to handle_calls. To spawn new process on function call, add spawn function to the body of desired handle_call. Do not use handle_info to handle incoming messages -- instead of sending them call the gen_server API and 'translate' your call into gen_server:call or cast. e.g.

start_link() ->
    gen_server:start_link({local, ?MODULE}, ?MODULE, [], []).

init(_) ->
    {ok, #state{}}

welcome(Arg) ->
   gen_server:cast(?MODULE, {welcome, Arg}).

handle_cast({welcome, Arg},_,State) ->
  io:format("gen_server PID: ~p~n", [self()]),
  spawn(?MODULE, some_fun, [Arg]),
  {noreply, State}

some_fun(Arg) ->
  io:format("Incoming arguments ~p to me: ~p~n",[Arg, self()]).

I have never compiled above, but it should give you the idea.