gen_event模块¶
回调函数:
gen_event module Callback module
---------------- ---------------
gen_event:start
gen_event:start_link -----> -
gen_event:add_handler
gen_event:add_sup_handler -----> Module:init/1
gen_event:notify
gen_event:sync_notify -----> Module:handle_event/2
gen_event:call -----> Module:handle_call/2
- -----> Module:handle_info/2
gen_event:delete_handler -----> Module:terminate/2
gen_event:swap_handler
gen_event:swap_sup_handler -----> Module1:terminate/2
Module2:init/1
gen_event:which_handlers -----> -
gen_event:stop -----> Module:terminate/2
- -----> Module:code_change/3
add_handler/3¶
结构:
add_handler(EventMgrRef, Handler, Args) -> Result
类型:
EventMgrRef = Name | {Name,Node} | {global,GlobalName} | {via,Module,ViaName} | pid()
Handler = Module | {Module,Id}
Args = term()
Result = ok | {'EXIT',Reason} | term()
Reason = term()
Handler:
Module: 回调模块
{Module,Id}: 当多个event handler用同一个回调模块时,用于指定event handler的唯一标识
Args: Module:init/1函数的传参
add_sup_handler/3¶
结构:
add_sup_handler(EventMgrRef, Handler, Args) -> Result
类型
EventMgrRef = Name | {Name,Node} | {global,GlobalName} | {via,Module,ViaName} | pid()
Handler = Module | {Module,Id}
Args = term()
Result = ok | {'EXIT',Reason} | term()
说明:
类似add_handler/3
不同:
1.当调用进程以Reason原因终止时,
event manager会用参数为{stop,Reason}的方法Module:terminate/2删除此event handler
2.当event handler之后被删除时,
event manager会发送消息{gen_event_EXIT,Handler,Reason}给调用进程
其中,Reason有:
normal
shutdown
{swapped,NewHandler,Pid}
error()
call/3/4¶
结构:
call(EventMgrRef, Handler, Request) -> Result
call(EventMgrRef, Handler, Request, Timeout) -> Result
类型:
EventMgrRef = Name | {Name,Node} | {global,GlobalName} | {via,Module,ViaName} | pid()
Name = Node = atom()
GlobalName = ViaName = term()
Handler = Module | {Module,Id}
Module = atom()
Id = term()
Request = term()
Timeout = int()>0 | infinity
Result = Reply | {error,Error}
Reply = term()
Error = bad_module | {'EXIT',Reason} | term()
Reason = term()
说明:
发送一个同步请求,等待返回值或超时发生
EventMgrRef, Handler: 参见add_handler/3
Request: 转发给handle_call函数
Timeout: 默认为5000
Result:
{error, bad_module}: % If the specified event handler is not installed,
{error, {'EXIT', Reason}}: % If the callback function fails with Reason
{error, Term}: % If the callback function returns an unexpected value Term
delete_handler/3¶
结构:
delete_handler(EventMgrRef, Handler, Args) -> Result
类型:
EventMgrRef = Name | {Name,Node} | {global,GlobalName} | {via,Module,ViaName} | pid()
Name = Node = atom()
GlobalName = ViaName = term()
Handler = Module | {Module,Id}
Module = atom()
Id = term()
Args = term()
Result = term() | {error,module_not_found} | {'EXIT',Reason}
说明:
从事件管理EventMgrRef中删除event handler
Args: 此参数会传给Module:terminate/2的第1个参数
返回值: 是函数Module:terminate/2的返回值
Result:
{error,module_not_found}: 如果没有安装此handler
{'EXIT',Reason}: 如果回调函数失败
notify/2¶
参见sync_notify/2
sync_notify/2¶
结构:
notify(EventMgrRef, Event) -> ok
sync_notify(EventMgrRef, Event) -> ok
类型:
EventMgrRef = Name | {Name,Node} | {global,GlobalName} | {via,Module,ViaName} | pid()
Event = term()
说明:
event manager EventMgrRef会调用每个安装了此event的event handler
的回调函数Module:handle_event/2
notify是异步请求,立即返回
sync_notify/2是同步请求,在所有的event handlers都处理完后返回ok
其他:
notify/1 does not fail even if the specified event manager does not exist,
unless it is specified as Name.
which_handlers/1¶
结构:
which_handlers(EventMgrRef) -> [Handler]
类型:
EventMgrRef = Name | {Name,Node} | {global,GlobalName} | {via,Module,ViaName} | pid()
Name = Node = atom()
GlobalName = ViaName = term()
Handler = Module | {Module,Id}
Module = atom()
Id = term()
实例¶
terminal_logger.erl:
-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.
file_logger.erl:
-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).
启动:
// start_link通常用于supervisor监控树
// start通常用于单独的事件管理
1> gen_event:start({local, error_man}).
{ok,<0.31.0>}
// 此函数会调用terminal_logger:init([])
2> gen_event:add_handler(error_man, terminal_logger, []).
ok
// 对file_logger类事件来说, 会调用
// terminal_logger:init([])
增加handler:
3> gen_event:add_handler(error_man, file_logger, ["/tmp/file.txt"]).
// 会调用
// file_logger:init(["/tmp/file.txt"])
消息发送:
4> gen_event:notify(error_man, no_reply).
// 会调用回调函数
1.对terminal_logger:
handle_event(ErrorMsg, State) ->
io:format("***Error*** ~p~n", [ErrorMsg]),
{ok, State}.
2.对file_logger:
handle_event(ErrorMsg, Fd) ->
io:format(Fd, "***Error*** ~p~n", [ErrorMsg]),
{ok, Fd}.
删除handler:
5> gen_event:delete_handler(error_man, terminal_logger, []).
ok
6> gen_event:delete_handler(error_man, file_logger, []).
ok
停止:
> gen_event:stop(error_man).
ok
处理其他消息:
handle_info({'EXIT', Pid, Reason}, State) ->
..code to handle exits here..
{ok, NewState}.
code_change(OldVsn, State, Extra) ->
..code to convert state (and more) during code change
{ok, NewState}