From d86fd35ca0c65069955a34d6ae9fbc33b9663eb0 Mon Sep 17 00:00:00 2001 From: Raimo Niskanen Date: Tue, 20 Mar 2018 03:34:23 -0700 Subject: Update User's Guide and pointers to it --- lib/stdlib/doc/src/gen_statem.xml | 89 +++++++++++++++++++++++++++------------ 1 file changed, 62 insertions(+), 27 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 be0d64feba..252a8370ad 100644 --- a/lib/stdlib/doc/src/gen_statem.xml +++ b/lib/stdlib/doc/src/gen_statem.xml @@ -32,39 +32,43 @@ Generic state machine behavior.

- This behavior module provides a state machine. Two - callback modes - are supported: + gen_statem provides a generic state machine behaviour + and replaces its predecessor + gen_fsm + since Erlang/OTP 20.0. +

+

+ This reference manual describes types generated from the types + in the gen_statem source code, so they are correct. + However, the generated descriptions also reflect the type hiearchy, + which makes them kind of hard to read. +

+

+ To get an overview of the concepts and operation of gen_statem, + do read the + User's Guide. + It frequently links back to this reference manual to avoid containing + detailed facts that may rot by age.

- - -

One for finite-state machines - (gen_fsm like), - which requires the state to be an atom and uses that state as - the name of the current callback function -

-
- -

One without restriction on the state data type - that uses one callback function for all states -

-
-

- This is a new behavior in Erlang/OTP 19.0. - It has been thoroughly reviewed, is stable enough - to be used by at least two heavy OTP applications, - and is here to stay. - Depending on user feedback, we do not expect - but can find it necessary to make minor - not backward compatible changes into Erlang/OTP 20.0. + This behavior appeared in Erlang/OTP 19.0. + In OTP 19.1 a backwards incompatible change of + the return tuple from + Module:init/1 + was made and the mandatory callback function + + Module:callback_mode/0 + + was introduced. In OTP 20.0 the + generic timeouts + were added.

- The gen_statem behavior replaces - gen_fsm in Erlang/OTP 20.0. - It has the same features and adds some really useful: + gen_statem has got the same features that + gen_fsm + had and adds some really useful:

Gathered state code. @@ -78,6 +82,27 @@ Reply from other state than the request. Multiple sys traceable replies. + + +

+ Two + callback modes + are supported: +

+ + +

One for finite-state machines + (gen_fsm like), + which requires the state to be an atom and uses that state as + the name of the current callback function +

+
+ +

One without restriction on the state data type + that uses one callback function for all states +

+
+

The callback model(s) for gen_statem differs from the one for gen_fsm, @@ -252,6 +277,16 @@ erlang:'!' -----> Module:StateName/3 to use after every event; see erlang:hibernate/3.

+

+ There is also a server start option + + {hibernate_after, Timeout} + + for + start/3,4 or + start_link/3,4 + that may be used to automatically hibernate the server. +

-- cgit v1.2.3 From 3ed7d729cab697b9f668dadb563d629de10f593d Mon Sep 17 00:00:00 2001 From: Raimo Niskanen Date: Tue, 10 Apr 2018 10:50:41 +0200 Subject: Fix timeout parsing and doc feedback --- lib/stdlib/doc/src/gen_statem.xml | 134 +++++++++++++++++++++++++------------- 1 file changed, 88 insertions(+), 46 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 252a8370ad..fe391b329a 100644 --- a/lib/stdlib/doc/src/gen_statem.xml +++ b/lib/stdlib/doc/src/gen_statem.xml @@ -71,16 +71,18 @@ had and adds some really useful:

- Gathered state code. - Arbitrary term state. - Event postponing. - Self-generated events. - State time-out. - Multiple generic named time-outs. - Absolute time-out time. - Automatic state enter calls. - Reply from other state than the request. - Multiple sys traceable replies. + Gathered state code + Arbitrary term state + Event postponing + Self-generated events + State time-out + Multiple generic named time-outs + Absolute time-out time + Automatic state enter calls + + Reply from other state than the request, sys traceable + + Multiple sys traceable replies @@ -232,8 +234,10 @@ erlang:'!' -----> Module:StateName/3 whenever a new state is entered; see state_enter(). This is for writing code common to all state entries. - Another way to do it is to insert events at state transitions, - but you have to do so everywhere it is needed. + Another way to do it is to insert an event at the state transition, + and/or to use a dedicated state transition function, + but that is something you will have to remember + at every state transition to the state(s) that need it.

If you in gen_statem, for example, postpone @@ -703,9 +707,9 @@ handle_event(_, _, State, Data) ->

If Module:code_change/4 - should transform the state to a state with a different - name it is still regarded as the same state so this - does not cause a state enter call. + should transform the state, + it is regarded as a state rename and not a state change, + which will not cause a state enter call.

Note that a state enter call will be done @@ -723,12 +727,19 @@ handle_event(_, _, State, Data) ->

Transition options can be set by actions - and they modify how the state transition is done: + and modify the state transition. + Here are the sequence of steps for a state transition:

- If the state changes, is the initial state, + If + + state enter calls + + are used, and either: + the state changes, it is the initial state, + or one of the callback results repeat_state @@ -736,16 +747,21 @@ handle_event(_, _, State, Data) -> repeat_state_and_data - is used, and also - state enter calls - are used, the gen_statem calls + is used; the gen_statem calls the new state callback with arguments (enter, OldState, Data). +

+

Any actions returned from this call are handled as if they were - appended to the actions - returned by the state callback that changed states. + appended to the actions + returned by the state callback that caused the state entry. +

+

+ Should this state enter call return any of + the mentioned repeat_* callback results + it is repeated again, with the updated Data.

@@ -774,7 +790,7 @@ handle_event(_, _, State, Data) -> All events stored with action() next_event - are inserted to be processed before the other queued events. + are inserted to be processed before previously queued events.

@@ -788,7 +804,9 @@ handle_event(_, _, State, Data) -> delivered to the state machine before any external not yet received event so if there is such a time-out requested, the corresponding time-out zero event is enqueued as - the newest event. + the newest received event; + that is after already queued events + such as inserted and postponed events.

Any event cancels an @@ -826,7 +844,7 @@ handle_event(_, _, State, Data) -> When a new message arrives the state callback is called with the corresponding event, - and we start again from the top of this list. + and we start again from the top of this sequence.

@@ -851,13 +869,19 @@ handle_event(_, _, State, Data) -> 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 - that the gen_statem entered hibernation - and immediately got awakened by the oldest enqueued event.

+ +

+ If there are enqueued events to process + when hibrnation is requested, + this is optimized by not hibernating but instead calling + + erlang:garbage_collect/0 + + to simulate that the gen_statem entered hibernation + and immediately got awakened by an enqueued event. +

+
@@ -892,7 +916,7 @@ handle_event(_, _, State, Data) -> no timer is actually started, instead the the time-out event is enqueued to ensure that it gets processed before any not yet - received external event. + received external event, but after already queued events.

Note that it is not possible nor needed to cancel this time-out, @@ -978,7 +1002,9 @@ handle_event(_, _, State, Data) -> If Abs is true an absolute timer is started, and if it is false a relative, which is the default. See - erlang:start_timer/4 + + erlang:start_timer/4 + for details.

@@ -1004,7 +1030,9 @@ 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 @@ -1016,7 +1044,9 @@ handle_event(_, _, State, Data) ->

Sets the - transition_option() + + transition_option() + postpone() for this state transition. This action is ignored when returned from @@ -1029,7 +1059,11 @@ handle_event(_, _, State, Data) -> next_event

- Stores the specified EventType + This action does not set any + + transition_option() + + but instead stores the specified EventType and EventContent for insertion after all actions have been executed.

@@ -1101,15 +1135,15 @@ handle_event(_, _, State, Data) -> transition options.

- Timeout + Time

- Short for {timeout,Timeout,Timeout}, that is, + Short for {timeout,Time,Time}, that is, the time-out message is the time-out time. This form exists to make the state callback - return value {next_state,NextState,NewData,Timeout} - allowed like for gen_fsm's + return value {next_state,NextState,NewData,Time} + allowed like for gen_fsm.

timeout @@ -1161,7 +1195,11 @@ handle_event(_, _, State, Data) -> enter_loop/5,6.

- It replies to a caller waiting for a reply in + It does not set any + + transition_option() + + but instead replies to a caller waiting for a reply in call/2. From must be the term from argument {call,From} @@ -2144,16 +2182,20 @@ init(Args) -> erlang:error(not_implemented, [Args]). You may also not change states from this call. Should you return {next_state,NextState, ...} with NextState =/= State the gen_statem crashes. - It is possible to use {repeat_state, ...}, - {repeat_state_and_data,_} or - repeat_state_and_data but all of them makes little + Note that it is actually allowed to use + {repeat_state, NewData, ...} although it makes little sense since you immediately will be called again with a new state enter call making this just a weird way of looping, and there are better ways to loop in Erlang. + If you do not update NewData and have some + loop termination condition, or if you use + {repeat_state_and_data, _} or + repeat_state_and_data you have an infinite loop! You are advised to use {keep_state,...}, {keep_state_and_data,_} or - keep_state_and_data since you can not change states - from a state enter call anyway. + keep_state_and_data + since changing states from a state enter call + is not possible anyway.

Note the fact that you can use -- cgit v1.2.3 From 549f6b20ef9c881d8c186739207be69cd8d2f7f7 Mon Sep 17 00:00:00 2001 From: Raimo Niskanen Date: Mon, 16 Apr 2018 11:07:04 +0200 Subject: Fix after feedback on 'When to use' --- lib/stdlib/doc/src/gen_statem.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 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 fe391b329a..28ea3fa00b 100644 --- a/lib/stdlib/doc/src/gen_statem.xml +++ b/lib/stdlib/doc/src/gen_statem.xml @@ -71,7 +71,7 @@ had and adds some really useful:

- Gathered state code + Co-located state code Arbitrary term state Event postponing Self-generated events @@ -175,7 +175,7 @@ erlang:'!' -----> Module:StateName/3 is state_functions, the state must be an atom and is used as the state callback name; see Module:StateName/3. - This gathers all code for a specific state + This co-locates all code for a specific state in one function as the gen_statem engine branches depending on state name. Note the fact that the callback function -- cgit v1.2.3 From bf573371185de2c52e8b6ff46bff30f6d7d9f3c4 Mon Sep 17 00:00:00 2001 From: Raimo Niskanen Date: Wed, 18 Apr 2018 10:06:19 +0200 Subject: Improve pointer to User's Guide --- lib/stdlib/doc/src/gen_statem.xml | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 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 28ea3fa00b..e918e83df7 100644 --- a/lib/stdlib/doc/src/gen_statem.xml +++ b/lib/stdlib/doc/src/gen_statem.xml @@ -34,7 +34,7 @@

gen_statem provides a generic state machine behaviour and replaces its predecessor - gen_fsm + gen_fsm since Erlang/OTP 20.0.

@@ -46,9 +46,15 @@

To get an overview of the concepts and operation of gen_statem, do read the - User's Guide. - It frequently links back to this reference manual to avoid containing - detailed facts that may rot by age. + + gen_statem Behaviour + + in + + OTP Design Principles + + which frequently links back to this reference manual to avoid + containing detailed facts that may rot by age.

@@ -67,7 +73,7 @@

gen_statem has got the same features that - gen_fsm + gen_fsm had and adds some really useful:

@@ -749,11 +755,11 @@ handle_event(_, _, State, Data) -> is used; the gen_statem calls the new state callback with arguments - (enter, OldState, Data). + (enter, OldState, Data).

Any - actions + actions returned from this call are handled as if they were appended to the actions returned by the state callback that caused the state entry. -- cgit v1.2.3