From 259c8c7bde51f0b25707f0101195aff22650e952 Mon Sep 17 00:00:00 2001 From: Raimo Niskanen Date: Wed, 27 Jul 2016 14:41:45 +0200 Subject: Rewrite gen_statem docs for M:callback_mode/0 --- lib/stdlib/doc/src/gen_statem.xml | 203 +++++++++++++++++++++++--------------- 1 file changed, 121 insertions(+), 82 deletions(-) (limited to 'lib/stdlib/doc/src') diff --git a/lib/stdlib/doc/src/gen_statem.xml b/lib/stdlib/doc/src/gen_statem.xml index ed44eef912..f18c1087ab 100644 --- a/lib/stdlib/doc/src/gen_statem.xml +++ b/lib/stdlib/doc/src/gen_statem.xml @@ -97,6 +97,9 @@ gen_statem module Callback module gen_statem:start gen_statem:start_link -----> Module:init/1 +Server start or code change + -----> Module:callback_mode/0 + gen_statem:stop -----> Module:terminate/3 gen_statem:call @@ -127,7 +130,8 @@ erlang:'!' -----> Module:StateName/3 in a gen_statem is the callback function that is called for all events in this state. It is selected depending on which callback mode - that the implementation specifies when the server starts. + that the callback module defines with the callback function + Module:callback_mode/0.

When the @@ -138,9 +142,9 @@ erlang:'!' -----> Module:StateName/3 This gathers all code for a specific state in one function as the gen_statem engine branches depending on state name. - Notice that in this mode the mandatory callback function + Notice the fact that there is a mandatory callback function Module:terminate/3 - makes the state name terminate unusable. + makes the state name terminate unusable in this mode.

When the @@ -249,11 +253,10 @@ erlang:'!' -----> Module:StateName/3 -behaviour(gen_statem). -export([start/0,push/0,get_count/0,stop/0]). --export([terminate/3,code_change/4,init/1]). +-export([terminate/3,code_change/4,init/1,callback_mode/0]). -export([on/3,off/3]). name() -> pushbutton_statem. % The registered server name -callback_mode() -> state_functions. %% API. This example uses a registered name name() %% and does not link to the caller. @@ -270,15 +273,14 @@ stop() -> terminate(_Reason, _State, _Data) -> void. code_change(_Vsn, State, Data, _Extra) -> - {callback_mode(),State,Data}. + {ok,State,Data}. init([]) -> - %% Set the callback mode and initial state + data. - %% Data is used only as a counter. + %% Set the initial state + data. Data is used only as a counter. State = off, Data = 0, - {callback_mode(),State,Data}. - + {ok,State,Data}. +callback_mode() -> state_functions. -%%% State functions +%%% State function(s) off({call,From}, push, Data) -> %% Go to 'on', increment count and reply @@ -326,18 +328,13 @@ ok To compare styles, here follows the same example using callback mode state_functions, or rather the code to replace - from function init/1 of the pushbutton.erl + after function init/1 of the pushbutton.erl example file above:

-init([]) -> - %% Set the callback mode and initial state + data. - %% Data is used only as a counter. - State = off, Data = 0, - {handle_event_function,State,Data}. - +callback_mode() -> handle_event_function. -%%% Event handling +%%% State function(s) handle_event({call,From}, push, off, Data) -> %% Go to 'on', increment count and reply @@ -426,8 +423,8 @@ handle_event(_, _, State, Data) ->

Debug option that can be used when starting - a gen_statem server through, for example, - enter_loop/5. + a gen_statem server through, + enter_loop/4-6.

For every entry in Dbgs, @@ -525,12 +522,9 @@ handle_event(_, _, State, Data) ->

The callback mode is selected when starting the - gen_statem using the return value from - Module:init/1 - or when calling - enter_loop/5,6,7, - and with the return value from - Module:code_change/4. + gen_statem and after code change + using the return value from + Module:callback_mode/0.

state_functions @@ -691,7 +685,7 @@ handle_event(_, _, State, Data) -> state function, from Module:init/1 or by giving them to - enter_loop/6,7. + enter_loop/5,6.

Actions are executed in the containing list order. @@ -958,35 +952,36 @@ handle_event(_, _, State, Data) -> - + Enter the gen_statem receive loop.

The same as - enter_loop/7 - except that no + enter_loop/6 + with Actions = [] except that no server_name() - must have been registered. + must have been registered. This creates an anonymous server.

- + Enter the gen_statem receive loop.

If Server_or_Actions is a list(), the same as - enter_loop/7 + enter_loop/6 except that no server_name() must have been registered and Actions = Server_or_Actions. + This creates an anonymous server.

Otherwise the same as - enter_loop/7 + enter_loop/6 with Server = Server_or_Actions and Actions = []. @@ -995,7 +990,7 @@ handle_event(_, _, State, Data) -> - + Enter the gen_statem receive loop.

@@ -1015,21 +1010,31 @@ handle_event(_, _, State, Data) -> the gen_statem behavior provides.

- Module, Opts, and - Server have the same meanings - as when calling + Module, Opts + have the same meaning as when calling start[_link]/3,4. +

+

+ If Server is self() an anonymous + server is created just as when using + start[_link]/3. + If Server is a + server_name() + a named server is created just as when using + start[_link]/4. However, the server_name() name must have been registered accordingly - before this function is called.

+ before this function is called. +

- CallbackMode, State, - Data, and Actions + State, Data, + and Actions have the same meanings as in the return value of Module:init/1. - Also, the callback module Module - does not need to export an init/1 function. + Also, the callback module does not need to export a + Module:init/1 + function.

The function fails if the calling process was not started by a @@ -1252,6 +1257,54 @@ handle_event(_, _, State, Data) -> + + Module:callback_mode() -> CallbackMode + Update the internal state during upgrade/downgrade. + + + CallbackMode = + callback_mode() + + + +

+ This function is called by a gen_statem + when it needs to find out the + callback mode + of the callback module. The value is cached by gen_statem + for efficiency reasons, so this function is only called + once after server start and after code change, + but before the first + state function + is called. More occasions may be added in future versions + of gen_statem. +

+

+ Server start happens either when + Module:init/1 + returns or when + enter_loop/4-6 + is called. Code change happens when + Module:code_change/4 + returns. +

+

+ This function can use + erlang:throw/1 + to return CallbackMode, just for symmetry reasons. + There should be no actual reason to use this. +

+ +

+ If this function's body does not consist of solely one of two + possible + atoms + the callback module is doing something strange. +

+
+
+
+ Module:code_change(OldVsn, OldState, OldData, Extra) -> Result @@ -1262,11 +1315,7 @@ handle_event(_, _, State, Data) ->   Vsn = term() OldState = NewState = term() Extra = term() - Result = {CallbackMode,NewState,NewData} | Reason - - CallbackMode = - callback_mode() - + Result = {ok,NewState,NewData} | Reason OldState = NewState = state() @@ -1295,21 +1344,6 @@ handle_event(_, _, State, Data) -> Module. If no such attribute is defined, the version is the checksum of the Beam file.

- -

- If you would dare to change - 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 - know from argument Extra that comes from the - sasl:appup - file what callback mode the old code did use. - It can also be possible to figure this out - from argument {down,Vsn}, as Vsn - in effect defines the old callback module version. -

-

OldState and OldData is the internal state of the gen_statem. @@ -1321,16 +1355,16 @@ handle_event(_, _, State, Data) ->

If successful, the function must return the updated internal state in an - {CallbackMode,NewState,NewData} tuple. + {ok,NewState,NewData} tuple.

If the function returns a failure Reason, the ongoing upgrade fails and rolls back to the old release. - Note that Reason can not be a 3-tuple since that - will be regarded as a - {CallbackMode,NewState,NewData} tuple, + Note that Reason can not be an {ok,_,_} tuple + since that will be regarded as a + {ok,NewState,NewData} tuple, and that a tuple matching {ok,_} - is an invalid failure Reason. + is an also invalid failure Reason. It is recommended to use an atom as Reason since it will be wrapped in an {error,Reason} tuple.

@@ -1344,16 +1378,14 @@ handle_event(_, _, State, Data) -> Module:init(Args) -> Result - Initialize process and internal state. + + Optional function for initializing process and internal state. + Args = term() - Result = {CallbackMode,State,Data} -  | {CallbackMode,State,Data,Actions} + Result = {ok,State,Data} +  | {ok,State,Data,Actions}  | {stop,Reason} | ignore - - CallbackMode = - callback_mode() - State = state() Data = data() @@ -1372,7 +1404,7 @@ handle_event(_, _, State, Data) -> start_link/3,4 or start/3,4, - this function is called by the new process to initialize + this optional function is called by the new process to initialize the implementation state and server data.

@@ -1381,11 +1413,8 @@ handle_event(_, _, State, Data) ->

If the initialization is successful, the function is to - return {CallbackMode,State,Data} or - {CallbackMode,State,Data,Actions}. - CallbackMode selects the - callback mode - of the gen_statem. + return {ok,State,Data} or + {ok,State,Data,Actions}. State is the initial state() and Data the initial server @@ -1408,6 +1437,16 @@ handle_event(_, _, State, Data) -> erlang:throw/1 to return Result.

+ +

+ This callback is optional, so a callback module does not need + to export it, but most do. If this function is not exported, + the gen_statem should be started through + proc_lib + and + enter_loop/4-6. +

+
-- cgit v1.2.3