From b2a68e1e20b9ae41490e5d2777ed5c4f1147b26b Mon Sep 17 00:00:00 2001 From: Raimo Niskanen Date: Thu, 12 Apr 2018 11:01:55 +0200 Subject: Add a 'When to use' section --- system/doc/design_principles/statem.xml | 107 ++++++++++++++++++++++++++------ 1 file changed, 89 insertions(+), 18 deletions(-) (limited to 'system/doc/design_principles') diff --git a/system/doc/design_principles/statem.xml b/system/doc/design_principles/statem.xml index b44e169a9a..c44f240098 100644 --- a/system/doc/design_principles/statem.xml +++ b/system/doc/design_principles/statem.xml @@ -82,6 +82,69 @@ State(S) x Event(E) -> Actions(A), State(S')

+ + +
+ + When to use gen_statem +

+ If your process logic is convenient to describe as a state machine, + and you want any of these gen_statem key features: +

+ + + Gathered callback code for each state, + regardless of + Event Types. + (such as calls, casts and infos) + + + + Postponing Events + + (a substitute for selective receive) + + + + Inserted Events + + (in particular purely internal events) + + + + State Enter Calls + + (callback on state entry gathered with the rest + of the state callback code) + + + Higher level timeouts + ( + State Time-Outs, + Event Time-Outs + or + Generic Time-outs + (named time-outs)) + + +

+ If so, or if possibly needed in future versions, + then you should consider using gen_statem over + gen_server. +

+

+ For simple state machines not needing these fetures + gen_server + works just fine. + It also has got smaller call overhead, + but we are talking about something like 2 vs 3.3 microseconds + call roundtrip time here, so if the server callback + does just a little bit more than just replying, + or if the callback is not extremely frequent, + that difference will be hard to notice. +

+
+
@@ -160,7 +223,7 @@ State(S) x Event(E) -> Actions(A), State(S') function may also return a list containing the callback mode and the atom state_enter in which case - state enter calls + State Enter Calls are activated for the callback mode.

@@ -176,7 +239,7 @@ State(S) x Event(E) -> Actions(A), State(S')

The two - callback modes + Callback Modes give different possibilities and restrictions, but one goal remains: you want to handle all possible combinations of @@ -221,6 +284,8 @@ State(S) x Event(E) -> Actions(A), State(S')

The mode enables the use of non-atom states, for example, complex states or even hierarchical states. + See section + Complex State. If, for example, a state diagram is largely alike for the client side and the server side of a protocol, you can have a state {StateName,server} or @@ -344,7 +409,10 @@ State(S) x Event(E) -> Actions(A), State(S')

Same as the keep_state or keep_state_and_data values, - and if state enter calls + and if + + State Enter Calls + are enabled, repeat that call.

@@ -379,7 +447,7 @@ State(S) x Event(E) -> Actions(A), State(S') Module:init(Args) callback function is called before any - event handler + Event Handler is called. This function behaves like an event handler function, but gets its only argument Args from the gen_statem @@ -407,8 +475,10 @@ State(S) x Event(E) -> Actions(A), State(S') State Transition Actions

- In the first - section + In the first section + + Event-Driven State Machines + actions were mentioned as a part of the general state machine model. These general actions are implemented with the code that callback module @@ -644,7 +714,7 @@ StateName(EventType, EventContent, Data) ->

Since the state enter call is not an event there are restrictions on the allowed return value and - state transition actions. + State Transition Actions. You may not change the state, postpone this non-event, or @@ -657,7 +727,7 @@ StateName(EventType, EventContent, Data) ->

You may repeat the state enter call using the {repeat_state,...} return value from the - event handler. + Event Handler. In this case OldState will also be equal to the current state.

@@ -1301,8 +1371,8 @@ open(cast, {button,_}, Data) -> ... ]]>

- An specific generic time-out can just as a - state time-out + Specific generic time-outs can just as + State Time-Outs be restarted or cancelled by setting it to a new time or infinity.

@@ -1397,7 +1467,7 @@ open(cast, {button,_}, Data) ->

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

@@ -1422,7 +1492,7 @@ open(cast, {button,_}, Data) -> (see section Complex State) with - callback mode + Callback Mode handle_event_function. If a change in the value changes the set of events that is handled, then the value should be kept in the State. @@ -1527,8 +1597,8 @@ do_unlock() ->

The - - state transition action + + State Transition Action postpone is designed to model selective receives. A selective receive implicitly postpones @@ -1555,7 +1625,7 @@ do_unlock() -> (described in the next section), especially if just one or a few states has got state enter actions, this is a perfect use case for the built in - state enter calls. + State Enter Calls.

You return a list containing state_enter from your @@ -1617,7 +1687,7 @@ open(state_timeout, lock, Data) -> to your own state machine. This can be done with the - state transition action + State Transition Action {next_event,EventType,EventContent}.

@@ -1970,7 +2040,7 @@ format_status(Opt, [_PDict,State,Data]) ->

One reason to use this is when you have a state item that when changed should cancel the - state time-out, + State Time-Out, or one that affects the event handling in combination with postponing events. We will go for the latter and complicate the previous example @@ -2160,7 +2230,8 @@ handle_event(enter, _OldState, {open,_}, _Data) -> {open,_} state, which would clutter the code.

- Another not uncommon scenario is to use the event time-out + Another not uncommon scenario is to use the + Event Time-Out to trigger hibernation after a certain time of inactivity. There is also a server start option -- cgit v1.2.3