【问题标题】:What OTP behaviors should I use for such module?我应该对此类模块使用哪些 OTP 行为?
【发布时间】:2012-06-09 02:14:14
【问题描述】:

我有一个简单的 erlang 模块,我想根据 OTP 原则重写它。但我无法确定我应该使用哪个 opt 模板。

模块代码:

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

【问题讨论】:

    标签: erlang erlang-otp


    【解决方案1】:

    gen_server 会很好。

    几件事:

    • 向自己发送消息是一种不好的做法
    • 消息通常是元组而不是列表,因为它们不是动态的
    • 尽管您发表了评论,但您并未生成新进程。 调用 loop/0 进入同一个循环。

    Gen_server init 将保存您的 start/0 正文。 API 调用序列并将您的调用通过 gen_server 代理到 handle_calls。要在函数调用上生成新进程,请将 spawn 函数添加到所需的 handle_call 的主体中。不要使用 handle_info 来处理传入的消息——而不是发送它们调用 gen_server API 并将您的调用“翻译”为 gen_server:call 或 cast。例如

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

    我从来没有在上面编译过,但它应该给你的想法。

    【讨论】:

    • 谢谢,但是接收部分应该在哪里?或者我可以在生成的some_fun 进程中通过?MODULE 进程接收消息吗?
    • 接收正文在gen_server 模块中对您隐藏。通过回调函数接收消息
    • 是的.. !语法很花哨,但也很难追踪。在实际系统中,并行化隐藏在众所周知的行为中(如 gen_srv)并包裹在函数调用中。
    • 是的,您可以在新进程中接收消息.. 但您首先需要知道它的 PID 才能向它发送消息。要解决这个问题,请使用 handle_call 并返回 PID。顺便提一句。 handle_info 基本上是 gen_* 行为的接收块,但正如我之前所说,导出的 API 更好。
    猜你喜欢
    • 2011-11-21
    • 1970-01-01
    • 2020-06-27
    • 2017-08-11
    • 1970-01-01
    • 1970-01-01
    • 2010-09-22
    • 2015-08-14
    • 2014-04-21
    相关资源
    最近更新 更多