Erlang:扩展的gen_服务器

Erlang:扩展的gen_服务器,erlang,gen-server,Erlang,Gen Server,我想用一些额外的功能扩展gen\u server(创建一个gen\u server\u extra)。这些要求是: gen\u server\u extra进程的行为应类似于常规的gen\u服务器。例如,他们应该通过genu服务器接受呼叫:call、与SASL集成、适应OTC监管树等 gen\u server\u extra进程应具有由gen\u server\u extra提供的附加功能。这基本上意味着一些消息将由gen\u server\u extracode处理,而不会传递给回调模块。其余

我想用一些额外的功能扩展
gen\u server
(创建一个
gen\u server\u extra
)。这些要求是:

  • gen\u server\u extra
    进程的行为应类似于常规的
    gen\u服务器。例如,他们应该通过
    genu服务器接受呼叫:call
    、与SASL集成、适应OTC监管树等
  • gen\u server\u extra
    进程应具有由
    gen\u server\u extra
    提供的附加功能。这基本上意味着一些消息将由
    gen\u server\u extra
    code处理,而不会传递给回调模块。其余消息按原样传递给回调模块
  • gen_server_extra
    功能需要自己的状态,该状态应该对回调模块隐藏

  • 最简单的方法是什么?

    最好、最模块化的方法是在模块中实现新的行为(例如,
    gen\u ext\u server
    ),并从那里包装gen\u 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\u cast/2
    handle\u info/2
    terminate/1
    等实现类似的功能。

    好吧,我不会称之为自定义,而是一种新的行为。你需要定义自己的行为。可在trapexit.org上找到。
    然而,这些要求并不十分恰当

    让回调函数访问服务器状态的主要本质是在不中断并发细节的情况下,编写正常的顺序代码,在需要的时间和地点操纵应用程序的状态。
    否则,如果是这样的话,就实施你自己的行为。

    是的,经过一些思考,我得出了类似的设计。唯一的问题是大量的样板代码。OTP中的行为实际上是不可扩展的,这是可以理解的,因为它会影响性能和简单性。