From 17405463ba134e71ff09e8d2921de9aa931805ee Mon Sep 17 00:00:00 2001 From: Raimo Niskanen Date: Mon, 9 May 2016 14:20:03 +0200 Subject: Fix all seealso and other minor changes --- lib/stdlib/doc/src/gen_statem.xml | 296 ++++++++++---------------------- system/doc/design_principles/statem.xml | 184 ++++++-------------- 2 files changed, 145 insertions(+), 335 deletions(-) diff --git a/lib/stdlib/doc/src/gen_statem.xml b/lib/stdlib/doc/src/gen_statem.xml index be90488a1f..b1d9799917 100644 --- a/lib/stdlib/doc/src/gen_statem.xml +++ b/lib/stdlib/doc/src/gen_statem.xml @@ -84,9 +84,7 @@ 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 - - OTP Design Principles - . + OTP Design Principles.

A gen_statem assumes all specific parts to be located in a @@ -136,28 +134,23 @@ erlang:'!' -----> Module:StateName/3 callback mode is state_functions, the state must be an atom and is used as the state function name; see - - Module:StateName/3 - . + Module:StateName/3. This gathers all code for a specific state in one function and hence dispatches on state first. Notice that in this mode the mandatory callback function - - Module:terminate/3 - makes the state name terminate unusable. + Module:terminate/3 + makes the state name terminate unusable.

When the callback mode is handle_event_function, the state can be any term and the state function name is - - Module:handle_event/4 - . + Module:handle_event/4. This makes it easy to dispatch on state or on event as you desire. Be careful about which events you handle in which - states so that you do not accidentally postpone one event + states so that you do not accidentally postpone an event forever creating an infinite busy loop.

@@ -178,15 +171,12 @@ erlang:'!' -----> Module:StateName/3

The state function can insert events using the - - action() next_event - + action() + next_event and such an event is inserted as the next to present to the state function. That is, as if it is the oldest incoming event. A dedicated - - event_type() - + event_type() internal can be used for such events making them impossible to mistake for external events.

@@ -206,21 +196,18 @@ erlang:'!' -----> Module:StateName/3

For the details of a state transition, see type - - transition_option() - . + transition_option().

A gen_statem handles system messages as described in sys. - The sysmodule can be used for debugging a gen_statem. + The sys module can be used for debugging a gen_statem.

Notice that a gen_statem does not trap exit signals automatically, this must be explicitly initiated in the callback module (by calling - - process_flag(trap_exit, true). + process_flag(trap_exit, true).

Unless otherwise stated, all functions in this module fail if @@ -229,9 +216,7 @@ erlang:'!' -----> Module:StateName/3

The gen_statem process can go into hibernation; see - - proc_lib:hibernate/3 - . + proc_lib:hibernate/3. It is done when a state function or Module:init/1 @@ -242,9 +227,7 @@ erlang:'!' -----> Module:StateName/3 However, use this feature with care, as hibernation can be too costly to use after every event; see - - erlang:hibernate/3 - . + erlang:hibernate/3.

@@ -257,7 +240,7 @@ erlang:'!' -----> Module:StateName/3 state_functions. You can push the button and it replies if it went on or off, and you can ask for a count of how many times it has been - pushed to on. + pushed to switch on.

The following is the complete callback module file pushbutton.erl:

@@ -381,13 +364,10 @@ handle_event(_, _, State, Data) ->

Name specification to use when starting a gen_statem server. See - - start_link/3 - + start_link/3 and - - server_ref() - below. + server_ref() + below.

@@ -398,14 +378,12 @@ handle_event(_, _, State, Data) -> Server specification to use when addressing a gen_statem server. See call/2 and - - server_name() - + server_name() above.

It can be:

- pid() | LocalName + pid() | LocalName

The gen_statem is locally registered. @@ -421,21 +399,21 @@ handle_event(_, _, State, Data) -> {global,GlobalName}

- The gen_statem is globally registered - in kernel:global. + The gen_statem is globally registered in + kernel:global.

{via,RegMod,ViaName}

- The gen_statem is registered through + The gen_statem is registered in an alternative process registry. The registry callback module RegMod is to export functions register_name/2, unregister_name/1, whereis_name/1, and send/2, - which are to behave like the corresponding functions - in kernel:global. + which are to behave like the corresponding functions in + kernel:global. Thus, {via,global,GlobalName} is the same as {global,GlobalName}.

@@ -482,9 +460,7 @@ handle_event(_, _, State, Data) ->

Destination to use when replying through, for example, the - - action() - + action() {reply,From,Reply} to a process that has called the gen_statem server using call/2. @@ -554,9 +530,7 @@ handle_event(_, _, State, Data) -> or when calling enter_loop/5,6,7, and with the return value from - - Module:code_change/4 - . + Module:code_change/4.

state_functions @@ -565,9 +539,7 @@ handle_event(_, _, State, Data) -> The state must be of type state_name() and one callback function per state, that is, - - Module:StateName/3 - , + Module:StateName/3, is used.

@@ -575,9 +547,7 @@ handle_event(_, _, State, Data) ->

The state can be any term and the callback function - - Module:handle_event/4 - + Module:handle_event/4 is used for all states.

@@ -604,9 +574,7 @@ handle_event(_, _, State, Data) ->

If - - postpone() - + postpone() is true, the current event is postponed.

@@ -620,9 +588,7 @@ handle_event(_, _, State, Data) ->

All events stored with - - action() - + action() next_event are inserted in the queue to be processed before all other events. @@ -631,13 +597,9 @@ handle_event(_, _, State, Data) ->

If an - - event_timeout() - + event_timeout() is set through - - action() - + action() timeout, an event timer can be started or a time-out zero event can be enqueued. @@ -651,9 +613,7 @@ handle_event(_, _, State, Data) -> otherwise the gen_statem goes into receive or hibernation (if - - hibernate() - + hibernate() is true) to wait for the next message. In hibernation the next non-system event awakens the gen_statem, or rather @@ -681,16 +641,13 @@ handle_event(_, _, State, Data) ->

If true, hibernates the gen_statem by calling - - proc_lib:hibernate/3 - + proc_lib:hibernate/3 before going into receive to wait for a new external event. If there are enqueued events, to prevent receiving any new event, an - - erlang:garbage_collect/0 - is done instead to simulate + erlang:garbage_collect/0 + is done instead to simulate that the gen_statem entered hibernation and immediately got awakened by the oldest enqueued event.

@@ -731,8 +688,8 @@ handle_event(_, _, State, Data) ->

These state transition actions can be invoked by returning them from the - state function, - from Module:init/1 + state function, from + Module:init/1 or by giving them to enter_loop/6,7.

@@ -741,15 +698,11 @@ handle_event(_, _, State, Data) ->

Actions that set - - transition options - + transition options override any previous of the same type, so the last in the containing list wins. For example, the last - - event_timeout() - + event_timeout() overrides any other event_timeout() in the list.

@@ -757,12 +710,8 @@ handle_event(_, _, State, Data) ->

Sets the - - transition_option() - - - postpone() - + transition_option() + postpone() for this state transition. This action is ignored when returned from Module:init/1 @@ -775,12 +724,8 @@ handle_event(_, _, State, Data) ->

Sets the - - transition_option() - - - hibernate() - + transition_option() + hibernate() for this state transition.

@@ -792,22 +737,16 @@ handle_event(_, _, State, Data) -> This form exists to make the state function return value {next_state,NextState,NewData,Timeout} - allowed like for - - gen_fsm:Module:StateName/2 - . + allowed like for gen_fsm's + Module:StateName/2.

timeout

Sets the - - transition_option() - - - event_timeout() - + transition_option() + event_timeout() to Time with EventContent.

@@ -832,9 +771,7 @@ handle_event(_, _, State, Data) ->

An event of type - - internal - + internal is to be used when you want to reliably distinguish an event inserted this way from any external event.

@@ -849,9 +786,7 @@ handle_event(_, _, State, Data) -> Replies to a caller waiting for a reply in call/2. From must be the term from argument - - {call,From} - + {call,From} to the state function.

@@ -907,9 +842,7 @@ handle_event(_, _, State, Data) ->

Terminates the gen_statem by calling - - Module:terminate/3 - + Module:terminate/3 with Reason and NewData, if specified.

@@ -919,9 +852,7 @@ handle_event(_, _, State, Data) ->

Sends all Replies, then terminates the gen_statem by calling - - Module:terminate/3 - + Module:terminate/3 with Reason and NewData, if specified.

@@ -965,9 +896,7 @@ handle_event(_, _, State, Data) ->

Makes a synchronous call to the gen_statem - - ServerRef - + ServerRef by sending a request and waiting until its reply arrives. The gen_statem calls the @@ -1015,9 +944,7 @@ handle_event(_, _, State, Data) ->

Sends an asynchronous event to the gen_statem - - ServerRef - + ServerRef and returns ok immediately, ignoring if the destination node or gen_statem does not exist. @@ -1038,9 +965,7 @@ handle_event(_, _, State, Data) -> The same as enter_loop/7 except that no - - server_name() - + server_name() must have been registered.

@@ -1055,9 +980,7 @@ handle_event(_, _, State, Data) -> the same as enter_loop/7 except that no - - server_name() - + server_name() must have been registered and Actions = Server_or_Actions.

@@ -1095,13 +1018,9 @@ handle_event(_, _, State, Data) -> Module, Opts, and Server have the same meanings as when calling - - start[_link]/3,4 - . + start[_link]/3,4. However, the - - server_name() - + server_name() name must have been registered accordingly before this function is called.

@@ -1137,16 +1056,12 @@ handle_event(_, _, State, Data) ->

From must be the term from argument - - {call,From} - + {call,From} to the state function. From and Reply can also be specified using a - - reply_action() - + reply_action() and multiple replies with a list of them.

@@ -1204,9 +1119,7 @@ handle_event(_, _, State, Data) ->

ServerName specifies the - - server_name() - + server_name() to register for the gen_statem. If the gen_statem is started with start_link/3, no ServerName is provided and @@ -1225,8 +1138,7 @@ handle_event(_, _, State, Data) -> Opts, the gen_statem is allowed to spend Time milliseconds initializing or it terminates and the start function returns - - {error,timeout}. + {error,timeout}.

@@ -1241,8 +1153,8 @@ handle_event(_, _, State, Data) ->

If option {spawn_opt,SpawnOpts} is present in Opts, SpawnOpts is passed - as option list to - erlang:spawn_opt/2, + as option list to + erlang:spawn_opt/2, which is used to spawn the gen_statem process.

@@ -1250,22 +1162,19 @@ handle_event(_, _, State, Data) ->

Using spawn option monitor is not - allowed, it cause this function to fail with reason + allowed, it causes this function to fail with reason badarg.

If the gen_statem is successfully created and initialized, this function returns - - {ok,Pid} - , + {ok,Pid}, where Pid is the pid() of the gen_statem. If a process with the specified ServerName exists already, this function returns - - {error,{already_started,Pid}}, + {error,{already_started,Pid}}, where Pid is the pid() of that process.

@@ -1273,16 +1182,12 @@ handle_event(_, _, State, Data) -> this function returns {error,Reason}. If Module:init/1 returns - - {stop,Reason} - + {stop,Reason} or ignore, the process is terminated and this function returns - - {error,Reason} - + {error,Reason} or ignore, respectively. @@ -1296,9 +1201,7 @@ handle_event(_, _, State, Data) ->

The same as - - stop(ServerRef, normal, infinity). - + stop(ServerRef, normal, infinity).

@@ -1309,15 +1212,11 @@ handle_event(_, _, State, Data) ->

Orders the gen_statem - - ServerRef - + ServerRef to exit with the specified Reason and waits for it to terminate. The gen_statem calls - - Module:terminate/3 - + Module:terminate/3 before exiting.

@@ -1325,9 +1224,7 @@ handle_event(_, _, State, Data) -> with the expected reason. Any other reason than normal, shutdown, or {shutdown,Term} causes an error report to be issued through - - error_logger:format/2 - . + error_logger:format/2. The default Reason is normal.

@@ -1388,9 +1285,7 @@ handle_event(_, _, State, Data) -> where Change={advanced,Extra}, is specified in the appup file. For more information, see - - OTP Design Principles - . + OTP Design Principles.

For an upgrade, OldVsn is Vsn, and @@ -1403,9 +1298,7 @@ handle_event(_, _, State, Data) ->

If you would dare to change - - callback mode - + callback mode during release upgrade/downgrade, the upgrade is no problem, as the new code surely knows what callback mode it needs. However, for a downgrade this function must @@ -1483,8 +1376,7 @@ handle_event(_, _, State, Data) -> return {CallbackMode,State,Data} or {CallbackMode,State,Data,Actions}. CallbackMode selects the - - callback mode + callback mode of the gen_statem. State is the initial state() @@ -1549,9 +1441,7 @@ handle_event(_, _, State, Data) -> One of - - sys:get_status/1,2 - + sys:get_status/1,2 is invoked to get the gen_statem status. Opt is set to the atom normal for this case. @@ -1564,9 +1454,7 @@ handle_event(_, _, State, Data) -> This function is useful for changing the form and appearance of the gen_statem status for these cases. A callback module wishing to change the - - sys:get_status/1,2 - + sys:get_status/1,2 return value and how its status appears in termination error logs exports an instance of format_status/2, which returns a term @@ -1589,9 +1477,7 @@ handle_event(_, _, State, Data) -> changes the details of the current state and status of the gen_statem. There are no restrictions on the form Status can take, but for the - - sys:get_status/1,2 - + sys:get_status/1,2 case (when Opt is normal), the recommended form for the Status value is [{data, [{"State", @@ -1599,9 +1485,7 @@ handle_event(_, _, State, Data) -> the gen_statem state. Following this recommendation is not required, but it makes the callback module status consistent with the rest of the - - sys:get_status/1,2 - + sys:get_status/1,2 return value.

@@ -1642,15 +1526,11 @@ handle_event(_, _, State, Data) -> StateFunctionResult = - - state_function_result() - + state_function_result() HandleEventResult = - - handle_event_result() - + handle_event_result() @@ -1766,9 +1646,7 @@ handle_event(_, _, State, Data) -> shutdown, or {shutdown,Term}, the gen_statem is assumed to terminate because of an error and an error report is issued using - - error_logger:format/2. - + error_logger:format/2.

This function can use @@ -1781,11 +1659,13 @@ handle_event(_, _, State, Data) ->

See Also -

gen_event(3), +

+ gen_event(3), gen_fsm(3), gen_server(3), proc_lib(3), supervisor(3), - sys(3)

+ sys(3). +

diff --git a/system/doc/design_principles/statem.xml b/system/doc/design_principles/statem.xml index 8b0fbed7c0..585b1a35f5 100644 --- a/system/doc/design_principles/statem.xml +++ b/system/doc/design_principles/statem.xml @@ -84,8 +84,9 @@ State(S) x Event(E) -> Actions(A), State(S') a server Data besides the state. Because of this, and as there is no restriction on the number of states (assuming that there is enough virtual machine memory) - or on the number of distinct input events, makes - a state machine implemented with this behavior Turing complete. + or on the number of distinct input events, + a state machine implemented with this behavior + is in fact Turing complete. But it feels mostly like an Event-Driven Mealy Machine.

@@ -101,8 +102,8 @@ State(S) x Event(E) -> Actions(A), State(S')

- In mode - state_functions, + In mode + state_functions, the state transition rules are written as some Erlang functions, which conform to the following convention:

@@ -113,20 +114,19 @@ StateName(EventType, EventContent, Data) ->

- In mode - handle_event_function, + In mode + handle_event_function, only one Erlang function provides all state transition rules:

 handle_event(EventType, EventContent, State, Data) ->
     .. code for actions here ...
-    {next_state, State', Data'}
+ {next_state, NewState, NewData}

Both these modes allow other return tuples; see - - Module:StateName/3 + Module:StateName/3 in the gen_statem manual page. These other return tuples can, for example, stop the machine, execute state transition actions on the machine engine itself, @@ -172,8 +172,7 @@ handle_event(EventType, EventContent, State, Data) -> This mode works equally well when you want to focus on one event at the time or on one state at the time, but function - - Module:handle_event/4 + Module:handle_event/4 quickly grows too large to handle without introducing dispatching.

@@ -291,9 +290,7 @@ start_link(Code) -> ]]>

start_link calls function - - gen_statem:start_link/4 - , + gen_statem:start_link/4, which spawns and links to a new process, a gen_statem.

@@ -308,9 +305,7 @@ start_link(Code) -> Instead its pid must be used. The name can also be specified as {global,Name}, then the gen_statem is registered using - - global:register_name/2 - + global:register_name/2 in Kernel.

@@ -339,9 +334,7 @@ start_link(Code) ->

The fourth argument, [], is a list of options. For the available options, see - - gen_statem:start_link/3 - . + gen_statem:start_link/3.

@@ -350,13 +343,9 @@ start_link(Code) -> calls callback function code_lock:init(Code). This function is expected to return {CallbackMode,State,Data}, where - - CallbackMode - + CallbackMode selects callback module state function mode, in this case - - state_functions - + state_functions through macro ?CALLBACK_MODE. That is, each state has got its own handler function. State is the initial state of the gen_statem, @@ -375,23 +364,17 @@ init(Code) -> {?CALLBACK_MODE,locked,Data}. ]]>

Function - - gen_statem:start_link - + gen_statem:start_link is synchronous. It does not return until the gen_statem is initialized and is ready to receive events.

Function - - gen_statem:start_link - + gen_statem:start_link must be used if the gen_statem is part of a supervision tree, that is, started by a supervisor. Another function, - - gen_statem:start - + gen_statem:start can be used to start a standalone gen_statem, that is, a gen_statem that is not part of a supervision tree.

@@ -403,9 +386,7 @@ init(Code) -> Handling Events

The function notifying the code lock about a button event is implemented using - - gen_statem:cast/2: - + gen_statem:cast/2:

@@ -528,9 +509,7 @@ handle_event({call,From}, code_length, #{code := Code} = Data) -> ]]>

This example uses - - gen_statem:call/2 - , + gen_statem:call/2, which waits for a reply from the server. The reply is sent with a {reply,From,Reply} tuple in an action list in the {keep_state,...} tuple @@ -545,15 +524,13 @@ handle_event({call,From}, code_length, #{code := Code} = Data) ->

If mode handle_event_function is used, all events are handled in - - Module:handle_event/4 - + Module:handle_event/4 and we can (but do not have to) use an event-centered approach where we dispatch on event first and then state:

strategy must be a time-out value and the gen_statem must in function init/1 set itself to trap exit signals by calling - - process_flag(trap_exit, true) - . - When ordered to shut down, the gen_statem then calls - callback function terminate(shutdown, State, Data): + process_flag(trap_exit, true):

@@ -616,6 +589,10 @@ init(Args) -> do_lock(), ... ]]> +

+ When ordered to shut down, the gen_statem then calls + callback function terminate(shutdown, State, Data). +

In the following example, function terminate/3 locks the door if it is open, so we do not accidentally leave the door @@ -633,9 +610,7 @@ terminate(_Reason, State, _Data) ->

If the gen_statem is not part of a supervision tree, it can be stopped using - - gen_statem:stop - , + gen_statem:stop, preferably through an API function:

Actions

In the first sections actions were mentioned as a part of - the general state machine model. These actions + the general state machine model. These general actions are implemented with the code that callback module gen_statem executes in an event-handling callback function before returning @@ -671,17 +646,11 @@ stop() -> that a callback function can order the gen_statem engine to do after the callback function return. These are ordered by returning a list of - - actions - + actions in the - - return tuple - + return tuple from the - - callback function - . + callback function. These state transition actions affect the gen_statem engine itself and can do the following:

@@ -697,9 +666,7 @@ stop() -> and replying to a caller. An example of event postponing is included later in this chapter. For details, see the - - gen_statem(3) - + gen_statem(3) manual page. You can, for example, reply to many callers and generate multiple next events to handle. @@ -712,9 +679,7 @@ stop() -> Event Types

The previous sections mentioned a few - - event types - . + event types. Events of all types are handled in the same callback function, for a given state, and the function gets EventType and EventContent as arguments. @@ -727,22 +692,16 @@ stop() -> cast Generated by - - gen_statem:cast. - + gen_statem:cast. {call,From} Generated by - - gen_statem:call - , + gen_statem:call, where From is the reply address to use when replying either through the state transition action {reply,From,Msg} or by calling - - gen_statem:reply - . + gen_statem:reply. info @@ -759,7 +718,7 @@ stop() -> Generated by state transition action {next_event,internal,EventContent}. - All event types above can be generated using + All event types above can also be generated using {next_event,EventType,EventContent}. @@ -780,9 +739,7 @@ stop() -> or you want to start a timer in one state and respond to the time-out in another. This can be accomplished with a regular Erlang timer: - - erlang:start_timer. - + erlang:start_timer.

For the example so far in this chapter: using the @@ -818,9 +775,7 @@ open(cast, {button,_}, Data) -> ]]>

If you need to cancel a timer because of some other event, you can use - - erlang:cancel_timer(Tref) - . + erlang:cancel_timer(Tref). Notice that a time-out message cannot arrive after this, unless you have postponed it (see the next section) before, so ensure that you do not accidentally postpone such messages. @@ -844,9 +799,7 @@ open(cast, {button,_}, Data) ->

Postponing is ordered by the state transition - - action - + action postpone.

@@ -861,7 +814,7 @@ open(cast, {button,_}, Data) -> ... ]]>

- A postponed event is only retried after a state change + The fact that a postponed event is only retried after a state change translates into a requirement on the event and state space. If you have a choice between storing a state data item in the State or in the Data: @@ -953,9 +906,7 @@ do_unlock() ->

The state transition - - action - + action postpone is designed to model selective receives. A selective receive implicitly postpones any not received events, but the postpone @@ -977,16 +928,12 @@ do_unlock() -> It can sometimes be beneficial to be able to generate events to your own state machine. This can be done with the state transition - - action - + action {next_event,EventType,EventContent}.

You can generate events of any existing - - type - , + type, but the internal type can only be generated through action next_event. Hence, it cannot come from an external source, so you can be certain that an internal event is an event @@ -1150,9 +1097,9 @@ code_change(_Vsn, State, Data, _Extra) ->

This section describes what to change in the example to use one handle_event/4 function. - The following clean first-dispatch-on-event approach - does not work that well because of the generated - entry actions: + The previously used clean first-dispatch-on-event approach + does not work that well here because of the generated + entry actions so this example dispatches on state first:

To avoid this, you can format the internal state that gets in the error log and gets returned from - - sys:get_status/1,2 - + sys:get_status/1,2 by implementing function - - Module:format_status/2 - , + Module:format_status/2, for example like this:

]]>

It is not mandatory to implement a - - Module:format_status/2 - + Module:format_status/2 function. If you do not, a default implementation is used that does the same as this example function without filtering the Data term, that is, StateData = {State,Data}. @@ -1274,13 +1215,9 @@ format_status(Opt, [_PDict,State,Data]) -> Complex State

The callback mode - - handle_event_function - + handle_event_function enables using a non-atom state as described in section - - Callback Modes - , + Callback Modes, for example, a complex state term like a tuple.

@@ -1308,8 +1245,7 @@ format_status(Opt, [_PDict,State,Data]) ->

So we make the button/1 function synchronous by using - - gen_statem:call + gen_statem:call and still postpone its events in the open state. Then a call to button/1 during the open state does not return until the state transits to locked, @@ -1462,16 +1398,12 @@ format_status(Opt, [_PDict,State,Data]) -> and the amount of heap memory all these servers need is a problem, then the memory footprint of a server can be mimimized by hibernating it through - - proc_lib:hibernate/3. - + proc_lib:hibernate/3.

It is rather costly to hibernate a process; see - - erlang:hibernate/3 - . + erlang:hibernate/3. It is not something you want to do after every event.

@@ -1495,9 +1427,7 @@ handle_event( ]]>

The - - [hibernate] - + [hibernate] action list on the last line when entering the {open,_} state is the only change. If any event arrives in the {open,_}, state, we -- cgit v1.2.3