Erlang:扩展gen_server

时间:2011-07-19 09:43:22

标签: erlang gen-server

我想扩展gen_server(创建gen_server_extra)并增加一些功能。要求是:

  1. gen_server_extra进程应该像常规gen_server一样运行。例如,他们应该通过gen_server:call接受呼叫,与SASL集成,适合OTC监管树等。
  2. gen_server_extra进程应具有gen_server_extra提供的附加功能。这基本上意味着一些消息将由gen_server_extra代码处理,而不会将它们传递给回调模块。其余消息按原样传递给回调模块。
  3. gen_server_extra功能需要自己的状态,应该从回调模块中隐藏。
  4. 最简单的方法是什么?

2 个答案:

答案 0 :(得分:7)

最好的,最模块化的方法是在模块中实现新行为(例如gen_ext_server)并从那里包装gen_server行为。

首先,确保您的行为与gen_server相同:

-module(gen_ext_server).
-behavior(gen_server).

% Exports...

behaviour_info(Type) -> gen_server:behaviour_info(Type).

实现gen_server所需的所有回调,保留在您所在州实现行为的回调模块的名称:

init([Mod|ExtraArgs]) ->
    % ...
    ModState = Mod:init(ExtraArgs),
    #state{mod = Mod, mod_state = ModState, internal = [...]}

然后,在每个gen_server回调中,实现您的行为,然后在需要时调用回调模块:

handle_call(internal, _From, State) ->
    % Do internal stuff...
    {reply, ok, State};
handle_call(Normal, From, State = #state{mod = Mod, mod_state = ModState}) ->
    case Mod:handle_call(Normal, From, ModState) of
        {reply, Reply, NewState} ->
            {reply, Reply, #state{mod_state = NewState};
        ... ->
            ...
    end.

handle_cast/2handle_info/2terminate/1等实施类似的功能。

答案 1 :(得分:-1)

好吧,我不会称之为定制,而是一种新行为。您需要定义自己的行为。 A tutorial which will take you through this 可在trapexit.org找到 但是,要求不是很合适。

给回调函数访问服务器状态的主要本质是编写正常的顺序代码,在不中断并发细节的情况下随时随地处理应用程序的状态。 否则,如果这是可行的方法,请实施自己的行为。