• Erlang模块gen_fsm翻译


    模块摘要
        通用有限状态机行为。
     
    描述
        用于实现有限状态机的行为模块。使用该模块实现的通用有限状态机进程(gen_fsm)将具有一组标准的接口函数,并包括用于跟踪和错误报告的功能。它也适用于OTP监督树。有关更多信息,请参阅OTP设计原则。
        gen_fsm假定所有特定部分都位于回调模块中,导出预定义的函数集。行为函数和回调函数之间的关系可以说明如下:
    gen_fsm module Callback module
    -------------- ---------------
    gen_fsm:start_link -----> Module:init/1
     
    gen_fsm:send_event -----> Module:StateName/2
     
    gen_fsm:send_all_state_event -----> Module:handle_event/3
     
    gen_fsm:sync_send_event -----> Module:StateName/3
     
    gen_fsm:sync_send_all_state_event -----> Module:handle_sync_event/4
     
    - -----> Module:handle_info/3
     
    - -----> Module:terminate/3
     
    - -----> Module:code_change/4
        如果回调函数失败或返回错误值,gen_fsm将终止。
        gen_fsm处理系统消息,如sys(3)中所述。该SYS模块可用于调试gen_fsm。
        请注意,gen_fsm不会自动捕获退出信号,必须在回调模块中明确启动。
        除非另有说明,否则如果指定的gen_fsm不存在或者给出了错误的参数,则此模块中的所有函数都将失败。
        如果回调函数指定'hibernate'而不是超时值,gen_fsm进程可以进入休眠状态(参见erlang(3))。如果预计服务器长时间处于空闲状态,这可能很有用。但是,应谨慎使用此功能,因为休眠意味着至少有两个垃圾收集(在休眠时和唤醒后不久),对于忙的状态机器并不想在每一次调用之间处理垃圾回收。
     
    导出
    start_link(Module, Args, Options) -> Result
    start_link(FsmName, Module, Args, Options) -> Result
        Types:
            FsmName = {local,Name} | {global,GlobalName} | {via,Module,ViaName}
             Name = atom()
             GlobalName = ViaName = term()
            Module = atom()
            Args = term()
            Options = [Option]
             Option = {debug,Dbgs} | {timeout,Time} | {spawn_opt,SOpts}
             Dbgs = [Dbg]
             Dbg = trace | log | statistics | {log_to_file,FileName} | {install,{Func,FuncState}}
             SOpts = [SOpt]
             SOpt - 见erlang:spawn_opt/2,3,4,5
            Result = {ok,Pid} | ignore | {error,Error}
             Pid = pid()
             Error = {already_started,Pid} | term()
        创建gen_fsm进程作为监督树的一部分。该功能应由监督树直接或间接调用。除其他外,它将确保gen_fsm链接到监督树。
        gen_fsm进程调用Module:init/1进行初始化。为确保同步启动过程,在Module:init/1返回之前,start_link/3,4不会返回。
        如果FsmName = {local,Name},则gen_fsm使用register/2在本地注册为Name。如果FsmName = {global,GlobalName},则gen_fsm使用global:register_name/2全局注册为GlobalName。如果EventMgrName={via,Module,ViaName},则事件管理器注册用Module表示的注册表。所述模块的回调应该导出的函数register_name/2,unregister_name/1,whereis_name/1和send/2,其行为应与global中的相应函数相同。因此,{via,global,GlobalName}是有效的引用。
        如果未提供名称,则不会注册gen_fsm。
        Module是回调模块的名称。
        Args是一个任意项,它作为参数传递给Module:init/1。
        如果选项{timeout,Time}存在,则允许gen_fsm花费Time毫秒初始化,或者它将被终止,启动函数将返回 {error,timeout}。
        如果存在选项{debug,Dbgs},则将为Dbgs中的每个项调用相应的sys函数。见sys(3)。
        如果选项{spawn_opt,SOpts}存在,则SOpts将作为选项列表传递给spawn_opt BIF,后者用于生成gen_fsm进程。见erlang(3)。
        注意
            目前不允许使用spawn选项monitor,但会导致函数失败,原因为badarg。
        如果gen_fsm成功创建并初始化,则函数返回{ok,Pid},其中Pid是gen_fsm的pid。如果已存在具有指定FsmName的进程,则该函数返回 {error,{already_started,Pid}},其中Pid是该进程的pid。
        如果Module:init/1因Reason而失败,则函数返回{error,Reason}。如果Module:init/1返回{stop,Reason}或ignore,则进程终止,函数分别返回{error,Reason}或ignore。
     
    start(Module, Args, Options) -> Result
    start(FsmName, Module, Args, Options) -> Result
        Types:
            FsmName = {local,Name} | {global,GlobalName} | {via,Module,ViaName}
             Name = atom()
             GlobalName = ViaName = term()
            Module = atom()
            Args = term()
            Options = [Option]
             Option = {debug,Dbgs} | {timeout,Time} | {spawn_opt,SOpts}
             Dbgs = [Dbg]
             Dbg = trace | log | statistics | {log_to_file,FileName} | {install,{Func,FuncState}}
             SOpts = [term()]
            Result = {ok,Pid} | ignore | {error,Error}
             Pid = pid()
             Error = {already_started,Pid} | term()
        创建一个独立的gen_fsm进程,即gen_fsm,它不是监督树的一部分,因此没有监督者。
        有关参数和返回值的说明,请参见start_link/3,4。
     
    send_event(FsmRef, Event) -> ok
        Types:
            FsmRef = Name | {Name,Node} | {global,GlobalName} | {via,Module,ViaName} | pid()
             Name = Node = atom()
             GlobalName = ViaName = term()
            Event = term()
        将事件异步发送到gen_fsm FsmRef并立即返回ok。gen_fsm将调用Module:StateName/2来处理事件,其中StateName是gen_fsm的当前状态的名称。
        FsmRef可以是:
        pid,
        Name,如果gen_fsm在本地注册,
        {Name,Node},如果gen_fsm在另一个节点本地注册,或者
        {global,GlobalName},如果gen_fsm是全局注册的,
        {via,Module,ViaName},如果事件管理器是通过可选进程注册表注册的,
        Event是一个任意项,作为Module:StateName/2的参数之一传递。
     
    send_all_state_event(FsmRef, Event) -> ok
        Types:
            FsmRef = Name | {Name,Node} | {global,GlobalName} | {via,Module,ViaName} | pid()
             Name = Node = atom()
             GlobalName = ViaName = term()
            Event = term()
        将事件异步发送到gen_fsm FsmRef并立即返回ok。gen_fsm将调用Module:handle_event/3来处理事件。
        有关参数的说明,请参阅send_event/2。
        send_event和send_all_state_event之间的区别在于使用哪个回调函数来处理事件。在每个状态下发送事件以相同方式被处理,此函数很有用,因为在每个状态名称函数中只需要一个handle_event子句来处理事件而不是每个状态名函数一个子句。
     
    sync_send_event(FsmRef, Event) -> Reply
    sync_send_event(FsmRef, Event, Timeout) -> Reply
        Types:
            FsmRef = Name | {Name,Node} | {global,GlobalName} | {via,Module,ViaName} | pid()
             Name = Node = atom()
             GlobalName = ViaName = term()
            Event = term()
            Timeout = int()>0 | infinity
            Reply = term()
        将事件发送到gen_fsm FsmRef并等待,直到回复到达或发生超时。gen_fsm将调用Module:StateName/3来处理事件,其中 StateName是gen_fsm的当前状态的名称。
        有关FsmRef和Event 的说明,请参阅send_event/2。
        Timeout是一个大于零的整数,它指定等待回复的毫秒数,或无限期等待的原子infinity。默认值为5000.如果在指定时间内未收到回复,则函数调用失败。
        返回值Reply在Module:StateName/3的返回值中定义。
        在OTP R12B/Erlang 5.6中删除了在连接到客户端时,如果服务器在调用期间挂了,有时会消耗服务器退出消息的古老行为。
     
    sync_send_all_state_event(FsmRef, Event) -> Reply
    sync_send_all_state_event(FsmRef, Event, Timeout) -> Reply
        Types:
            FsmRef = Name | {Name,Node} | {global,GlobalName} | {via,Module,ViaName} | pid()
             Name = Node = atom()
             GlobalName = ViaName = term()
            Event = term()
            Timeout = int()>0 | infinity
            Reply = term()
        将事件发送到gen_fsm FsmRef并等待,直到回复到达或发生超时。gen_fsm将调用Module:handle_sync_event/4来处理事件。
        有关FsmRef和Event的说明,请参阅send_event/2。有关Timeout和Reply的说明,请参阅sync_send_event/3。
        见send_all_state_event/2,讨论sync_send_event和sync_send_all_state_event的区别。
     
    reply(Caller, Reply) -> true
        Types:
            Caller - 见下面
            Reply = term()
        当无法在Module:State/3或Module:handle_sync_event/4的返回值中定义回复时,gen_fsm可以使用此函数向客户端进程显式发送回复,当调用sync_send_event/2,3或sync_send_all_state_event/2,3。 
        Caller必须是提供给回调函数的From参数。Reply是一个任意项,它将作为sync_send_event/2,3或sync_send_all_state_event/2,3的返回值返回给客户端。
     
    send_event_after(Time, Event) -> Ref
        Types:
            Time = integer()
            Event = term()
            Ref = reference()
        在gen_fsm内部发送延迟事件,在time ms后调用此函数。使用cancel_timer/1可用于取消延迟发送的引用,立即返回。
        gen_fsm将调用Module:StateName/2来处理事件,其中StateName是传递延迟事件时gen_fsm的当前状态的名称。
        Event是一个任意项,作为Module:StateName/2的参数之一传递。
     
    start_timer(Time, Msg) -> Ref
        Types:
            Time = integer()
            Msg = term()
            Ref = reference()
        在gen_fsm内部发送超时事件,在Time ms后调用此函数。立即返回可用于使用cancel_timer/1取消计时器的引用。
        gen_fsm将调用Module:StateName/2来处理事件,其中StateName是传递超时消息时gen_fsm的当前状态的名称。
        Msg是一个任意的术语,它在超时消息{timeout,Ref,Msg}中传递,作为Module:StateName/2的参数之一。
     
    cancel_timer(Ref) -> RemainingTime | false
        Types:
            Ref = reference()
            RemainingTime = integer()
        取消gen_fsm中Ref引用的内部计时器。
        Ref是从send_event_after/2 或 start_timer/2返回的引用。
        如果计时器已经超时,但事件尚未发送,则会被取消,就好像它没有超时一样,因此从此函数返回后将没有错误的计时器事件。
        如果Ref引用活动计时器,则返回以毫秒为单位的剩余时间,直到计时器到期为止,否则返回false。
     
    enter_loop(Module, Options, StateName, StateData)
    enter_loop(Module, Options, StateName, StateData, FsmName)
    enter_loop(Module, Options, StateName, StateData, Timeout)
    enter_loop(Module, Options, StateName, StateData, FsmName, Timeout)
        Types:
            Module = atom()
            Options = [Option]
             Option = {debug,Dbgs}
              Dbgs = [Dbg]
               Dbg = trace | log | statistics | {log_to_file,FileName} | {install,{Func,FuncState}}
            StateName = atom()
            StateData = term()
            FsmName = {local,Name} | {global,GlobalName} | {via,Module,ViaName}
             Name = atom()
             GlobalName = ViaName = term()
            Timeout = int() | infinity
        将现有进程转换为gen_fsm。不返回,而是调用进程将进入gen_fsm接收receive循环并成为gen_fsm进程。该进程必须使用proc_lib中的启动函数被启动,参看proc_lib(3)。用户对进程初始化负责,包括注册名字。
        当需要比gen_fsm行为提供的更复杂的初始化过程时,此函数很有用。
        Module,Options和FsmName与调用start[_link]/3,4时的含义相同。但是,如果指定了FsmName,则必须在调用此函数之前相应地注册该进程。
        StateName,StateData和Timeout与Module:init/1的返回值具有相同的含义 。此外,回调模块Module不需要导出init/1功能。
        失败:如果调用进程未由proc_lib启动函数启动,或者未根据FsmName注册。
     
    回调函数
        应从gen_fsm回调模块导出以下函数。
        在描述中,表达式state name用于表示状态机的状态。state data用于表示实现状态机的Erlang进程的内部状态。
     
    导出
    Module:init(InitArgs) -> {ok,State} | {ok,State,hibernate} | {error,Reason}
        Types:
            InitArgs = Args | {Args,Term}
            Args = Term = term()
            State = term()
            Reason = term()
        每当将新事件处理程序添加到事件管理器时,都会调用此函数来初始化事件处理程序。
        如果添加了事件处理程序,由于调用gen_event:add_handler/3或gen_event:add_sup_handler/3,则InitArgs是这些函数的Args参数。
        如果事件处理程序由于调用gen_event:swap_handler/3或gen_event:swap_sup_handler/3而替换另一个事件处理程序,或者由于来自其他一个回调函数的交换返回元组,则InitArgs是一个元组{Args,Term} 其中Args是函数call/return元组中提供的参数,Term是终止旧事件处理程序的结果,请参阅gen_event:swap_handler/3。
        如果成功,该函数应返回{ok,State}或{ok,State,hibernate},其中State是事件处理程序的初始内部状态。
        如果返回{ok,State,hibernate},则事件管理器将进入休眠状态(通过调用proc_lib:hibernate/3),等待下一个事件发生。 
     
    Module:StateName(Event, StateData) -> Result
        Types:
            Event = timeout | term()
            StateData = term()
            Result = {next_state,NextStateName,NewStateData} 
        | {next_state,NextStateName,NewStateData,Timeout}
        | {next_state,NextStateName,NewStateData,hibernate}
        | {stop,Reason,NewStateData}
             NextStateName = atom()
             NewStateData = term()
             Timeout = int()>0 | infinity
             Reason = term()
        每个可能的状态名称应该有一个此函数的实例。每当gen_fsm接收到使用gen_fsm:send_event/2发送的事件时,将调用与当前状态名称StateName同名的此函数的实例来处理该事件。 如果发生超时,也会调用它。
        事件是原子timeout,如果发生超时,Event提供参数给send_event/2。
        StateData是gen_fsm的状态数据。
        如果函数返回{next_state,NextStateName,NewStateData},{next_state,NextStateName,NewStateData,Timeout}或{next_state,NextStateName,NewStateData,hibernate},gen_fsm将继续执行,当前状态名称设置为NextStateName并且可能更新状态数据NewStateData。 有关Timeout和hibernate的说明,请参阅Module:init/1。
        如果函数返回{stop,Reason,NewStateData},gen_fsm将调用Module:terminate(Reason,NewStateData)并终止。      
     
    Module:handle_event(Event, StateName, StateData) -> Result
        Types:
            Event = term()
            StateName = atom()
            StateData = term()
            Result = {next_state,NextStateName,NewStateData} 
            | {next_state,NextStateName,NewStateData,Timeout}
            | {next_state,NextStateName,NewStateData,hibernate}
            | {stop,Reason,NewStateData}
            NextStateName = atom()
            NewStateData = term()
            Timeout = int()>0 | infinity
            Reason = term()   
        每当gen_fsm接收到使用gen_fsm:send_all_state_event/2发送的事件时,就会调用此函数来处理该事件。
        StateName是gen_fsm的当前状态名称。
        有关其他参数和可能的返回值的说明,请参阅Module:StateName/2。 
     
    Module:StateName(Event, From, StateData) -> Result
        Types:
            Event = term()
            From = {pid(),Tag}
            StateData = term()
            Result = {reply,Reply,NextStateName,NewStateData}
            | {reply,Reply,NextStateName,NewStateData,Timeout}
            | {reply,Reply,NextStateName,NewStateData,hibernate}
            | {next_state,NextStateName,NewStateData}
            | {next_state,NextStateName,NewStateData,Timeout}
            | {next_state,NextStateName,NewStateData,hibernate}
            | {stop,Reason,Reply,NewStateData} | {stop,Reason,NewStateData}
            Reply = term()
            NextStateName = atom()
            NewStateData = term()
            Timeout = int()>0 | infinity
            Reason = normal | term()   
        每个可能的状态名称应该有一个此函数的实例。每当gen_fsm接收到使用gen_fsm:sync_send_event/2,3发送的事件时,将调用与当前状态名称StateName同名的此函数的实例来处理该事件。
        Event是提供给sync_send_event的Event参数。
        From是一个元组{Pid,Tag},其中Pid是名为sync_send_event/2,3进程的pid,Tag是唯一标记。
        StateData是gen_fsm的状态数据。
        如果函数返回{reply,Reply,NextStateName,NewStateData},{reply,Reply,NextStateName,NewStateData,Timeout}或{reply,Reply,NextStateName,NewStateData,hibernate},则Reply将给回到From作为sync_send_event/2,3的返回值。然后gen_fsm继续执行,当前状态名称设置为NextStateName,并且可能更新状态数据NewStateData。有关Timeout和hibernate的说明,请参阅Module:init/1。
        如果函数返回{next_state,NextStateName,NewStateData},{next_state,NextStateName,NewStateData,Timeout}或{next_state,NextStateName,NewStateData,hibernate},gen_fsm将继续使用NewStateData在NextStateName中执行。必须使用gen_fsm:reply/2明确给出对From的任何回复。
        如果函数返回{stop,Reason,Reply,NewStateData},则回复将返回From。如果函数返回{stop,Reason,NewStateData},则必须使用gen_fsm:reply/2显式给出对From的任何回复。然后gen_fsm将调用Module:terminate(Reason,NewStateData)并终止。         
     
    Module:handle_sync_event(Event, From, StateName, StateData) -> Result
        Types:
            Event = term()
            From = {pid(),Tag}
            StateName = atom()
            StateData = term()
            Result = {reply,Reply,NextStateName,NewStateData}
            | {reply,Reply,NextStateName,NewStateData,Timeout}
            | {reply,Reply,NextStateName,NewStateData,hibernate}
            | {next_state,NextStateName,NewStateData}
            | {next_state,NextStateName,NewStateData,Timeout}
            | {next_state,NextStateName,NewStateData,hibernate}
            | {stop,Reason,Reply,NewStateData} | {stop,Reason,NewStateData}
             Reply = term()
             NextStateName = atom()
             NewStateData = term()
             Timeout = int()>0 | infinity
             Reason = term()
        每当gen_fsm接收到使用gen_fsm:sync_send_all_state_event/2,3发送的事件时,将调用此函数来处理该事件。
        StateName是gen_fsm的当前状态名称。
        有关其他参数和可能的返回值的说明,请参阅Module:StateName/3。
     
    Module:handle_info(Info, StateName, StateData) -> Result
        Types:
            Info = term()
            StateName = atom()
            StateData = term()
            Result = {next_state,NextStateName,NewStateData}
            | {next_state,NextStateName,NewStateData,Timeout}
            | {next_state,NextStateName,NewStateData,hibernate}
            | {stop,Reason,NewStateData}
            NextStateName = atom()
            NewStateData = term()
            Timeout = int()>0 | infinity
            Reason = normal | term()
        当gen_fsm接收到除同步或异步事件(或系统消息)之外的任何其他消息时,将调用此函数。
        Info是收到的消息。
        有关其他参数和可能的返回值的说明,请参阅Module:StateName/2。
     
    Module:terminate(Reason, StateName, StateData)
        Types:
            Reason = normal | shutdown | {shutdown,term()} | term()
            StateName = atom()
            StateData = term()
        当gen_fsm即将终止时,该函数被gen_fsm调用。它应该与Module:init/1相反,并进行任何必要的清理。返回时,gen_fsm以Reason结束。返回值被忽略。
        Reason是表示停止原因的术语,StateName是当前状态名称,StateData是gen_fsm的状态数据。
        Reason取决于gen_fsm为何终止。如果是因为另一个回调函数返回了一个停止元组{stop,..},则Reason将具有该元组中指定的值。如果是由于失败,则Reason是错误原因。
        如果gen_fsm是监督树的一部分并且由其主管命令终止,则如果满足以下条件,则将使用Reason = shutdown调用此函数:
        gen_fsm已被设置为捕获退出信号,并且监督者的子规范中定义的关闭策略是整数超时值,而不是brutal_kill。
        即使gen_fsm不是监督树的一部分,如果它从其父级接收到“EXIT”消息,也将调用该函数。Reason与“EXIT”消息中的原因相同。
        否则,gen_fsm将立即终止。
        请注意,除了正常,关闭或{shutdown,Term}之外的任何其他原因,假定gen_fsm由于错误而终止,并且使用error_logger:format/2发出错误报告。 
     
    Module:code_change(OldVsn, StateName, StateData, Extra) -> {ok, NextStateName, NewStateData}
        Types:
            OldVsn = Vsn | {down, Vsn}
            Vsn = term()
            StateName = NextStateName = atom()
            StateData = NewStateData = term()
            Extra = term()
        当gen_fsm在发布升级/降级期间更新其内部状态数据时,即在appup文件中给出Change= {advanced,Extra}的指令{update,Module,Change,...}时,将调用此函数。 见OTP设计原则。
        在升级的情况下,OldVsn是Vsn,在降级的情况下,OldVsn是{down,Vsn}。 Vsn由旧版本的回调模块Module的vsn属性定义。 如果未定义此类属性,则版本是BEAM文件的校验和。
        StateName是当前状态名称,StateData是gen_fsm的内部状态数据。
        Extra从更新指令的{advanced,Extra}部分按原样传递。
        该函数应返回新的当前状态名称和更新的内部数据。
     
    Module:format_status(Opt, [PDict, StateData]) -> Status
        Types:
            Opt = normal | terminate
            PDict = [{Key, Value}]
            StateData = term()
            Status = term()
        请注意,该回调可选,所以回调模块不需要导出它,这个回调模块提供一个默认实现,该函数返回回调模块状态。
     
        在以下情况下,gen_fsm进程会调用此函数:
        调用sys:get_status/1,2之一以获取gen_fsm状态。对于这种情况,Opt设置为原子normal。
        gen_fsm异常终止并记录错误。对于这种情况,选项设置为原子terminate。
        此函数可用于自定义这些情况的gen_fsm状态的形式和外观。希望自定义sys:get_status/1,2返回值以及其状态如何在终止错误日志中出现的回调模块导出format_status/2的实例,该实例返回描述gen_fsm当前状态的术语。
        PDict是gen_fsm的进程字典的当前值。
        StateData是gen_fsm的内部状态数据。
        该函数应返回Status,这是一个定制gen_fsm当前状态和状态详细信息的术语。状态可以采取的形式没有限制,但对于sys:get_status/1,2情况(当Opt是normal时),Status值的推荐形式为[{data,[{“StateData”,Term}]其中Term提供gen_fsm状态数据的相关详细信息。不需要遵循此建议,但这样做会使回调模块状态与sys:get_status/1,2返回值的其余部分保持一致。
        此函数的一个用途是返回紧凑的替代状态数据表示,以避免在日志文件中打印大的状态术语。
  • 相关阅读:
    AIX 开机启动网络服务配置
    aix 6+ mount 光驱
    AIX 系统中 PVID 的含义与作用
    lsslot
    hp小机定位网卡位置
    HP 7440老机器重启
    ntp -q 输出说明
    使用过滤器实现网站访问计数器的功能
    过滤器:-------------创建并配置过滤器:
    什么是Servlet,Servlet的作用,生命周期,如何创建、配置Servlet
  • 原文地址:https://www.cnblogs.com/sunbin-hello/p/9882046.html
Copyright © 2020-2023  润新知