确保在ERLANG/OTP中切换GEN_EVENT处理程序时处理事件
题
假设我有几个版本的 gen_event
处理程序,并希望在程序运行时将它们更改:
-module(logger_all).
-behaviour(gen_event).
-export([init/1, handle_event/2, terminate/2]).
init(_Args) ->
{ok, []}.
handle_event({Severity, ErrorMsg}, State) ->
io:format("***~p*** ~p~n", [Severity, ErrorMsg]),
{ok, State}.
terminate(_Args, _State) ->
ok.
-module(logger_errors_only).
-behaviour(gen_event).
-export([init/1, handle_event/2, terminate/2]).
init(_Args) ->
{ok, []}.
handle_event({error, ErrorMsg}, State) ->
io:format("***Error*** ~p~n", [ErrorMsg]),
{ok, State}.
handle_event({_, ErrorMsg}, State) ->
{ok, State}. %% ignore everything except errors
terminate(_Args, _State) ->
ok.
显然,我可以通过删除一个处理程序并添加另一个处理程序来切换它们:
log_errors_only() ->
gen_event:delete_handler(error_man, logger_all, []),
gen_event:add_handler(error_man, logger_errors_only, []).
但这留下了种族条件的可能性。如果 error_man
仅在错误的时间收到活动,不会记录它。或者,如果我更改操作顺序,它将被记录两次,这也是不希望的。我如何确保其精确处理一次?
对于这种情况,我只能拥有一个处理程序,并继续记录级别 State
, ,但是假设这是不可接受的。
解决方案
OTP团队擅长于这样的预测需求。 gen_event有一个功能 交换活动处理程序 原子:
log_errors_only() ->
gen_event:swap_handler(error_man,
{logger_all, swapped_out},
{logger_errors_only, []}).
不隶属于 StackOverflow