Erlang:扩展gen_server

Iva*_*rov 4 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 功能需要自己的状态,应该从回调模块中隐藏.

这样做最简单的方法是什么?

Ada*_*erg 7

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

首先,确保您的行为与以下内容相同gen_server:

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

% Exports...

behaviour_info(Type) -> gen_server:behaviour_info(Type).
Run Code Online (Sandbox Code Playgroud)

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

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

然后,在每个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.
Run Code Online (Sandbox Code Playgroud)

实现类似的功能为handle_cast/2,handle_info/2,terminate/1等等.