zoukankan      html  css  js  c++  java
  • Erlang OTP gen_event

    转自:http://www.myexception.cn/program/1569725.html

    Erlang OTP gen_event (0)
    原英文文档:http://www.erlang.org/erldoc?q=&x=0&y=0
    Tips:看到网页右边的搜索功能了么,保存这个实用网页吧。

       一个实现事件处理功能行为模块,可以动态的删除和增加任意数量事件的事件管理器(event_manager),事件管理器使用这个模块将实现一套标准的接口功能,包括跟踪和错误报告功能。同样他也适合OTP 监控树(supervision tree)


        每个事件处理程序被实现为一个回调模块导出一组预定义的功能:
        每一个事件处理程序都是一个回调模块,一个事件管理器必可以动态的增加和删除事件回调,所以gen_event 会比其它behaviours(gen_server,gen_fsm)容错更新好,如果安装好的事件处理回调失败(fails with Reason or returns a bad value Term),这个事件管理器是不会失败的,他会删除这个事件回调,并调用对应事件的terminate/2.如果给的参数如:{error, {'EXIT',Reasion}} or {error,Term},其它事件是不会受到影响的。
       事件管理不会自动处理(trap)exit signals,%%手动调用 process_flag(trap_exit, true). 
       如果事件管理器回调返回值里面hibernation有可以进入休眠状态(hibernation),这对于长期处于空闲状态的server来说非常好, 不过此特性会使用2个垃圾回收器(when hibernating and shortly after waking up),不适合处理非常多的事件管理器。只要其中一个事件处理返回hibernate就会使event manager进入休眠状态。
    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

    start_link() -> Result
    start_link(EventMgrName) -> Result
    Types:EventMgrName = {local,Name} | {global,GlobalName} | {via,Module,ViaName}
    Name = atom()
    GlobalName = ViaName = term()
    Result = {ok,Pid} | {error,{already_started,Pid}}
     Pid = pid()


         创建一个事件管理器进程(event_manager)这个函数会被supervisor调用创建,保证event_manager与supervisor相连接(link),
      如果EventMrName={local,Name},event manager 会像用register/2注册一样本地注册。
      如果EventMrName={global,GlobalName},event manager 会像用global:register_name/2注册一样本地注册。
      如果不提供Name就不会注册。
      如果EventMrName = {via,Module,ViaName} event manager会使用Module里面自己定义的register_name/2,unregister_name/1,whereis_name/1 and send/2,这些函数的功能和global里面功能一致,否则{via,Module,ViaName}无用

    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

    start() -> Result
    start(EventMgrName) -> Result
     
    Types:
    EventMgrName = {local,Name} | {global,GlobalName} | {via,Module,ViaName}
     Name = atom()
     GlobalName = ViaName = term()
    Result = {ok,Pid} | {error,{already_started,Pid}}
     Pid = pid()


       创建一个独立的event manager 进程,例如没有监控树,其它参见start_link/0
    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    a

    add_handler(EventMgrRef, Handler, Args) -> Result
     
    Types:
    EventMgr = 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 = ok | {'EXIT',Reason} | term()
     Reason = term()


        给event manager 增加一个新的事件回调(event handler),会调用Module:init/1来初始化他的状态
        EventMgr 参数可以:pid(),Name,{Name,Node}(如果这个事件管理注册在其它节点上){global,GlobalName}{via,Module,ViaName}
    Args 参数是传给Module:init/1使用的
    如果Module:init/1返回一个正确的值,event manager会增加event handler,此函数也会返回ok.
    如果Module:init/1带Reason的失败或返回{error,Reasion} 这具event hander会被忽略,此函数会返回{'EXIT',Reason}或{error,Reason}.
    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

    add_sup_handler(EventMgrRef, Handler, Args) -> Result
     
    Types:
    EventMgr = 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 = ok | {'EXIT',Reason} | term()
     Reason = term()
    

       
       和add_handler/3一样添加一个event handler,但会在event handler 和被调用的进程之间添加监控连接(supervise ther connection),
    如果这个进程terminateswith Reason event manager 会用Module:terminate/2 {stop,Reason} 把这个event handler 删除
    如果event handler 被删除,event manager 会发{gen_event_EXIT,Handler,Reason}给进程(the calling process):这时的Reason会有以下:
     

    •    1)normal ----使用delete_handler/3或remove_handler
    •    2)shutdown ---event_manager 终结了:is terminating
    •    3){swapped,NewHandler,Pid} 如果使用swap_handler/3或swap_sup_handler/3替换原event handler
    •    4)一个term如果由于一个错误被移除


    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

     
    notify(EventMgrRef, Event) -> ok
     
    sync_notify(EventMgrRef, Event) -> ok
     
    Types:
    EventMgrRef = Name | {Name,Node} | {global,GlobalName} | {via,Module,ViaName} | pid()
     Name = Node = atom()
     GlobalName = ViaName = term()
     Event = term()


        向已增加在event manager里面所有的event handler都发一个Event(MSG).event manager会调用所有的event handler的Module:handler_event/2.
        notify 是异步的:在消息发出后立即返回,sync_notify同步的,会在所有的event_handler处理完消息后返回ok.

    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

    call(EventMgrRef, Handler, Request) -> Result
    call(EventMgrRef, Handler, Request, Timeout) -> Result
     
    Types:
     
    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()


       一个同步call(和gen_server:call差不多)不过会指定对应的Hander来处理Request.Handler内使用handler_call/2来处理Request.
        TimeOut 是一个比0大的毫秒级或infinity.默认值为50000ms.如果规定时间内没有返回,就会call fails.
        Repeal会返回Module:handle_call/2返回,如果 event handler没有安装,会返回{error,bad_module}.callback会分别返回Reason Term ,这个函数就会返回{error,{'EXIT',Reason},{error,Term}.
    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

    delete_handler(EventMgrRef, Handler, Args) -> Result
     
    Types:
    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}
     Reason = term()


       删除event manager(EvenMgrRef)里面对应的Handler,调用Handler:terminate(Args,State).来终结这个事件.
    Result:返回Handler:terminate(Args,State)的返回值,如果没有找到安装的事件返回{error,module_not_found}.
       如果失败了就会回调返回Reason.此函数返回:{'EXIT',Reason}.

    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

    swap_handler(EventMgrRef, {Handler1,Args1}, {Handler2,Args2}) -> Result
     
    Types:
    EventMgrRef = Name | {Name,Node} | {global,GlobalName} | {via,Module,ViaName} | pid()
     Name = Node = atom()
     GlobalName = ViaName = term()
     Handler1 = Handler2 = Module | {Module,Id}
     Module = atom()
     Id = term()
     Args1 = Args2 = term()
     Result = ok | {error,Error}
     Error = {'EXIT',Reason} | term()
     Reason = term()



    在event manager (EventMgrRef)用Handler1代替Handler2

    • 1)删除Handler1-----与调用delete_handler一致:
    • 2)增加Handler2-----与调用add_handler一致:【init里面调用{Args2,Term}:Term是Handler1:terminate里面返回的】
    • 3)这2个操作没有原子性,1,2的成功没有关系的。



    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

    swap_sup_handler(EventMgrRef, {Handler1,Args1}, {Handler2,Args2}) -> Result
     
    Types:
    EventMgrRef = Name | {Name,Node} | {global,GlobalName} | {via,Module,ViaName} | pid()
     Name = Node = atom()
     GlobalName = ViaName = term()
     Handler1 = Handler 2 = Module | {Module,Id}
     Module = atom()
     Id = term()
     Args1 = Args2 = term()
     Result = ok | {error,Error}
     Error = {'EXIT',Reason} | term()
     Reason = term()



        与swap_handler/3一致,但是会Handler2和the calling process里面建立连接.

    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

    which_handlers(EventMgrRef) -> [Handler]
     
    Types:
     EventMgrRef = Name | {Name,Node} | {global,GlobalName} | {via,Module,ViaName} | pid()
     Name = Node = atom()
     GlobalName = ViaName = term()
     Handler = Module | {Module,Id}
     Module = atom()
     Id = term()



       返回event manager的事件Event handler列表
    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

    stop(EventMgrRef) -> ok
     
    Types:
    EventMgrRef = Name | {Name,Node} | {global,GlobalName} | {via,Module,ViaName} | pid()
    Name = Node = atom()
    GlobalName = ViaName = term()



    terminates the event manager 在此之前会对安装好的事件调用Module:terminate(stop,...).

    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    event handler里面的callback函数

    Module:init(InitArgs) -> {ok,State} | {ok,State,hibernate} | {error,Reason}
    Types:
    InitArgs = Args | {Args,Term}
    Args = Term = term()
    State = term()
    Reason = term()


        当一个新的event handler被加入event manager时,这个函数会被调用.
        调用gen_event:add_sup_handler/3,swap_handler/3 swap_sup_handler
        返回{ok,State,hibernate}时event manager会进入休眠状态:等待下次事件发生

    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

    Module:handle_event(Event, State) -> Result
     
    Types:
    Event = term()
    State = term()
    Result = {ok,NewState} | {ok,NewState,hibernate} | {swap_handler,Args1,NewState,Handler2,Args2} | remove_handler
    NewState = term()
    Args1 = Args2 = term()
    Handler2 = Module2 | {Module2,Id}
    Module2 = atom()
    Id = term



         当event manager收到用notify/2或sync_notify/2发送的消息时会调用:所有安装过的事件的Handler:handler_event/2
         返回{swap_handler,Args1,NewState,Handler2,Args2}时会调用Term = Module:terminate(Args1,NewState),Module2:init(Args2,Term) 【基本和swap_handler/3相同】
         返回remove_handler 时会调用Module:terminate(remove_handler,State).

    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

    Module:handle_call(Request, State) -> Result
     
    Types:
    Request = term()
    State = term()
    Result = {ok,Reply,NewState} | {ok,Reply,NewState,hibernate}| {swap_handler,Reply,Args1,NewState,Handler2,Args2}| {remove_handler, Reply}
     Reply = term()
     NewState = term()
     Args1 = Args2 = term()
     Handler2 = Module2 | {Module2,Id}
      Module2 = atom()
      Id = term()


    使用gen_event:call/3发出的信息,与handle_event类似,不过是同步的。

    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

    Module:handle_info(Info, State) -> Result
     
    Types:
    Info = term()
    State = term()
    Result = {ok,NewState} | {ok,NewState,hibernate}
     | {swap_handler,Args1,NewState,Handler2,Args2} | remove_handler
     NewState = term()
     Args1 = Args2 = term()
     Handler2 = Module2 | {Module2,Id}
      Module2 = atom()
      Id = term()


         收到除用gen_event:call/3,gen_event:notify/3,gen_event:sync_notify/3之外的任何消息。

    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

    Module:terminate(Arg, State) -> term()
     
    Types:
    Arg = Args | {stop,Reason} | stop | remove_handler
     | {error,{'EXIT',Reason}} | {error,Term}
     Args = Reason = Term = term()



    在要完成删除,清理工作时会调用。

    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

    Module:code_change(OldVsn, State, Extra) -> {ok, NewState}
     
    Types:
    OldVsn = Vsn | {down, Vsn}
    Vsn = term()
    State = NewState = term()
    Extra = term()
  • 相关阅读:
    python-判断
    python-文件读写
    python-数据类型
    python简介
    Charles--简单使用
    【模拟赛】BYVoid魔兽世界模拟赛 解题报告
    【最短路】埃雷萨拉斯寻宝(eldrethalas) 解题报告
    【递推】地铁重组(subway) 解题报告
    【背包型动态规划】灵魂分流药剂(soultap) 解题报告
    【最短路】血色先锋军(scarlet) 解题报告
  • 原文地址:https://www.cnblogs.com/yanwei-wang/p/5198332.html
Copyright © 2011-2022 走看看