我想扩展gen_server
(创建gen_server_extra
)并增加一些功能。要求是:
gen_server_extra
进程应该像常规gen_server
一样运行。例如,他们应该通过gen_server:call
接受呼叫,与SASL集成,适合OTC监管树等。gen_server_extra
进程应具有gen_server_extra
提供的附加功能。这基本上意味着一些消息将由gen_server_extra
代码处理,而不会将它们传递给回调模块。其余消息按原样传递给回调模块。gen_server_extra
功能需要自己的状态,应该从回调模块中隐藏。最简单的方法是什么?
答案 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/2
,handle_info/2
,terminate/1
等实施类似的功能。
答案 1 :(得分:-1)
好吧,我不会称之为定制,而是一种新行为。您需要定义自己的行为。 A tutorial which will take you through this 可在trapexit.org找到 但是,要求不是很合适。
给回调函数访问服务器状态的主要本质是编写正常的顺序代码,在不中断并发细节的情况下随时随地处理应用程序的状态。 否则,如果这是可行的方法,请实施自己的行为。