OTP中,事件管理器(event manager)用来接收事件,这里的事件非常广泛,可以为错误,警告各种各样erlang允许的信息。
事件管理器拥有零个或多个事件处理器(event handler)。当事件管理器收到一个事件时,此事件会被管理器内部安装的所有处理器处理。
其实在事件管理器(gen_event behaviour)中,拥有一个[{Module, State}],其保存安装的处理器(Module模块)及对应的状态。当收到事件时,管理器遍历调用Module的
Module:handle_event/2函数进行处理。
callbacks接口
1. init(InitArg)
处理器安装后,进行初始化,返回Module对应的状态
2. handle_event(Event, State)
处理各种event
3. handle_call(Request, State)
处理同步调用
4. terminate(Arg, State)
处理器被删除或事件管理器停止时,Module调用terminate
完成详细规范请参考erlang man手册
example-日志记录模块,保存最近的5条错误日志
-module(recent_logger).
-behaviour(gen_enevt).
-export([start/0, stop/0, log/1, report/0, release/0])
%% gen_event callbacks
-export([init/1, handle_event/2, handle_call/2, terminate/2]).
-define(NAME, logger_manager).
%% start behaviour
start() ->
case gen_event:start_link({local, ?NAME}) of
Ret = {ok, _Pid} ->
gen_event:add_handler(?NAME, ?MODULE, []),
Ret;
Other ->
Other
end.
%% stop
stop() ->
gen_envent:stop(?NAME).
%% notify an envent about log
log(E) ->
gen_enevt:notify(?NAME, {log, E}).
%% report the all log
report() ->
gen_event:call(?NAME, ?MODULE, report).
%% release this handler
release() ->
gen_event:delete_handler(?NAME, ?MODULE, release).
init(_Arg) ->
io:format("start recent log handler~n"),
{ok, []}.
handle_event({log, E}, List) ->
{ok, trim([E | List])}.
handle_call(report, List) ->
List.
terminate(stop, _List) ->
io:format("recent log handler stop~n"),
ok;
terminate(release, _List) ->
io:format("recent log handler release~n"),
ok.
%% save the recent five log
trim([E1, E2, E3, E4, E5 | []) ->
[E1, E2, E3, E4, E5];
trim(List) ->
List.
gen_event使用
1. 启动gen_event
gen_event:start_link({local, ?NAME})用来启动命名为?NAME所表示宏的事件管理器。
同gen_server一样,命名可以为{global, ?NAME}或者没有命名使用Pid交互。此模块作为supervision tree的worker时,必须使用start_link启动,
而单独应用可以使用start
2. 添加一个handler
gen_event:add_handler(?NAME, ?MODULE, [])将本Module作为一个handler添加到事件管理器中,函数内部会调用Module:init/1函数,其中参数为
add_handler/3的第三个参数。
3. 通知一个事件
当我们想要事件管理器记录一个日志时,我们通过gen_enevt:notify(?NAME, {log, E}).向事件管理器发送一个事件,这样事件管理就会依次调用其内部
安装的所有处理器处理此事件,并更新对应处理器的状态。具体的处理过程在Module的handle_event/2中进行。此处是{ok, trim([E | List])}保存日志消息。
4. 删除一个事件
gen_event:delete_handler(?NAME, ?MODULE, [])我们将?MODULE指定的处理器删除,其中会调用Module:terminate/2进行清除。
5. 同步调用
gen_server:call(?NAME, ?MODULE, report)用来进行同步调用,需要注意的是:此函数不同于gen_enevt:notify/2,其拥有三个参数,第二个参数用来指明调用那个事件处理器进行处理此请求,而notify是通知所有的事件处理器某个事件,因此这里是不同的。
函数调用Module:handle_call/2返回结果,这里直接返回保存的log List
6. 停止事件管理器
如果事件管理器应用在supervision tree中,不需要提供stop函数,监督树会自动清除事件管理器。如果是单独的应用,需要调用 gen_envent:stop(?NAME)停止事件管理器。
此处与gen_server相似,具体参考supervision shutdown strategy
通过上面的描述,您对gen_enevt熟悉了么?把example代码自己书写一遍,理解会更深刻!
分享到:
相关推荐
gen_lex_hash for pc,mysql交叉编译需要用到的文件,5.1.51 and 5.1.63两个版本,5.1.67版本始终编译不出来。有需要的下载。
Gen_Signature_Android2.apk、获取签名工具。
Gen_Signature_Android.apk
包名签名查看,输入包名则可查看签名值,用于微信第三方分享 登录等设置填写,安装则可以使用,没需要任何设置,可以在安卓模拟器上使用
华硕Z87-C主板升级BIOS的工具,BIOS_updater_for_4th_Gen_Intel_Core_CPU.zip
srio_response_gen_srio_gen2_0_srio_gen_srio_reponse_SRIO_gen2_SR
gen_lyricist.dll 万能播放器仿千千静听
gen_tags.vim, 用来轻松使用 ctags/gtags的vim和neovim的异步插件 gen_tags.vim 为方便用户使用 Vim/ NeoVim,简化了 ctags/ gtags的使用。它用于为你生成和维护多个平台支持的标签,在 Windows/Linux/macOS. 上测试...
1、将2560及ramps1.4集合在一块板子上,解决了Ramps1.4组合接口繁琐,易出故障的问题。 2、可更换电机驱动,支持4988驱动和8825驱动。 3、电路板采用高质量的4层板,并专门作了散热优化处理;...
采用verilog实现RTLAB多路驱动程序
pwm_gen,PWN波形发生器,开关波形
erlang-gen_tcp手册,详细完整,网络tcp开发好东东
K210的机器码生成固件,来自https://en.bbs.sipeed.com/uploads/default/original/1X/bca0832bed92a1ada63bd05327688784e2ef14d1.zip
android 导航选项卡效果源码,带有彩色交互的导航选项卡栏。
gen_table自动从txt生成表格读写代码
资源来自pypi官网。 资源全名:gen_data_model-1.6.1.tar.gz