gen_statem模块¶
@todo [1]
design_principles¶
事件驱动状态机:
State(S) x Event(E) -> Actions(A), State(S')
在状态S时,发生事件E => 执行A事件,并把状态改为S'
实例:
1-module(code_lock).
2-behaviour(gen_statem).
3-define(NAME, code_lock).
4
5-export([start_link/1]).
6-export([button/1]).
7-export([init/1,callback_mode/0,terminate/3]).
8-export([locked/3,open/3]).
9
10start_link(Code) ->
11 gen_statem:start_link({local,?NAME}, ?MODULE, Code, []).
12
13button(Button) ->
14 gen_statem:cast(?NAME, {button,Button}).
15
16init(Code) ->
17 do_lock(),
18 Data = #{code => Code, length => length(Code), buttons => []},
19 {ok, locked, Data}.
20
21callback_mode() ->
22 state_functions.
23
24locked(cast, {button,Button}, #{code := Code, length := Length, buttons := Buttons} = Data) ->
25 NewButtons =
26 if
27 length(Buttons) < Length ->
28 Buttons;
29 true ->
30 tl(Buttons)
31 end ++ [Button],
32 if
33 NewButtons =:= Code -> % Correct
34 do_unlock(),
35 {next_state, open, Data#{buttons := []}, [{state_timeout,10000,lock}]}; % Time in milliseconds
36 true -> % Incomplete | Incorrect
37 {next_state, locked, Data#{buttons := NewButtons}}
38 end.
39
40open(state_timeout, lock, Data) ->
41 do_lock(),
42 {next_state, locked, Data};
43open(cast, {button,_}, Data) ->
44 {next_state, open, Data}.
45
46do_lock() ->
47 io:format("Lock~n", []).
48do_unlock() ->
49 io:format("Unlock~n", []).
50
51terminate(_Reason, State, _Data) ->
52 State =/= locked andalso do_lock(),
53 ok.
什么时候用:
1.无论事件类型(call, cast, info),每个state共用回一回调代码.
Co-located callback code for each state, regardless of Event Type (such as call, cast and info)
2.延迟事件(替代选择性receive)
Postponing Events (a substitute for selective receive)
3.插入事件:从状态机到自身的事件(特别是纯内部事件)
Inserted Events that is: events from the state machine to itself (in particular purely internal events)
4.State Enter Calls(state的回调入口与其他states的回调代码共用)
State Enter Calls (callback on state entry co-located with the rest of each state's callback code)
5.超时使用简单(状态超时,事件超时,通用超时)
Easy-to-use timeouts (State Time-Outs, Event Time-Outs and Generic Time-outs (named time-outs))