在OTP里,event manager是一个命名对象,它可以接收event
一个event可以是一个error、alarm或者一些应该被log的信息
在event manager里会安装一些event handler
当event manager被通知一个event时,event会被所有安装的event handler来处理
event manager实现为一个进程,而每个event handler实现为一个callback模块
event manager本质上是维护一个{Module, State}对的list,每个Module是一个event handler,State是event handler的内部状态
2,例子
将error消息输出到终端的callback模块:
-module(terminal_logger). -behaviour(gen_event). -export([init/1, handle_event/2, terminate/2). init(_Args) -> {ok, []}. handle_event(ErrorMsg, State) -> io:format("***Error*** ~p~n", [ErrorMsg]), {ok, State}. terminate(_Args, _State) -> ok.
将error消息写入到文件的callback模块:
-module(file_logger). -behaviour(gen_event). -export([init/1, handle_event/2, terminate/2]). init(File) -> {ok, Fd} = file:open(File, read). {ok, Fd}. handle_event(ErrorMsg, Fd) -> io:format(Fd, "***Error*** ~p~n", [ErrorMsg]), {ok, Fd}. terminate(_Args, Fd) -> file:close(Fd).
3,启动一个event manager
启动一个event manager来处理error需要调用如下方法:
gen_event:start_link({local, error_man})
这个方法启动一个新的event manager进程并连接它
参数{local, error_man}指定名字,在这里event manager在本地注册为error_man
gen_event:start则是启动一个独立的event manager,没有supervisor
4,添加event handler
这里是启动event manager并添加一个event handler的例子:
1> gen_event:start({local, error_man}). {ok,<0.31.0>} 2> gen_event:add_handler(error_man, terminal_logger, []). ok
gen_event:add_handler用来添加一个event hander
event manager将调用callback方法terminal_logger:init([]),参数[]为add_handler的第三个参数
init返回{ok, State},State是event handler的内部状态
init(_Args) -> {ok, []}. init(File) -> {ok, Fd} = file:open(File, read), {ok, Fd}.
5,通知event
3> gen_event:notify(error_man, no_reply). ***Error*** no_reply ok
error_man是event manager的名字,no_reply是event
event被当作一个消息发送给event manager
event接收以后event manager为每个event handler调用handle_event(Event, State),调用顺序为event handler添加的顺序相反的顺序
handle_event返回{ok, State1},State1是event handler的新状态
handle_event(ErrorMsg, State) -> io:format("***Error*** ~p~n", [ErrorMsg]), {ok, State}. handle_event(ErrorMsg, Fd) -> io:format(Fd, "***Error*** ~p~n", [ErrorMsg]), {ok, Fd}.
6,删除event handler
gen_event:delete_handler(error_man, terminal_logger, []). ok
这将发送一个消息给event manager来删除terminal_logger这个event handler
还将调用回调方法terminal_logger:terminate([], State),参数[]为delete_handler方法的第三个参数,返回值被忽略
terminate(_Args, _State) -> ok. terminate(_Args, Fd) -> file:close(Fd).
7,停止
当event manger停止之后,它将会让每个event handler调用terminate/2
7.1 在supervision tree里
不需要stop方法
7.2 独立的event manager
可以调用stop方法来停止event manager
> gen_event:stop(error_man). ok
补充:gen_event exports and callbacks
gen_event module Callback module gen_event:start_link gen_event:start gen_event:add_handler ----------------------> Module:init/1 gen_event:add_suphandler gen_event:notify ---------------------------> Module:handle_event/2 gen_event:sync_notify gen_event:call -----------------------------> Module:handle_call/2 gen_event:delete_handler -------------------> Module:terminate/2 gen_event:swap_handler ---------------------> Module1:terminate/2 Module2:init/1 gen_event:swap_sup_handler gen_event:which_handlers gen_event:stop -----------------------------> Module:terminate/2 Module:handle_info/2 Module:code_change/3