diff options
Diffstat (limited to 'lib/stdlib/doc/src/gen_fsm.xml')
-rw-r--r-- | lib/stdlib/doc/src/gen_fsm.xml | 1262 |
1 files changed, 677 insertions, 585 deletions
diff --git a/lib/stdlib/doc/src/gen_fsm.xml b/lib/stdlib/doc/src/gen_fsm.xml index 835e252704..de06987d38 100644 --- a/lib/stdlib/doc/src/gen_fsm.xml +++ b/lib/stdlib/doc/src/gen_fsm.xml @@ -29,29 +29,30 @@ <rev></rev> </header> <module>gen_fsm</module> - <modulesummary>Generic Finite State Machine Behaviour</modulesummary> + <modulesummary>Generic finite state machine behavior.</modulesummary> <description> <note> <p> There is a new behaviour <seealso marker="gen_statem"><c>gen_statem</c></seealso> that is intended to replace <c>gen_fsm</c> for new code. - It has the same features and add some really useful. - This module will not be removed for the foreseeable future + <c>gen_fsm</c> will not be removed for the foreseeable future to keep old state machine implementations running. </p> </note> - <p>A behaviour module for implementing a finite state machine. - A generic finite state machine process (gen_fsm) implemented - using this module will have a standard set of interface functions - and include functionality for tracing and error reporting. It will - also fit into an OTP supervision tree. Refer to - <seealso marker="doc/design_principles:fsm">OTP Design Principles</seealso> for more information. + <p>This behavior module provides a finite state machine. + A generic finite state machine process (<c>gen_fsm</c>) implemented + using this module has a standard set of interface functions + and includes functionality for tracing and error reporting. It + also fits into an OTP supervision tree. For more information, see + <seealso marker="doc/design_principles:fsm">OTP Design Principles</seealso>. </p> - <p>A gen_fsm assumes all specific parts to be located in a callback - module exporting a pre-defined set of functions. The relationship - between the behaviour functions and the callback functions can be - illustrated as follows:</p> + + <p>A <c>gen_fsm</c> process assumes all specific parts to be located in a + callback module exporting a predefined set of functions. The relationship + between the behavior functions and the callback functions is as + follows:</p> + <pre> gen_fsm module Callback module -------------- --------------- @@ -73,34 +74,261 @@ gen_fsm:sync_send_all_state_event -----> Module:handle_sync_event/4 - -----> Module:terminate/3 - -----> Module:code_change/4</pre> - <p>If a callback function fails or returns a bad value, the gen_fsm - will terminate.</p> - <p>A gen_fsm handles system messages as documented in - <seealso marker="sys">sys(3)</seealso>. The <c>sys</c> module - can be used for debugging a gen_fsm.</p> - <p>Note that a gen_fsm does not trap exit signals automatically, - this must be explicitly initiated in the callback module.</p> + + <p>If a callback function fails or returns a bad value, the <c>gen_fsm</c> + process terminates.</p> + + <p>A <c>gen_fsm</c> process handles system messages as described in + <seealso marker="sys"><c>sys(3)</c></seealso>. The <c>sys</c> module + can be used for debugging a <c>gen_fsm</c> process.</p> + + <p>Notice that a <c>gen_fsm</c> process does not trap exit signals + automatically, this must be explicitly initiated in the callback + module.</p> + <p>Unless otherwise stated, all functions in this module fail if - the specified gen_fsm does not exist or if bad arguments are - given.</p> - <p>The gen_fsm process can go into hibernation - (see <seealso marker="erts:erlang#erlang:hibernate/3">erlang(3)</seealso>) if a callback - function specifies <c>'hibernate'</c> instead of a timeout value. This - might be useful if the server is expected to be idle for a long - time. However this feature should be used with care as hibernation - implies at least two garbage collections (when hibernating and - shortly after waking up) and is not something you'd want to do - between each call to a busy state machine.</p> + the specified <c>gen_fsm</c> process does not exist or if bad arguments + are specified.</p> + <p>The <c>gen_fsm</c> process can go into hibernation + (see <seealso marker="erts:erlang#hibernate/3"> + <c>erlang:hibernate/3</c></seealso>) if a callback function + specifies <c>'hibernate'</c> instead of a time-out value. This + can be useful if the server is expected to be idle for a long + time. However, use this feature with care, as hibernation + implies at least two garbage collections (when hibernating and + shortly after waking up) and is not something you want to do + between each call to a busy state machine.</p> </description> + <funcs> <func> + <name>cancel_timer(Ref) -> RemainingTime | false</name> + <fsummary>Cancel an internal timer in a generic FSM.</fsummary> + <type> + <v>Ref = reference()</v> + <v>RemainingTime = integer()</v> + </type> + <desc> + <p>Cancels an internal timer referred by <c>Ref</c> in the + <c>gen_fsm</c> process that calls this function.</p> + <p><c>Ref</c> is a reference returned from + <seealso marker="#send_event_after/2"> + <c>send_event_after/2</c></seealso> or + <seealso marker="#start_timer/2"><c>start_timer/2</c></seealso>.</p> + <p>If the timer has already timed out, but the event not yet + been delivered, it is cancelled as if it had <em>not</em> + timed out, so there is no false timer event after + returning from this function.</p> + <p>Returns the remaining time in milliseconds until the timer would + have expired if <c>Ref</c> referred to an active timer, otherwise + <c>false</c>.</p> + </desc> + </func> + + <func> + <name>enter_loop(Module, Options, StateName, StateData)</name> + <name>enter_loop(Module, Options, StateName, StateData, FsmName)</name> + <name>enter_loop(Module, Options, StateName, StateData, Timeout)</name> + <name>enter_loop(Module, Options, StateName, StateData, FsmName, Timeout)</name> + <fsummary>Enter the <c>gen_fsm</c> receive loop.</fsummary> + <type> + <v>Module = atom()</v> + <v>Options = [Option]</v> + <v> Option = {debug,Dbgs}</v> + <v> Dbgs = [Dbg]</v> + <v> Dbg = trace | log | statistics</v> + <v> | {log_to_file,FileName} | {install,{Func,FuncState}}</v> + <v>StateName = atom()</v> + <v>StateData = term()</v> + <v>FsmName = {local,Name} | {global,GlobalName}</v> + <v> | {via,Module,ViaName}</v> + <v> Name = atom()</v> + <v> GlobalName = ViaName = term()</v> + <v>Timeout = int() | infinity</v> + </type> + <desc> + <p>Makes an existing process into a <c>gen_fsm</c> process. + Does not return, + instead the calling process enters the <c>gen_fsm</c> receive + loop and becomes a <c>gen_fsm</c> process. The process <em>must</em> + have been started using one of the start functions in + <seealso marker="proc_lib"><c>proc_lib(3)</c></seealso>. The user is + responsible for any initialization of the process, including + registering a name for it.</p> + <p>This function is useful when a more complex initialization + procedure is needed than the <c>gen_fsm</c> behavior provides.</p> + <p><c>Module</c>, <c>Options</c>, and <c>FsmName</c> have + the same meanings as when calling + <seealso marker="#start_link/3"><c>start[_link]/3,4</c></seealso>. + However, if <c>FsmName</c> is specified, the process must have + been registered accordingly <em>before</em> this function is + called.</p> + <p><c>StateName</c>, <c>StateData</c>, and <c>Timeout</c> have + the same meanings as in the return value of + <seealso marker="#Moduleinit"><c>Module:init/1</c></seealso>. + The callback module <c>Module</c> does not need to + export an <c>init/1</c> function.</p> + <p>The function fails if the calling process was not started by a + <c>proc_lib</c> start function, or if it is not registered + according to <c>FsmName</c>.</p> + </desc> + </func> + + <func> + <name>reply(Caller, Reply) -> Result</name> + <fsummary>Send a reply to a caller.</fsummary> + <type> + <v>Caller - see below</v> + <v>Reply = term()</v> + <v>Result = term()</v> + </type> + <desc> + <p>This function can be used by a <c>gen_fsm</c> process to + explicitly send a reply to a client process that called + <seealso marker="#sync_send_event/2"> + <c>sync_send_event/2,3</c></seealso> or + <seealso marker="#sync_send_all_state_event/2"> + <c>sync_send_all_state_event/2,3</c></seealso> + when the reply cannot be defined in the return value of + <seealso marker="#Module:StateName/3"> + <c>Module:StateName/3</c></seealso> or + <seealso marker="#Module:handle_sync_event/4"> + <c>Module:handle_sync_event/4</c></seealso>.</p> + <p><c>Caller</c> must be the <c>From</c> argument provided to + the callback function. <c>Reply</c> is any term + given back to the client as the return value of + <c>sync_send_event/2,3</c> or + <c>sync_send_all_state_event/2,3</c>.</p> + <p>Return value <c>Result</c> is not further defined, and + is always to be ignored.</p> + </desc> + </func> + + <func> + <name>send_all_state_event(FsmRef, Event) -> ok</name> + <fsummary>Send an event asynchronously to a generic FSM.</fsummary> + <type> + <v>FsmRef = Name | {Name,Node} | {global,GlobalName}</v> + <v> | {via,Module,ViaName} | pid()</v> + <v> Name = Node = atom()</v> + <v> GlobalName = ViaName = term()</v> + <v>Event = term()</v> + </type> + <desc> + <p>Sends an event asynchronously to the <c>FsmRef</c> of the + <c>gen_fsm</c> process and returns <c>ok</c> immediately. + The <c>gen_fsm</c> process calls + <seealso marker="#Module:handle_event/3"> + <c>Module:handle_event/3</c></seealso> to handle the event.</p> + <p>For a description of the arguments, see + <seealso marker="#send_event/2"><c>send_event/2</c></seealso>.</p> + <p>The difference between <c>send_event/2</c> and + <c>send_all_state_event/2</c> is which callback function is + used to handle the event. This function is useful when + sending events that are handled the same way in every state, + as only one <c>handle_event</c> clause is needed to handle + the event instead of one clause in each state name function.</p> + </desc> + </func> + + <func> + <name>send_event(FsmRef, Event) -> ok</name> + <fsummary>Send an event asynchronously to a generic FSM.</fsummary> + <type> + <v>FsmRef = Name | {Name,Node} | {global,GlobalName}</v> + <v> | {via,Module,ViaName} | pid()</v> + <v> Name = Node = atom()</v> + <v> GlobalName = ViaName = term()</v> + <v>Event = term()</v> + </type> + <desc> + <p>Sends an event asynchronously to the <c>FsmRef</c> of the + <c>gen_fsm</c> process + and returns <c>ok</c> immediately. The <c>gen_fsm</c> process calls + <seealso marker="#Module:StateName/2"> + <c>Module:StateName/2</c></seealso> to handle the event, where + <c>StateName</c> is the name of the current state of + the <c>gen_fsm</c> process.</p> + <p><c>FsmRef</c> can be any of the following:</p> + <list type="bulleted"> + <item>The pid</item> + <item><c>Name</c>, if the <c>gen_fsm</c> process is locally + registered</item> + <item><c>{Name,Node}</c>, if the <c>gen_fsm</c> process is locally + registered at another node</item> + <item><c>{global,GlobalName}</c>, if the <c>gen_fsm</c> process is + globally registered</item> + <item><c>{via,Module,ViaName}</c>, if the <c>gen_fsm</c> process is + registered through an alternative process registry</item> + </list> + <p><c>Event</c> is any term that is passed as one of + the arguments to <c>Module:StateName/2</c>.</p> + </desc> + </func> + + <func> + <name>send_event_after(Time, Event) -> Ref</name> + <fsummary>Send a delayed event internally in a generic FSM.</fsummary> + <type> + <v>Time = integer()</v> + <v>Event = term()</v> + <v>Ref = reference()</v> + </type> + <desc> + <p>Sends a delayed event internally in the <c>gen_fsm</c> process + that calls this function after <c>Time</c> milliseconds. + Returns immediately a + reference that can be used to cancel the delayed send using + <seealso marker="#cancel_timer/1"><c>cancel_timer/1</c></seealso>.</p> + <p>The <c>gen_fsm</c> process calls + <seealso marker="#Module:StateName/2"> + <c>Module:StateName/2</c></seealso> to handle + the event, where <c>StateName</c> is the name of the current + state of the <c>gen_fsm</c> process at the time the delayed event is + delivered.</p> + <p><c>Event</c> is any term that is passed as one of + the arguments to <c>Module:StateName/2</c>.</p> + </desc> + </func> + + <func> + <name>start(Module, Args, Options) -> Result</name> + <name>start(FsmName, Module, Args, Options) -> Result</name> + <fsummary>Create a standalone <c>gen_fsm</c> process.</fsummary> + <type> + <v>FsmName = {local,Name} | {global,GlobalName}</v> + <v> | {via,Module,ViaName}</v> + <v> Name = atom()</v> + <v> GlobalName = ViaName = term()</v> + <v>Module = atom()</v> + <v>Args = term()</v> + <v>Options = [Option]</v> + <v> Option = {debug,Dbgs} | {timeout,Time} | {spawn_opt,SOpts}</v> + <v> Dbgs = [Dbg]</v> + <v> Dbg = trace | log | statistics</v> + <v> | {log_to_file,FileName} | {install,{Func,FuncState}}</v> + <v> SOpts = [term()]</v> + <v>Result = {ok,Pid} | ignore | {error,Error}</v> + <v> Pid = pid()</v> + <v> Error = {already_started,Pid} | term()</v> + </type> + <desc> + <p>Creates a standalone <c>gen_fsm</c> process, that is, a process that + is not part of a supervision tree and thus has no supervisor.</p> + <p>For a description of arguments and return values, see + <seealso marker="#start_link/3"><c>start_link/3,4</c></seealso>.</p> + </desc> + </func> + + <func> <name>start_link(Module, Args, Options) -> Result</name> <name>start_link(FsmName, Module, Args, Options) -> Result</name> - <fsummary>Create a gen_fsm process in a supervision tree.</fsummary> + <fsummary>Create a <c>gen_fsm</c> process in a supervision tree. + </fsummary> <type> - <v>FsmName = {local,Name} | {global,GlobalName} - | {via,Module,ViaName}</v> + <v>FsmName = {local,Name} | {global,GlobalName}</v> + <v> | {via,Module,ViaName}</v> <v> Name = atom()</v> <v> GlobalName = ViaName = term()</v> <v>Module = atom()</v> @@ -117,54 +345,64 @@ gen_fsm:sync_send_all_state_event -----> Module:handle_sync_event/4 <v> Error = {already_started,Pid} | term()</v> </type> <desc> - <p>Creates a gen_fsm process as part of a supervision tree. - The function should be called, directly or indirectly, by - the supervisor. It will, among other things, ensure that - the gen_fsm is linked to the supervisor.</p> - <p>The gen_fsm process calls <c>Module:init/1</c> to - initialize. To ensure a synchronized start-up procedure, + <p>Creates a <c>gen_fsm</c> process as part of a supervision tree. + The function is to be called, directly or indirectly, by + the supervisor. For example, it ensures that + the <c>gen_fsm</c> process is linked to the supervisor.</p> + <p>The <c>gen_fsm</c> process calls + <seealso marker="#Module:init/1"><c>Module:init/1</c></seealso> to + initialize. To ensure a synchronized startup procedure, <c>start_link/3,4</c> does not return until <c>Module:init/1</c> has returned.</p> - <p>If <c>FsmName={local,Name}</c>, the gen_fsm is registered - locally as <c>Name</c> using <c>register/2</c>. - If <c>FsmName={global,GlobalName}</c>, the gen_fsm is - registered globally as <c>GlobalName</c> using - <c>global:register_name/2</c>. - If <c>FsmName={via,Module,ViaName}</c>, the gen_fsm will - register with the registry represented by <c>Module</c>. - The <c>Module</c> callback should export the functions - <c>register_name/2</c>, <c>unregister_name/1</c>, - <c>whereis_name/1</c> and <c>send/2</c>, which should behave like the - corresponding functions in <c>global</c>. Thus, - <c>{via,global,GlobalName}</c> is a valid reference.</p> - <p>If no name is provided, - the gen_fsm is not registered.</p> + <list type="bulleted"> + <item> + <p>If <c>FsmName={local,Name}</c>, the <c>gen_fsm</c> process is + registered locally as <c>Name</c> using <c>register/2</c>.</p> + </item> + <item> + <p>If <c>FsmName={global,GlobalName}</c>, the <c>gen_fsm</c> process + is registered globally as <c>GlobalName</c> using + <seealso marker="kernel:global#register_name/2"> + <c>global:register_name/2</c></seealso>.</p> + </item> + <item> + <p>If <c>FsmName={via,Module,ViaName}</c>, the <c>gen_fsm</c> + process registers with the registry represented by <c>Module</c>. + The <c>Module</c> callback is to export the functions + <c>register_name/2</c>, <c>unregister_name/1</c>, + <c>whereis_name/1</c>, and <c>send/2</c>, which are to behave + like the corresponding functions in + <seealso marker="kernel:global"><c>global</c></seealso>. + Thus, <c>{via,global,GlobalName}</c> is a valid reference.</p> + </item> + </list> + <p>If no name is provided, the <c>gen_fsm</c> process is not + registered.</p> <p><c>Module</c> is the name of the callback module.</p> - <p><c>Args</c> is an arbitrary term which is passed as + <p><c>Args</c> is any term that is passed as the argument to <c>Module:init/1</c>.</p> - <p>If the option <c>{timeout,Time}</c> is present, the gen_fsm - is allowed to spend <c>Time</c> milliseconds initializing - or it will be terminated and the start function will return + <p>If option <c>{timeout,Time}</c> is present, the <c>gen_fsm</c> + process is allowed to spend <c>Time</c> milliseconds initializing + or it terminates and the start function returns <c>{error,timeout}</c>.</p> - <p>If the option <c>{debug,Dbgs}</c> is present, - the corresponding <c>sys</c> function will be called for each - item in <c>Dbgs</c>. See - <seealso marker="sys">sys(3)</seealso>.</p> - <p>If the option <c>{spawn_opt,SOpts}</c> is present, - <c>SOpts</c> will be passed as option list to - the <c>spawn_opt</c> BIF which is used to spawn the gen_fsm - process. See - <seealso marker="erts:erlang#spawn_opt/2">erlang(3)</seealso>.</p> + <p>If option <c>{debug,Dbgs}</c> is present, the corresponding + <c>sys</c> function is called for each item in <c>Dbgs</c>; see + <seealso marker="sys"><c>sys(3)</c></seealso>.</p> + <p>If option <c>{spawn_opt,SOpts}</c> is present, <c>SOpts</c> is + passed as option list to the <c>spawn_opt</c> BIF that is used to + spawn the <c>gen_fsm</c> process; see + <seealso marker="erts:erlang#spawn_opt/2"> + <c>spawn_opt/2</c></seealso>.</p> <note> - <p>Using the spawn option <c>monitor</c> is currently not - allowed, but will cause the function to fail with reason + <p>Using spawn option <c>monitor</c> is not + allowed, it causes the function to fail with reason <c>badarg</c>.</p> </note> - <p>If the gen_fsm is successfully created and initialized - the function returns <c>{ok,Pid}</c>, where <c>Pid</c> is - the pid of the gen_fsm. If there already exists a process with - the specified <c>FsmName</c>, the function returns - <c>{error,{already_started,Pid}}</c> where <c>Pid</c> is + <p>If the <c>gen_fsm</c> process is successfully created and + initialized, the function returns <c>{ok,Pid}</c>, where <c>Pid</c> + is the pid of the <c>gen_fsm</c> process. If a process with the + specified <c>FsmName</c> exists already, the function returns + <c>{error,{already_started,Pid}}</c>, where <c>Pid</c> is the pid of that process.</p> <p>If <c>Module:init/1</c> fails with <c>Reason</c>, the function returns <c>{error,Reason}</c>. If @@ -173,129 +411,106 @@ gen_fsm:sync_send_all_state_event -----> Module:handle_sync_event/4 returns <c>{error,Reason}</c> or <c>ignore</c>, respectively.</p> </desc> </func> + <func> - <name>start(Module, Args, Options) -> Result</name> - <name>start(FsmName, Module, Args, Options) -> Result</name> - <fsummary>Create a stand-alone gen_fsm process.</fsummary> + <name>start_timer(Time, Msg) -> Ref</name> + <fsummary>Send a time-out event internally in a generic FSM.</fsummary> <type> - <v>FsmName = {local,Name} | {global,GlobalName} - | {via,Module,ViaName}</v> - <v> Name = atom()</v> - <v> GlobalName = ViaName = term()</v> - <v>Module = atom()</v> - <v>Args = term()</v> - <v>Options = [Option]</v> - <v> Option = {debug,Dbgs} | {timeout,Time} | {spawn_opt,SOpts}</v> - <v> Dbgs = [Dbg]</v> - <v> Dbg = trace | log | statistics</v> - <v> | {log_to_file,FileName} | {install,{Func,FuncState}}</v> - <v> SOpts = [term()]</v> - <v>Result = {ok,Pid} | ignore | {error,Error}</v> - <v> Pid = pid()</v> - <v> Error = {already_started,Pid} | term()</v> + <v>Time = integer()</v> + <v>Msg = term()</v> + <v>Ref = reference()</v> </type> <desc> - <p>Creates a stand-alone gen_fsm process, i.e. a gen_fsm which - is not part of a supervision tree and thus has no supervisor.</p> - <p>See <seealso marker="#start_link/3">start_link/3,4</seealso> - for a description of arguments and return values.</p> + <p>Sends a time-out event internally in the <c>gen_fsm</c> + process that calls this function after <c>Time</c> milliseconds. + Returns immediately a + reference that can be used to cancel the timer using + <seealso marker="#cancel_timer/1"><c>cancel_timer/1</c></seealso>.</p> + <p>The <c>gen_fsm</c> process calls + <seealso marker="#Module:StateName/2"> + <c>Module:StateName/2</c></seealso> to handle + the event, where <c>StateName</c> is the name of the current + state of the <c>gen_fsm</c> process at the time the time-out + message is delivered.</p> + <p><c>Msg</c> is any term that is passed in the + time-out message, <c>{timeout, Ref, Msg}</c>, as one of + the arguments to <c>Module:StateName/2</c>.</p> </desc> </func> + <func> <name>stop(FsmRef) -> ok</name> <name>stop(FsmRef, Reason, Timeout) -> ok</name> <fsummary>Synchronously stop a generic FSM.</fsummary> <type> - <v>FsmRef = Name | {Name,Node} | {global,GlobalName} - | {via,Module,ViaName} | pid()</v> + <v>FsmRef = Name | {Name,Node} | {global,GlobalName}</v> + <v> | {via,Module,ViaName} | pid()</v> <v> Node = atom()</v> <v> GlobalName = ViaName = term()</v> <v>Reason = term()</v> <v>Timeout = int()>0 | infinity</v> </type> <desc> - <p>Orders a generic FSM to exit with the given <c>Reason</c> - and waits for it to terminate. The gen_fsm will call - <seealso marker="#Module:terminate/3">Module:terminate/3</seealso> - before exiting.</p> - <p>The function returns <c>ok</c> if the generic FSM terminates - with the expected reason. Any other reason than <c>normal</c>, - <c>shutdown</c>, or <c>{shutdown,Term}</c> will cause an + <p>Orders a generic finite state machine to exit with the specified + <c>Reason</c> and waits for it to terminate. The <c>gen_fsm</c> + process calls <seealso marker="#Module:terminate/3"> + <c>Module:terminate/3</c></seealso> before exiting.</p> + <p>The function returns <c>ok</c> if the generic finite state machine + terminates with the expected reason. Any other reason than + <c>normal</c>, <c>shutdown</c>, or <c>{shutdown,Term}</c> causes an error report to be issued using - <seealso marker="kernel:error_logger#format/2">error_logger:format/2</seealso>. - The default <c>Reason</c> is <c>normal</c>.</p> - <p><c>Timeout</c> is an integer greater than zero which + <seealso marker="kernel:error_logger#format/2"> + <c>error_logger:format/2</c></seealso>. + The default <c>Reason</c> is <c>normal</c>.</p> + <p><c>Timeout</c> is an integer greater than zero that specifies how many milliseconds to wait for the generic FSM to terminate, or the atom <c>infinity</c> to wait indefinitely. The default value is <c>infinity</c>. If the - generic FSM has not terminated within the specified time, a - <c>timeout</c> exception is raised.</p> - <p>If the process does not exist, a <c>noproc</c> exception - is raised.</p> - </desc> - </func> - <func> - <name>send_event(FsmRef, Event) -> ok</name> - <fsummary>Send an event asynchronously to a generic FSM.</fsummary> - <type> - <v>FsmRef = Name | {Name,Node} | {global,GlobalName} - | {via,Module,ViaName} | pid()</v> - <v> Name = Node = atom()</v> - <v> GlobalName = ViaName = term()</v> - <v>Event = term()</v> - </type> - <desc> - <p>Sends an event asynchronously to the gen_fsm <c>FsmRef</c> - and returns <c>ok</c> immediately. The gen_fsm will call - <c>Module:StateName/2</c> to handle the event, where - <c>StateName</c> is the name of the current state of - the gen_fsm.</p> - <p><c>FsmRef</c> can be:</p> - <list type="bulleted"> - <item>the pid,</item> - <item><c>Name</c>, if the gen_fsm is locally registered,</item> - <item><c>{Name,Node}</c>, if the gen_fsm is locally - registered at another node, or</item> - <item><c>{global,GlobalName}</c>, if the gen_fsm is globally - registered.</item> - <item><c>{via,Module,ViaName}</c>, if the gen_fsm is registered - through an alternative process registry.</item> - </list> - <p><c>Event</c> is an arbitrary term which is passed as one of - the arguments to <c>Module:StateName/2</c>.</p> + generic finite state machine has not terminated within the specified + time, a <c>timeout</c> exception is raised.</p> + <p>If the process does not exist, a <c>noproc</c> exception + is raised.</p> </desc> </func> + <func> - <name>send_all_state_event(FsmRef, Event) -> ok</name> - <fsummary>Send an event asynchronously to a generic FSM.</fsummary> + <name>sync_send_all_state_event(FsmRef, Event) -> Reply</name> + <name>sync_send_all_state_event(FsmRef, Event, Timeout) -> Reply</name> + <fsummary>Send an event synchronously to a generic FSM.</fsummary> <type> - <v>FsmRef = Name | {Name,Node} | {global,GlobalName} - | {via,Module,ViaName} | pid()</v> + <v>FsmRef = Name | {Name,Node} | {global,GlobalName}</v> + <v> | {via,Module,ViaName} | pid()</v> <v> Name = Node = atom()</v> <v> GlobalName = ViaName = term()</v> <v>Event = term()</v> + <v>Timeout = int()>0 | infinity</v> + <v>Reply = term()</v> </type> <desc> - <p>Sends an event asynchronously to the gen_fsm <c>FsmRef</c> - and returns <c>ok</c> immediately. The gen_fsm will call - <c>Module:handle_event/3</c> to handle the event.</p> - <p>See <seealso marker="#send_event/2">send_event/2</seealso> - for a description of the arguments.</p> - <p>The difference between <c>send_event</c> and - <c>send_all_state_event</c> is which callback function is - used to handle the event. This function is useful when - sending events that are handled the same way in every state, - as only one <c>handle_event</c> clause is needed to handle - the event instead of one clause in each state name function.</p> + <p>Sends an event to the <c>FsmRef</c> of the <c>gen_fsm</c> + process and waits until a reply arrives or a time-out occurs. + The <c>gen_fsm</c> process calls + <seealso marker="#Module:handle_sync_event/4"> + <c>Module:handle_sync_event/4</c></seealso> to handle the event.</p> + <p>For a description of <c>FsmRef</c> and <c>Event</c>, see + <seealso marker="#send_event/2">send_event/2</seealso>. + For a description of <c>Timeout</c> and <c>Reply</c>, see + <seealso marker="#sync_send_event/3"> + <c>sync_send_event/3</c></seealso>.</p> + <p>For a discussion about the difference between + <c>sync_send_event</c> and <c>sync_send_all_state_event</c>, see + <seealso marker="#send_all_state_event/2"> + <c>send_all_state_event/2</c></seealso>.</p> </desc> </func> + <func> <name>sync_send_event(FsmRef, Event) -> Reply</name> <name>sync_send_event(FsmRef, Event, Timeout) -> Reply</name> <fsummary>Send an event synchronously to a generic FSM.</fsummary> <type> - <v>FsmRef = Name | {Name,Node} | {global,GlobalName} - | {via,Module,ViaName} | pid()</v> + <v>FsmRef = Name | {Name,Node} | {global,GlobalName}</v> + <v> | {via,Module,ViaName} | pid()</v> <v> Name = Node = atom()</v> <v> GlobalName = ViaName = term()</v> <v>Event = term()</v> @@ -303,210 +518,231 @@ gen_fsm:sync_send_all_state_event -----> Module:handle_sync_event/4 <v>Reply = term()</v> </type> <desc> - <p>Sends an event to the gen_fsm <c>FsmRef</c> and waits until a - reply arrives or a timeout occurs. The gen_fsm will call - <c>Module:StateName/3</c> to handle the event, where + <p>Sends an event to the <c>FsmRef</c> of the <c>gen_fsm</c> + process and waits until a reply arrives or a time-out occurs. + <c>The gen_fsm</c> process calls + <seealso marker="#Module:StateName/3"> + <c>Module:StateName/3</c></seealso> to handle the event, where <c>StateName</c> is the name of the current state of - the gen_fsm.</p> - <p>See <seealso marker="#send_event/2">send_event/2</seealso> - for a description of <c>FsmRef</c> and <c>Event</c>.</p> - <p><c>Timeout</c> is an integer greater than zero which + the <c>gen_fsm</c> process.</p> + <p>For a description of <c>FsmRef</c> and <c>Event</c>, see + <seealso marker="#send_event/2"><c>send_event/2</c></seealso>.</p> + <p><c>Timeout</c> is an integer greater than zero that specifies how many milliseconds to wait for a reply, or - the atom <c>infinity</c> to wait indefinitely. Default value - is 5000. If no reply is received within the specified time, + the atom <c>infinity</c> to wait indefinitely. Defaults + to 5000. If no reply is received within the specified time, the function call fails.</p> - <p>The return value <c>Reply</c> is defined in the return value + <p>Return value <c>Reply</c> is defined in the return value of <c>Module:StateName/3</c>.</p> - <p>The ancient behaviour of sometimes consuming the server + <note> + <p>The ancient behavior of sometimes consuming the server exit message if the server died during the call while - linked to the client has been removed in OTP R12B/Erlang 5.6.</p> + linked to the client was removed in Erlang 5.6/OTP R12B.</p> + </note> </desc> </func> + </funcs> + + <section> + <title>Callback Functions</title> + <p>The following functions are to be exported from a <c>gen_fsm</c> + callback module.</p> + + <p><em>state name</em> denotes a state of the state machine.</p> + + <p><em>state data</em> denotes the internal state of the Erlang process + that implements the state machine.</p> + </section> + + <funcs> <func> - <name>sync_send_all_state_event(FsmRef, Event) -> Reply</name> - <name>sync_send_all_state_event(FsmRef, Event, Timeout) -> Reply</name> - <fsummary>Send an event synchronously to a generic FSM.</fsummary> + <name>Module:code_change(OldVsn, StateName, StateData, Extra) -> {ok, NextStateName, NewStateData}</name> + <fsummary>Update the internal state data during upgrade/downgrade. + </fsummary> <type> - <v>FsmRef = Name | {Name,Node} | {global,GlobalName} - | {via,Module,ViaName} | pid()</v> - <v> Name = Node = atom()</v> - <v> GlobalName = ViaName = term()</v> - <v>Event = term()</v> - <v>Timeout = int()>0 | infinity</v> - <v>Reply = term()</v> + <v>OldVsn = Vsn | {down, Vsn}</v> + <v> Vsn = term()</v> + <v>StateName = NextStateName = atom()</v> + <v>StateData = NewStateData = term()</v> + <v>Extra = term()</v> </type> <desc> - <p>Sends an event to the gen_fsm <c>FsmRef</c> and waits until a - reply arrives or a timeout occurs. The gen_fsm will call - <c>Module:handle_sync_event/4</c> to handle the event.</p> - <p>See <seealso marker="#send_event/2">send_event/2</seealso> - for a description of <c>FsmRef</c> and <c>Event</c>. See - <seealso marker="#sync_send_event/3">sync_send_event/3</seealso> - for a description of <c>Timeout</c> and <c>Reply</c>.</p> - <p>See - <seealso marker="#send_all_state_event/2">send_all_state_event/2</seealso> - for a discussion about the difference between - <c>sync_send_event</c> and <c>sync_send_all_state_event</c>.</p> + <p>This function is called by a <c>gen_fsm</c> process when it is to + update its internal state data during a release upgrade/downgrade, + that is, when instruction <c>{update,Module,Change,...}</c>, + where <c>Change={advanced,Extra}</c>, is given in + the <c>appup</c> file; see section + <seealso marker="doc/design_principles:release_handling#instr"> + Release Handling Instructions</seealso> in OTP Design Principles.</p> + <p>For an upgrade, <c>OldVsn</c> is <c>Vsn</c>, and for a downgrade, + <c>OldVsn</c> is <c>{down,Vsn}</c>. <c>Vsn</c> is defined by the + <c>vsn</c> attribute(s) of the old version of the callback module + <c>Module</c>. If no such attribute is defined, the version is + the checksum of the Beam file.</p> + <p><c>StateName</c> is the current state name and <c>StateData</c> the + internal state data of the <c>gen_fsm</c> process.</p> + <p><c>Extra</c> is passed "as is" from the <c>{advanced,Extra}</c> + part of the update instruction.</p> + <p>The function is to return the new current state name and + updated internal data.</p> </desc> </func> + <func> - <name>reply(Caller, Reply) -> Result</name> - <fsummary>Send a reply to a caller.</fsummary> + <name>Module:format_status(Opt, [PDict, StateData]) -> Status</name> + <fsummary>Optional function for providing a term describing the + current <c>gen_fsm</c> process status.</fsummary> <type> - <v>Caller - see below</v> - <v>Reply = term()</v> - <v>Result = term()</v> + <v>Opt = normal | terminate</v> + <v>PDict = [{Key, Value}]</v> + <v>StateData = term()</v> + <v>Status = term()</v> </type> <desc> - <p>This function can be used by a gen_fsm to explicitly send a - reply to a client process that called - <seealso marker="#sync_send_event/2">sync_send_event/2,3</seealso> - or - <seealso marker="#sync_send_all_state_event/2">sync_send_all_state_event/2,3</seealso>, - when the reply cannot be defined in the return value of - <c>Module:State/3</c> or <c>Module:handle_sync_event/4</c>.</p> - <p><c>Caller</c> must be the <c>From</c> argument provided to - the callback function. <c>Reply</c> is an arbitrary term, - which will be given back to the client as the return value of - <c>sync_send_event/2,3</c> or - <c>sync_send_all_state_event/2,3</c>.</p> - <p>The return value <c>Result</c> is not further defined, and - should always be ignored.</p> + <note> + <p>This callback is optional, so callback modules need not + export it. The <c>gen_fsm</c> module provides a default + implementation of this function that returns the callback + module state data.</p> + </note> + <p>This function is called by a <c>gen_fsm</c> process in the + following situations:</p> + <list type="bulleted"> + <item>One of <seealso marker="sys#get_status/1"> + <c>sys:get_status/1,2</c></seealso> + is invoked to get the <c>gen_fsm</c> status. <c>Opt</c> is set to + the atom <c>normal</c> for this case.</item> + <item>The <c>gen_fsm</c> process terminates abnormally and logs an + error. <c>Opt</c> is set to the atom <c>terminate</c> for + this case.</item> + </list> + <p>This function is useful for changing the form and + appearance of the <c>gen_fsm</c> status for these cases. A callback + module wishing to change the <c>sys:get_status/1,2</c> + return value as well as how its status appears in + termination error logs, exports an instance + of <c>format_status/2</c> that returns a term describing the + current status of the <c>gen_fsm</c> process.</p> + <p><c>PDict</c> is the current value of the process dictionary of the + <c>gen_fsm</c> process.</p> + <p><c>StateData</c> is the internal state data of the + <c>gen_fsm</c> process.</p> + <p>The function is to return <c>Status</c>, a term that + change the details of the current state and status of + the <c>gen_fsm</c> process. There are no restrictions on the + form <c>Status</c> can take, but for + the <c>sys:get_status/1,2</c> case (when <c>Opt</c> + is <c>normal</c>), the recommended form for + the <c>Status</c> value is <c>[{data, [{"StateData", + Term}]}]</c>, where <c>Term</c> provides relevant details of + the <c>gen_fsm</c> state data. Following this recommendation is not + required, but it makes the callback module status + consistent with the rest of the <c>sys:get_status/1,2</c> + return value.</p> + <p>One use for this function is to return compact alternative + state data representations to avoid that large state terms + are printed in log files.</p> </desc> </func> + <func> - <name>send_event_after(Time, Event) -> Ref</name> - <fsummary>Send a delayed event internally in a generic FSM.</fsummary> + <name>Module:handle_event(Event, StateName, StateData) -> Result</name> + <fsummary>Handle an asynchronous event.</fsummary> <type> - <v>Time = integer()</v> <v>Event = term()</v> - <v>Ref = reference()</v> - </type> - <desc> - <p>Sends a delayed event internally in the gen_fsm that calls - this function after <c>Time</c> ms. Returns immediately a - reference that can be used to cancel the delayed send using - <seealso marker="#cancel_timer/1">cancel_timer/1</seealso>.</p> - <p>The gen_fsm will call <c>Module:StateName/2</c> to handle - the event, where <c>StateName</c> is the name of the current - state of the gen_fsm at the time the delayed event is - delivered.</p> - <p><c>Event</c> is an arbitrary term which is passed as one of - the arguments to <c>Module:StateName/2</c>.</p> - </desc> - </func> - <func> - <name>start_timer(Time, Msg) -> Ref</name> - <fsummary>Send a timeout event internally in a generic FSM.</fsummary> - <type> - <v>Time = integer()</v> - <v>Msg = term()</v> - <v>Ref = reference()</v> + <v>StateName = atom()</v> + <v>StateData = term()</v> + <v>Result = {next_state,NextStateName,NewStateData}</v> + <v> | {next_state,NextStateName,NewStateData,Timeout}</v> + <v> | {next_state,NextStateName,NewStateData,hibernate}</v> + <v> | {stop,Reason,NewStateData}</v> + <v> NextStateName = atom()</v> + <v> NewStateData = term()</v> + <v> Timeout = int()>0 | infinity</v> + <v> Reason = term()</v> </type> <desc> - <p>Sends a timeout event internally in the gen_fsm that calls - this function after <c>Time</c> ms. Returns immediately a - reference that can be used to cancel the timer using - <seealso marker="#cancel_timer/1">cancel_timer/1</seealso>.</p> - <p>The gen_fsm will call <c>Module:StateName/2</c> to handle - the event, where <c>StateName</c> is the name of the current - state of the gen_fsm at the time the timeout message is - delivered.</p> - <p><c>Msg</c> is an arbitrary term which is passed in the - timeout message, <c>{timeout, Ref, Msg}</c>, as one of - the arguments to <c>Module:StateName/2</c>.</p> + <p>Whenever a <c>gen_fsm</c> process receives an event sent using + <seealso marker="#send_all_state_event/2"> + <c>send_all_state_event/2</c></seealso>, + this function is called to handle the event.</p> + <p><c>StateName</c> is the current state name of the <c>gen_fsm</c> + process.</p> + <p>For a description of the other arguments and possible return values, + see <seealso marker="#Module:StateName/2"> + <c>Module:StateName/2</c></seealso>.</p> </desc> </func> + <func> - <name>cancel_timer(Ref) -> RemainingTime | false</name> - <fsummary>Cancel an internal timer in a generic FSM.</fsummary> + <name>Module:handle_info(Info, StateName, StateData) -> Result</name> + <fsummary>Handle an incoming message.</fsummary> <type> - <v>Ref = reference()</v> - <v>RemainingTime = integer()</v> + <v>Info = term()</v> + <v>StateName = atom()</v> + <v>StateData = term()</v> + <v>Result = {next_state,NextStateName,NewStateData}</v> + <v> | {next_state,NextStateName,NewStateData,Timeout}</v> + <v> | {next_state,NextStateName,NewStateData,hibernate}</v> + <v> | {stop,Reason,NewStateData}</v> + <v> NextStateName = atom()</v> + <v> NewStateData = term()</v> + <v> Timeout = int()>0 | infinity</v> + <v> Reason = normal | term()</v> </type> <desc> - <p>Cancels an internal timer referred by <c>Ref</c> in the - gen_fsm that calls this function.</p> - <p><c>Ref</c> is a reference returned from - <seealso marker="#send_event_after/2">send_event_after/2</seealso> - or - <seealso marker="#start_timer/2">start_timer/2</seealso>.</p> - <p>If the timer has already timed out, but the event not yet - been delivered, it is cancelled as if it had <em>not</em> - timed out, so there will be no false timer event after - returning from this function.</p> - <p>Returns the remaining time in ms until the timer would - have expired if <c>Ref</c> referred to an active timer, - <c>false</c> otherwise.</p> + <p>This function is called by a <c>gen_fsm</c> process when it receives + any other message than a synchronous or asynchronous event (or a + system message).</p> + <p><c>Info</c> is the received message.</p> + <p>For a description of the other arguments and possible return values, + see <seealso marker="#Module:StateName/2"> + <c>Module:StateName/2</c></seealso>.</p> </desc> </func> + <func> - <name>enter_loop(Module, Options, StateName, StateData)</name> - <name>enter_loop(Module, Options, StateName, StateData, FsmName)</name> - <name>enter_loop(Module, Options, StateName, StateData, Timeout)</name> - <name>enter_loop(Module, Options, StateName, StateData, FsmName, Timeout)</name> - <fsummary>Enter the gen_fsm receive loop</fsummary> + <name>Module:handle_sync_event(Event, From, StateName, StateData) -> Result</name> + <fsummary>Handle a synchronous event.</fsummary> <type> - <v>Module = atom()</v> - <v>Options = [Option]</v> - <v> Option = {debug,Dbgs}</v> - <v> Dbgs = [Dbg]</v> - <v> Dbg = trace | log | statistics</v> - <v> | {log_to_file,FileName} | {install,{Func,FuncState}}</v> + <v>Event = term()</v> + <v>From = {pid(),Tag}</v> <v>StateName = atom()</v> <v>StateData = term()</v> - <v>FsmName = {local,Name} | {global,GlobalName} - | {via,Module,ViaName}</v> - <v> Name = atom()</v> - <v> GlobalName = ViaName = term()</v> - <v>Timeout = int() | infinity</v> + <v>Result = {reply,Reply,NextStateName,NewStateData}</v> + <v> | {reply,Reply,NextStateName,NewStateData,Timeout}</v> + <v> | {reply,Reply,NextStateName,NewStateData,hibernate}</v> + <v> | {next_state,NextStateName,NewStateData}</v> + <v> | {next_state,NextStateName,NewStateData,Timeout}</v> + <v> | {next_state,NextStateName,NewStateData,hibernate}</v> + <v> | {stop,Reason,Reply,NewStateData} | {stop,Reason,NewStateData}</v> + <v> Reply = term()</v> + <v> NextStateName = atom()</v> + <v> NewStateData = term()</v> + <v> Timeout = int()>0 | infinity</v> + <v> Reason = term()</v> </type> <desc> - <p>Makes an existing process into a gen_fsm. Does not return, - instead the calling process will enter the gen_fsm receive - loop and become a gen_fsm process. The process <em>must</em> - have been started using one of the start functions in - <c>proc_lib</c>, see - <seealso marker="proc_lib">proc_lib(3)</seealso>. The user is - responsible for any initialization of the process, including - registering a name for it.</p> - <p>This function is useful when a more complex initialization - procedure is needed than the gen_fsm behaviour provides.</p> - <p><c>Module</c>, <c>Options</c> and <c>FsmName</c> have - the same meanings as when calling - <seealso marker="#start_link/3">start[_link]/3,4</seealso>. - However, if <c>FsmName</c> is specified, the process must have - been registered accordingly <em>before</em> this function is - called.</p> - <p><c>StateName</c>, <c>StateData</c> and <c>Timeout</c> have - the same meanings as in the return value of - <seealso marker="#Moduleinit">Module:init/1</seealso>. - Also, the callback module <c>Module</c> does not need to - export an <c>init/1</c> function.</p> - <p>Failure: If the calling process was not started by a - <c>proc_lib</c> start function, or if it is not registered - according to <c>FsmName</c>.</p> + <p>Whenever a <c>gen_fsm</c> process receives an event sent using + <seealso marker="#sync_send_all_state_event/2"> + <c>sync_send_all_state_event/2,3</c></seealso>, + this function is called to handle the event.</p> + <p><c>StateName</c> is the current state name of the <c>gen_fsm</c> + process.</p> + <p>For a description of the other arguments and possible return values, + see <seealso marker="#Module:StateName/3"> + <c>Module:StateName/3</c></seealso>.</p> </desc> </func> - </funcs> - <section> - <title>CALLBACK FUNCTIONS</title> - <p>The following functions should be exported from a <c>gen_fsm</c> - callback module.</p> - <p>In the description, the expression <em>state name</em> is used to - denote a state of the state machine. <em>state data</em> is used - to denote the internal state of the Erlang process which - implements the state machine.</p> - </section> - <funcs> <func> <name>Module:init(Args) -> Result</name> - <fsummary>Initialize process and internal state name and state data.</fsummary> + <fsummary>Initialize process and internal state name and state data. + </fsummary> <type> <v>Args = term()</v> <v>Result = {ok,StateName,StateData} | {ok,StateName,StateData,Timeout}</v> - <v> | {ok,StateName,StateData,hibernate}</v> + <v> | {ok,StateName,StateData,hibernate}</v> <v> | {stop,Reason} | ignore</v> <v> StateName = atom()</v> <v> StateData = term()</v> @@ -515,33 +751,36 @@ gen_fsm:sync_send_all_state_event -----> Module:handle_sync_event/4 </type> <desc> <marker id="Moduleinit"></marker> - <p>Whenever a gen_fsm is started using - <seealso marker="#start/3">gen_fsm:start/3,4</seealso> or - <seealso marker="#start_link/3">gen_fsm:start_link/3,4</seealso>, + <p>Whenever a <c>gen_fsm</c> process is started using + <seealso marker="#start/3"><c>start/3,4</c></seealso> or + <seealso marker="#start_link/3"><c>start_link/3,4</c></seealso>, this function is called by the new process to initialize.</p> <p><c>Args</c> is the <c>Args</c> argument provided to the start function.</p> - <p>If initialization is successful, the function should return - <c>{ok,StateName,StateData}</c>, - <c>{ok,StateName,StateData,Timeout}</c> or <c>{ok,StateName,StateData,hibernate}</c>, - where <c>StateName</c> + <p>If initialization is successful, the function is to return + <c>{ok,StateName,StateData}</c>, + <c>{ok,StateName,StateData,Timeout}</c>, or + <c>{ok,StateName,StateData,hibernate}</c>, where <c>StateName</c> is the initial state name and <c>StateData</c> the initial - state data of the gen_fsm.</p> - <p>If an integer timeout value is provided, a timeout will occur + state data of the <c>gen_fsm</c> process.</p> + <p>If an integer time-out value is provided, a time-out occurs unless an event or a message is received within <c>Timeout</c> - milliseconds. A timeout is represented by the atom - <c>timeout</c> and should be handled by - the <c>Module:StateName/2</c> callback functions. The atom + milliseconds. A time-out is represented by the atom + <c>timeout</c> and is to be handled by the + <seealso marker="#Module:StateName/2"> + <c>Module:StateName/2</c></seealso> callback functions. The atom <c>infinity</c> can be used to wait indefinitely, this is the default value.</p> - <p>If <c>hibernate</c> is specified instead of a timeout value, the process will go - into hibernation when waiting for the next message to arrive (by calling - <seealso marker="proc_lib#hibernate/3">proc_lib:hibernate/3</seealso>).</p> - <p>If something goes wrong during the initialization - the function should return <c>{stop,Reason}</c>, where - <c>Reason</c> is any term, or <c>ignore</c>.</p> + <p>If <c>hibernate</c> is specified instead of a time-out value, the + process goes into hibernation when waiting for the next message + to arrive (by calling <seealso marker="proc_lib#hibernate/3"> + <c>proc_lib:hibernate/3</c></seealso>).</p> + <p>If the initialization fails, the function returns + <c>{stop,Reason}</c>, where <c>Reason</c> is any term, + or <c>ignore</c>.</p> </desc> </func> + <func> <name>Module:StateName(Event, StateData) -> Result</name> <fsummary>Handle an asynchronous event.</fsummary> @@ -549,8 +788,8 @@ gen_fsm:sync_send_all_state_event -----> Module:handle_sync_event/4 <v>Event = timeout | term()</v> <v>StateData = term()</v> <v>Result = {next_state,NextStateName,NewStateData} </v> - <v> | {next_state,NextStateName,NewStateData,Timeout}</v> - <v> | {next_state,NextStateName,NewStateData,hibernate}</v> + <v> | {next_state,NextStateName,NewStateData,Timeout}</v> + <v> | {next_state,NextStateName,NewStateData,hibernate}</v> <v> | {stop,Reason,NewStateData}</v> <v> NextStateName = atom()</v> <v> NewStateData = term()</v> @@ -558,56 +797,33 @@ gen_fsm:sync_send_all_state_event -----> Module:handle_sync_event/4 <v> Reason = term()</v> </type> <desc> - <p>There should be one instance of this function for each - possible state name. Whenever a gen_fsm receives an event - sent using - <seealso marker="#send_event/2">gen_fsm:send_event/2</seealso>, + <p>There is to be one instance of this function for each + possible state name. Whenever a <c>gen_fsm</c> process receives + an event sent using + <seealso marker="#send_event/2"><c>send_event/2</c></seealso>, the instance of this function with the same name as the current state name <c>StateName</c> is called to handle - the event. It is also called if a timeout occurs.</p> - <p><c>Event</c> is either the atom <c>timeout</c>, if a timeout + the event. It is also called if a time-out occurs.</p> + <p><c>Event</c> is either the atom <c>timeout</c>, if a time-out has occurred, or the <c>Event</c> argument provided to <c>send_event/2</c>.</p> - <p><c>StateData</c> is the state data of the gen_fsm.</p> + <p><c>StateData</c> is the state data of the <c>gen_fsm</c> process.</p> <p>If the function returns <c>{next_state,NextStateName,NewStateData}</c>, - <c>{next_state,NextStateName,NewStateData,Timeout}</c> or - <c>{next_state,NextStateName,NewStateData,hibernate}</c>, - the gen_fsm will continue executing with the current state + <c>{next_state,NextStateName,NewStateData,Timeout}</c>, or + <c>{next_state,NextStateName,NewStateData,hibernate}</c>, the + <c>gen_fsm</c> process continues executing with the current state name set to <c>NextStateName</c> and with the possibly - updated state data <c>NewStateData</c>. See - <c>Module:init/1</c> for a description of <c>Timeout</c> and <c>hibernate</c>.</p> + updated state data <c>NewStateData</c>. For a description of + <c>Timeout</c> and <c>hibernate</c>, see + <seealso marker="#Module:init/1"><c>Module:init/1</c></seealso>.</p> <p>If the function returns <c>{stop,Reason,NewStateData}</c>, - the gen_fsm will call + the <c>gen_fsm</c> process calls <c>Module:terminate(Reason,StateName,NewStateData)</c> and - terminate.</p> - </desc> - </func> - <func> - <name>Module:handle_event(Event, StateName, StateData) -> Result</name> - <fsummary>Handle an asynchronous event.</fsummary> - <type> - <v>Event = term()</v> - <v>StateName = atom()</v> - <v>StateData = term()</v> - <v>Result = {next_state,NextStateName,NewStateData} </v> - <v> | {next_state,NextStateName,NewStateData,Timeout}</v> - <v> | {next_state,NextStateName,NewStateData,hibernate}</v> - <v> | {stop,Reason,NewStateData}</v> - <v> NextStateName = atom()</v> - <v> NewStateData = term()</v> - <v> Timeout = int()>0 | infinity</v> - <v> Reason = term()</v> - </type> - <desc> - <p>Whenever a gen_fsm receives an event sent using - <seealso marker="#send_all_state_event/2">gen_fsm:send_all_state_event/2</seealso>, - this function is called to handle the event.</p> - <p><c>StateName</c> is the current state name of the gen_fsm.</p> - <p>See <c>Module:StateName/2</c> for a description of the other - arguments and possible return values.</p> + terminates.</p> </desc> </func> + <func> <name>Module:StateName(Event, From, StateData) -> Result</name> <fsummary>Handle a synchronous event.</fsummary> @@ -616,11 +832,11 @@ gen_fsm:sync_send_all_state_event -----> Module:handle_sync_event/4 <v>From = {pid(),Tag}</v> <v>StateData = term()</v> <v>Result = {reply,Reply,NextStateName,NewStateData}</v> - <v> | {reply,Reply,NextStateName,NewStateData,Timeout}</v> - <v> | {reply,Reply,NextStateName,NewStateData,hibernate}</v> + <v> | {reply,Reply,NextStateName,NewStateData,Timeout}</v> + <v> | {reply,Reply,NextStateName,NewStateData,hibernate}</v> <v> | {next_state,NextStateName,NewStateData}</v> - <v> | {next_state,NextStateName,NewStateData,Timeout}</v> - <v> | {next_state,NextStateName,NewStateData,hibernate}</v> + <v> | {next_state,NextStateName,NewStateData,Timeout}</v> + <v> | {next_state,NextStateName,NewStateData,hibernate}</v> <v> | {stop,Reason,Reply,NewStateData} | {stop,Reason,NewStateData}</v> <v> Reply = term()</v> <v> NextStateName = atom()</v> @@ -629,102 +845,56 @@ gen_fsm:sync_send_all_state_event -----> Module:handle_sync_event/4 <v> Reason = normal | term()</v> </type> <desc> - <p>There should be one instance of this function for each - possible state name. Whenever a gen_fsm receives an event - sent using - <seealso marker="#sync_send_event/2">gen_fsm:sync_send_event/2,3</seealso>, + <p>There is to be one instance of this function for each + possible state name. Whenever a <c>gen_fsm</c> process receives an + event sent using <seealso marker="#sync_send_event/2"> + <c>sync_send_event/2,3</c></seealso>, the instance of this function with the same name as the current state name <c>StateName</c> is called to handle the event.</p> <p><c>Event</c> is the <c>Event</c> argument provided to - <c>sync_send_event</c>.</p> + <c>sync_send_event/2,3</c>.</p> <p><c>From</c> is a tuple <c>{Pid,Tag}</c> where <c>Pid</c> is - the pid of the process which called <c>sync_send_event/2,3</c> + the pid of the process that called <c>sync_send_event/2,3</c> and <c>Tag</c> is a unique tag.</p> - <p><c>StateData</c> is the state data of the gen_fsm.</p> - <p>If the function returns - <c>{reply,Reply,NextStateName,NewStateData}</c>, - <c>{reply,Reply,NextStateName,NewStateData,Timeout}</c> or - <c>{reply,Reply,NextStateName,NewStateData,hibernate}</c>, - <c>Reply</c> will be given back to <c>From</c> as the return - value of <c>sync_send_event/2,3</c>. The gen_fsm then - continues executing with the current state name set to - <c>NextStateName</c> and with the possibly updated state data - <c>NewStateData</c>. See <c>Module:init/1</c> for a - description of <c>Timeout</c> and <c>hibernate</c>.</p> - <p>If the function returns - <c>{next_state,NextStateName,NewStateData}</c>, - <c>{next_state,NextStateName,NewStateData,Timeout}</c> or - <c>{next_state,NextStateName,NewStateData,hibernate}</c>, - the gen_fsm will continue executing in <c>NextStateName</c> - with <c>NewStateData</c>. Any reply to <c>From</c> must be - given explicitly using - <seealso marker="#reply/2">gen_fsm:reply/2</seealso>.</p> - <p>If the function returns - <c>{stop,Reason,Reply,NewStateData}</c>, <c>Reply</c> will be - given back to <c>From</c>. If the function returns - <c>{stop,Reason,NewStateData}</c>, any reply to <c>From</c> - must be given explicitly using <c>gen_fsm:reply/2</c>. - The gen_fsm will then call - <c>Module:terminate(Reason,StateName,NewStateData)</c> and - terminate.</p> - </desc> - </func> - <func> - <name>Module:handle_sync_event(Event, From, StateName, StateData) -> Result</name> - <fsummary>Handle a synchronous event.</fsummary> - <type> - <v>Event = term()</v> - <v>From = {pid(),Tag}</v> - <v>StateName = atom()</v> - <v>StateData = term()</v> - <v>Result = {reply,Reply,NextStateName,NewStateData}</v> - <v> | {reply,Reply,NextStateName,NewStateData,Timeout}</v> - <v> | {reply,Reply,NextStateName,NewStateData,hibernate}</v> - <v> | {next_state,NextStateName,NewStateData}</v> - <v> | {next_state,NextStateName,NewStateData,Timeout}</v> - <v> | {next_state,NextStateName,NewStateData,hibernate}</v> - <v> | {stop,Reason,Reply,NewStateData} | {stop,Reason,NewStateData}</v> - <v> Reply = term()</v> - <v> NextStateName = atom()</v> - <v> NewStateData = term()</v> - <v> Timeout = int()>0 | infinity</v> - <v> Reason = term()</v> - </type> - <desc> - <p>Whenever a gen_fsm receives an event sent using - <seealso marker="#sync_send_all_state_event/2">gen_fsm:sync_send_all_state_event/2,3</seealso>, - this function is called to handle the event.</p> - <p><c>StateName</c> is the current state name of the gen_fsm.</p> - <p>See <c>Module:StateName/3</c> for a description of the other - arguments and possible return values.</p> - </desc> - </func> - <func> - <name>Module:handle_info(Info, StateName, StateData) -> Result</name> - <fsummary>Handle an incoming message.</fsummary> - <type> - <v>Info = term()</v> - <v>StateName = atom()</v> - <v>StateData = term()</v> - <v>Result = {next_state,NextStateName,NewStateData}</v> - <v> | {next_state,NextStateName,NewStateData,Timeout}</v> - <v> | {next_state,NextStateName,NewStateData,hibernate}</v> - <v> | {stop,Reason,NewStateData}</v> - <v> NextStateName = atom()</v> - <v> NewStateData = term()</v> - <v> Timeout = int()>0 | infinity</v> - <v> Reason = normal | term()</v> - </type> - <desc> - <p>This function is called by a gen_fsm when it receives any - other message than a synchronous or asynchronous event (or a - system message).</p> - <p><c>Info</c> is the received message.</p> - <p>See <c>Module:StateName/2</c> for a description of the other - arguments and possible return values.</p> + <p><c>StateData</c> is the state data of the <c>gen_fsm</c> process.</p> + <list type="bulleted"> + <item> + <p>If <c>{reply,Reply,NextStateName,NewStateData}</c>, + <c>{reply,Reply,NextStateName,NewStateData,Timeout}</c>, or + <c>{reply,Reply,NextStateName,NewStateData,hibernate}</c> is + returned, <c>Reply</c> is given back to <c>From</c> as the return + value of <c>sync_send_event/2,3</c>. The <c>gen_fsm</c> process + then continues executing with the current state name set to + <c>NextStateName</c> and with the possibly updated state data + <c>NewStateData</c>. For a description of <c>Timeout</c> and + <c>hibernate</c>, see + <seealso marker="#Module:init/1"> + <c>Module:init/1</c></seealso>.</p> + </item> + <item> + <p>If <c>{next_state,NextStateName,NewStateData}</c>, + <c>{next_state,NextStateName,NewStateData,Timeout}</c>, or + <c>{next_state,NextStateName,NewStateData,hibernate}</c> is + returned, the <c>gen_fsm</c> process continues executing in + <c>NextStateName</c> with <c>NewStateData</c>. + Any reply to <c>From</c> must be specified explicitly using + <seealso marker="#reply/2"><c>reply/2</c></seealso>.</p> + </item> + <item> + <p>If the function returns + <c>{stop,Reason,Reply,NewStateData}</c>, <c>Reply</c> is + given back to <c>From</c>. If the function returns + <c>{stop,Reason,NewStateData}</c>, any reply to <c>From</c> + must be specified explicitly using <c>reply/2</c>. + The <c>gen_fsm</c> process then calls + <c>Module:terminate(Reason,StateName,NewStateData)</c> and + terminates.</p> + </item> + </list> </desc> </func> + <func> <name>Module:terminate(Reason, StateName, StateData)</name> <fsummary>Clean up before termination.</fsummary> @@ -734,134 +904,56 @@ gen_fsm:sync_send_all_state_event -----> Module:handle_sync_event/4 <v>StateData = term()</v> </type> <desc> - <p>This function is called by a gen_fsm when it is about to - terminate. It should be the opposite of <c>Module:init/1</c> - and do any necessary cleaning up. When it returns, the gen_fsm - terminates with <c>Reason</c>. The return value is ignored.</p> + <p>This function is called by a <c>gen_fsm</c> process when it is about + to terminate. It is to be the opposite of + <seealso marker="#Module:init/1"><c>Module:init/1</c></seealso> + and do any necessary cleaning up. When it returns, the <c>gen_fsm</c> + process terminates with <c>Reason</c>. The return value is ignored. + </p> <p><c>Reason</c> is a term denoting the stop reason, <c>StateName</c> is the current state name, and - <c>StateData</c> is the state data of the gen_fsm.</p> - <p><c>Reason</c> depends on why the gen_fsm is terminating. If + <c>StateData</c> is the state data of the <c>gen_fsm</c> process.</p> + <p><c>Reason</c> depends on why the <c>gen_fsm</c> process is + terminating. If it is because another callback function has returned a stop - tuple <c>{stop,..}</c>, <c>Reason</c> will have the value - specified in that tuple. If it is due to a failure, + tuple <c>{stop,..}</c>, <c>Reason</c> has the value + specified in that tuple. If it is because of a failure, <c>Reason</c> is the error reason.</p> - <p>If the gen_fsm is part of a supervision tree and is ordered - by its supervisor to terminate, this function will be called + <p>If the <c>gen_fsm</c> process is part of a supervision tree and is + ordered by its supervisor to terminate, this function is called with <c>Reason=shutdown</c> if the following conditions apply:</p> <list type="bulleted"> - <item>the gen_fsm has been set to trap exit signals, and</item> - <item>the shutdown strategy as defined in the supervisor's - child specification is an integer timeout value, not - <c>brutal_kill</c>.</item> + <item> + <p>The <c>gen_fsm</c> process has been set to trap exit signals.</p> + </item> + <item> + <p>The shutdown strategy as defined in the child specification of + the supervisor is an integer time-out value, not + <c>brutal_kill</c>.</p> + </item> </list> - <p>Even if the gen_fsm is <em>not</em> part of a supervision tree, - this function will be called if it receives an <c>'EXIT'</c> - message from its parent. <c>Reason</c> will be the same as in - the <c>'EXIT'</c> message.</p> - <p>Otherwise, the gen_fsm will be immediately terminated.</p> - <p>Note that for any other reason than <c>normal</c>, - <c>shutdown</c>, or <c>{shutdown,Term}</c> the gen_fsm is - assumed to terminate due to an error and - an error report is issued using - <seealso marker="kernel:error_logger#format/2">error_logger:format/2</seealso>.</p> - </desc> - </func> - <func> - <name>Module:code_change(OldVsn, StateName, StateData, Extra) -> {ok, NextStateName, NewStateData}</name> - <fsummary>Update the internal state data during upgrade/downgrade.</fsummary> - <type> - <v>OldVsn = Vsn | {down, Vsn}</v> - <v> Vsn = term()</v> - <v>StateName = NextStateName = atom()</v> - <v>StateData = NewStateData = term()</v> - <v>Extra = term()</v> - </type> - <desc> - <p>This function is called by a gen_fsm when it should update - its internal state data during a release upgrade/downgrade, - i.e. when the instruction <c>{update,Module,Change,...}</c> - where <c>Change={advanced,Extra}</c> is given in - the <c>appup</c> file. See - <seealso marker="doc/design_principles:release_handling#instr">OTP Design Principles</seealso>.</p> - <p>In the case of an upgrade, <c>OldVsn</c> is <c>Vsn</c>, and - in the case of a downgrade, <c>OldVsn</c> is - <c>{down,Vsn}</c>. <c>Vsn</c> is defined by the <c>vsn</c> - attribute(s) of the old version of the callback module - <c>Module</c>. If no such attribute is defined, the version is - the checksum of the BEAM file.</p> - <p><c>StateName</c> is the current state name and - <c>StateData</c> the internal state data of the gen_fsm.</p> - <p><c>Extra</c> is passed as-is from the <c>{advanced,Extra}</c> - part of the update instruction.</p> - <p>The function should return the new current state name and - updated internal data.</p> - </desc> - </func> - <func> - <name>Module:format_status(Opt, [PDict, StateData]) -> Status</name> - <fsummary>Optional function for providing a term describing the - current gen_fsm status.</fsummary> - <type> - <v>Opt = normal | terminate</v> - <v>PDict = [{Key, Value}]</v> - <v>StateData = term()</v> - <v>Status = term()</v> - </type> - <desc> - <note> - <p>This callback is optional, so callback modules need not - export it. The gen_fsm module provides a default - implementation of this function that returns the callback - module state data.</p> - </note> - <p>This function is called by a gen_fsm process when:</p> - <list type="bulleted"> - <item>One - of <seealso marker="sys#get_status/1">sys:get_status/1,2</seealso> - is invoked to get the gen_fsm status. <c>Opt</c> is set to - the atom <c>normal</c> for this case.</item> - <item>The gen_fsm terminates abnormally and logs an - error. <c>Opt</c> is set to the atom <c>terminate</c> for - this case.</item> - </list> - <p>This function is useful for customising the form and - appearance of the gen_fsm status for these cases. A callback - module wishing to customise the <c>sys:get_status/1,2</c> - return value as well as how its status appears in - termination error logs exports an instance - of <c>format_status/2</c> that returns a term describing the - current status of the gen_fsm.</p> - <p><c>PDict</c> is the current value of the gen_fsm's - process dictionary.</p> - <p><c>StateData</c> is the internal state data of the - gen_fsm.</p> - <p>The function should return <c>Status</c>, a term that - customises the details of the current state and status of - the gen_fsm. There are no restrictions on the - form <c>Status</c> can take, but for - the <c>sys:get_status/1,2</c> case (when <c>Opt</c> - is <c>normal</c>), the recommended form for - the <c>Status</c> value is <c>[{data, [{"StateData", - Term}]}]</c> where <c>Term</c> provides relevant details of - the gen_fsm state data. Following this recommendation isn't - required, but doing so will make the callback module status - consistent with the rest of the <c>sys:get_status/1,2</c> - return value.</p> - <p>One use for this function is to return compact alternative - state data representations to avoid having large state terms - printed in logfiles.</p> + <p>Even if the <c>gen_fsm</c> process is <em>not</em> part of a + supervision tree, + this function is called if it receives an <c>'EXIT'</c> + message from its parent. <c>Reason</c> is the same as in + the <c>'EXIT'</c> message.</p> + <p>Otherwise, the <c>gen_fsm</c> process terminates immediately.</p> + <p>Notice that for any other reason than <c>normal</c>, + <c>shutdown</c>, or <c>{shutdown,Term}</c> the <c>gen_fsm</c> process + is assumed to terminate because of an error and an error report is + issued using <seealso marker="kernel:error_logger#format/2"> + <c>error_logger:format/2</c></seealso>.</p> </desc> </func> </funcs> <section> - <title>SEE ALSO</title> - <p><seealso marker="gen_event">gen_event(3)</seealso>, - <seealso marker="gen_server">gen_server(3)</seealso>, - <seealso marker="gen_statem">gen_statem(3)</seealso>, - <seealso marker="supervisor">supervisor(3)</seealso>, - <seealso marker="proc_lib">proc_lib(3)</seealso>, - <seealso marker="sys">sys(3)</seealso></p> + <title>See Also</title> + <p><seealso marker="gen_event"><c>gen_event(3)</c></seealso>, + <seealso marker="gen_server"><c>gen_server(3)</c></seealso>, + <seealso marker="gen_statem"><c>gen_statem(3)</c></seealso>, + <seealso marker="proc_lib"><c>proc_lib(3)</c></seealso>, + <seealso marker="supervisor"><c>supervisor(3)</c></seealso>, + <seealso marker="sys"><c>sys(3)</c></seealso></p> </section> </erlref> |