gen_fsm

MODULE

gen_fsm

MODULE SUMMARY

A Finite State Machine Behaviour

DESCRIPTION

This module provides a standard way of writing Finite State
Machine (FSM) processes. All FSMs written as gen_fsms share a
common set of interface functions. The generic parts of the FSM
contains functions for debugging, for handling the termination
of the parent process, and for presentation of illustrative
error information if something goes wrong in the process.

The state of the FSM is defined by two parameters, the
StateName and the StateData. For each
StateName, there must be a corresponding function
exported from the call-back module. When an event is received,
and the current state of the FSM is StateName,
Module:StateName(Event, StateData) is called. This
function should return the next state, which is the next
StateName.

It is also possible to define a function
Module:handle_event(Event, StateName, StateData) to take
care of events which should always be handled, regardless of
their state. This function is called when
gen_fsm:send_all_state_event/2 is used to generate an
event.

Events can be handled synchronously as well. This means that
the caller waits for a reply to the event.

The relationship between the generic interface functions (and
received messages) and the callback functions can be illustrated
as follows:

Starts an FSM process. An anonymous process is started if
Name is not specified. This process can only be
called by using the returned Pid identifier.

A
process which is started with start does not care
about the parent, which means that the parent is not handled
explicitly in the generic process part. If started in this
manner, this function must not be used if the FSM
is a worker in a supervision tree.

A process started with start_link is initially
linked to the caller - the parent - and will terminate
whenever the parent process terminates, and with the same
reason as the parent. If started in this manner, this
function should be used if the FSM is a worker in a
supervision tree.

The function Module:init(StartArgs) is called (see
below).

Time specifies how long time, in milliseconds, the
server is allowed to initialize itself.

Sends an event synchronously to the FSM process and waits
for the answer. In the callback module, the function
StateName/3 is called, where StateName is the
name of the current state.

Timeout should be set to some reasonable value. The
special value infinity can be used if the user has no
idea how long the request is supposed to take. The default
is 5000.

If Timeout has an integer value and if no response
has been delivered within Timeout milliseconds, the
client will terminate with reason {timeout, {gen_fsm,
sync_send_event, [ProcessRef, Event, Timeout]}}.

If the server should crash during the
request and the client is linked to the server and the
client is trapping exits, (phew) the exit message
is read out from the clients receive queue and then
this function call fails with the exit reason that was read.
This is a remnant from when monitors did not exist and
links was the only way to supervise the request, and the
behaviour may change in a future release. In this release,
unfortuneately, under certain circumstances
(e.g. ProcessRef = {Name, Node},
Node crashes during call) the exit message cannot
be read out. Note that if the server crashes in between calls,
the client must take care of the exit message anyway.

An event, which can be handled in all states, is sent
synchronously to the FSM process. In the callback module,
handle_event/4 is called.

Timeout should be set to some reasonable value. The
special value infinity can be used if the user has no
idea how long the request is supposed to take. The default
is 5000.

If Timeout has an integer value and no response has
been delivered within Timeout milliseconds, the
client will terminate with reason {timeout, {gen_fsm,
sync_send_all_state_event, [ProcessRef, Event,
Timeout]}}.

If a reply cannot be returned immediately - as the
return value of Module:StateName/3 or
Module:handle_sync_event/4 - this function can be
used to make an explicit reply. To has the same value
as the From argument in these functions.

Callback Functions

The following functions
should be exported from a gen_fsm callback module.

This function initializes the FSM process and returns the
initial state. The Timeout variable specifies that
the process shall wait for Timeout milliseconds for
the first message. If no message has arrived within the
specified time, Module:StateName(timeout, StateData)
is called.

The StartArgs argument supplied to the init/1
function is the same as the argument supplied to the
gen_fsm:start functions.

If the process should trap exits, this has to be explicitly
expressed here with process_flag(trap_exit, true).

The representation of the FSM StateData is an
implementation specific detail which has to be decided by
the designer of the FSM. It can be any Erlang term.
StateData will be visible as an argument to all
callback functions. To change something in StateData,
a new value is returned from the callback function using the
terms described below.

If the initializing procedure fails, the reason is supplied
as StopReason with the {stop, StopReason}
return value.

This function can return ignore in order to inform
the parent, especially if it is a supervisor, that the FSM,
as an example, has not started in accordance with the
configuration data.

Handles events in the state StateName. The
Timeout variable is as in Module:init/1 above.

Whenever the function gen_fsm:send_event is called,
this function is called to handle the event. If the FSM
times out, this function is also called with Event =
timeout.

Event is the same term as supplied in the above
client call.

If the FSM decides to terminate, this function should
return {stop, Reason, NewStateData}, and the function
Module:terminate(Reason, StateName, NewStateData) is
called. If Reason is something other than
normal or shutdown, the FSM is assumed to have
terminated with a runtime failure. In this case, a lot of
information about the failure is reported. The atom
normal causes a normal termination while
shutdown causes an abnormal, but faultless,
termination of the process.

Handles synchronous events in the state StateName.
The Timeout variable is as in Module:init/1
above.

Whenever the function gen_fsm:sync_send_event/2,3 is
called, this function is called to handle the event.

Event is the same as the term supplied with the
above client call.

The FSM decides if a reply is sent to the caller directly
({reply, ...}), indirectly ({next_state,
...}), or if the FSM has to terminate ({stop,
...}) as a result of the request. If {next_state,
...} is returned, a reply can be sent to the caller
using the reply/2 function.

If the FSM decides to terminate, this function returns
{stop, Reason, NewStateData} or {stop, Reason,
Reply, NewStateData}, and the function
Module:terminate(Reason, StateName, NewStateData) is
called. If Reason is something other than
normal or shutdown, the FSM is assumed to have
terminated with a runtime failure. In this case, a lot of
information about the failure is reported. The atom
normal causes a normal termination while
shutdown causes an abnormal, but faultless,
termination of the process.

This function receives all messages sent to this process
which are not generated by gen_fsm:send_event/2,
gen_fsm:send_all_state_event/2,
gen_fsm:sync_send_event/2,3, or
gen_fsm:sync_send_all_state_event/2,3. Typical
messages handled here include:

{'EXIT', Pid, Reason}

If the
process traps exit signals, the corresponding messages are
handled here.

{nodedown, Node}

If another
Erlang node is monitored, the corresponding nodedown
message is handled here.

Msg

All other messages sent to
the process using Fsm ! Msg are also handled here.

Communication with the FSM should always go through
the interface functions described above.

This callback function is called whenever the FSM is
about to terminate. Either one of the above callback
functions have returned {stop, StopReason, ...}, in
which case Reason is equal to StopReason; or
some other fault has been caught. Reason is any term
which describes the termination reason. If the FSM traps
exits, the terminate function is called if the
FSM's parent (normally a supervisor) dies or orders the
FSM to die. If the FSM does not trap exits, it dies
immediately if the parent dies.

With this function, the FSM can clean up before the
process terminates. It can, for example, de-allocate
external resources.

The termination reason cannot be
changed here. The FSM will terminate due toReason
regardless of what was returned from this function.

This function is called when a code change is performed,
which implies that the internal data structures of the FSM
have changed. The function is supposed to convert the old
state to the new one. OldVsn is the vsn
attribute of the old version of the module. If no such
attribute was defined, the atom undefined is
sent. Extra is an optional term, typically defined in
the release upgrade script.

System events

The gen_fsm behaviour
generates the following system events, handled by the sys
module: