1gen_fsm(3) Erlang Module Definition gen_fsm(3)
2
3
4
6 gen_fsm - Deprecated and replaced by gen_statem
7
9 Deprecated and replaced by gen_statem
10
12 Here follows a simple example of turning a gen_fsm into a gen_statem.
13 The example comes from the previous Users Guide for gen_fsm
14
15 -module(code_lock).
16 -define(NAME, code_lock).
17 %-define(BEFORE_REWRITE, true).
18
19 -ifdef(BEFORE_REWRITE).
20 -behaviour(gen_fsm).
21 -else.
22 -behaviour(gen_statem).
23 -endif.
24
25 -export([start_link/1, button/1, stop/0]).
26
27 -ifdef(BEFORE_REWRITE).
28 -export([init/1, locked/2, open/2, handle_sync_event/4, handle_event/3,
29 handle_info/3, terminate/3, code_change/4]).
30 -else.
31 -export([init/1, callback_mode/0, locked/3, open/3, terminate/3, code_change/4]).
32 %% Add callback__mode/0
33 %% Change arity of the state functions
34 %% Remove handle_info/3
35 -endif.
36
37 -ifdef(BEFORE_REWRITE).
38 start_link(Code) ->
39 gen_fsm:start_link({local, ?NAME}, ?MODULE, Code, []).
40 -else.
41 start_link(Code) ->
42 gen_statem:start_link({local,?NAME}, ?MODULE, Code, []).
43 -endif.
44
45 -ifdef(BEFORE_REWRITE).
46 button(Digit) ->
47 gen_fsm:send_event(?NAME, {button, Digit}).
48 -else.
49 button(Digit) ->
50 gen_statem:cast(?NAME, {button,Digit}).
51 %% send_event is asynchronous and becomes a cast
52 -endif.
53
54 -ifdef(BEFORE_REWRITE).
55 stop() ->
56 gen_fsm:sync_send_all_state_event(?NAME, stop).
57 -else.
58 stop() ->
59 gen_statem:call(?NAME, stop).
60 %% sync_send is synchronous and becomes call
61 %% all_state is handled by callback code in gen_statem
62 -endif.
63
64 init(Code) ->
65 do_lock(),
66 Data = #{code => Code, remaining => Code},
67 {ok, locked, Data}.
68
69 -ifdef(BEFORE_REWRITE).
70 -else.
71 callback_mode() ->
72 state_functions.
73 %% state_functions mode is the mode most similar to
74 %% gen_fsm. There is also handle_event mode which is
75 %% a fairly different concept.
76 -endif.
77
78 -ifdef(BEFORE_REWRITE).
79 locked({button, Digit}, Data0) ->
80 case analyze_lock(Digit, Data0) of
81 {open = StateName, Data} ->
82 {next_state, StateName, Data, 10000};
83 {StateName, Data} ->
84 {next_state, StateName, Data}
85 end.
86 -else.
87 locked(cast, {button,Digit}, Data0) ->
88 case analyze_lock(Digit, Data0) of
89 {open = StateName, Data} ->
90 {next_state, StateName, Data, 10000};
91 {StateName, Data} ->
92 {next_state, StateName, Data}
93 end;
94 locked({call, From}, Msg, Data) ->
95 handle_call(From, Msg, Data);
96 locked({info, Msg}, StateName, Data) ->
97 handle_info(Msg, StateName, Data).
98 %% Arity differs
99 %% All state events are dispatched to handle_call and handle_info help
100 %% functions. If you want to handle a call or cast event specifically
101 %% for this state you would add a special clause for it above.
102 -endif.
103
104 -ifdef(BEFORE_REWRITE).
105 open(timeout, State) ->
106 do_lock(),
107 {next_state, locked, State};
108 open({button,_}, Data) ->
109 {next_state, locked, Data}.
110 -else.
111 open(timeout, _, Data) ->
112 do_lock(),
113 {next_state, locked, Data};
114 open(cast, {button,_}, Data) ->
115 {next_state, locked, Data};
116 open({call, From}, Msg, Data) ->
117 handle_call(From, Msg, Data);
118 open(info, Msg, Data) ->
119 handle_info(Msg, open, Data).
120 %% Arity differs
121 %% All state events are dispatched to handle_call and handle_info help
122 %% functions. If you want to handle a call or cast event specifically
123 %% for this state you would add a special clause for it above.
124 -endif.
125
126 -ifdef(BEFORE_REWRITE).
127 handle_sync_event(stop, _From, _StateName, Data) ->
128 {stop, normal, ok, Data}.
129
130 handle_event(Event, StateName, Data) ->
131 {stop, {shutdown, {unexpected, Event, StateName}}, Data}.
132
133 handle_info(Info, StateName, Data) ->
134 {stop, {shutdown, {unexpected, Info, StateName}}, StateName, Data}.
135 -else.
136 -endif.
137
138 terminate(_Reason, State, _Data) ->
139 State =/= locked andalso do_lock(),
140 ok.
141 code_change(_Vsn, State, Data, _Extra) ->
142 {ok, State, Data}.
143
144 %% Internal functions
145 -ifdef(BEFORE_REWRITE).
146 -else.
147 handle_call(From, stop, Data) ->
148 {stop_and_reply, normal, {reply, From, ok}, Data}.
149
150 handle_info(Info, StateName, Data) ->
151 {stop, {shutdown, {unexpected, Info, StateName}}, StateName, Data}.
152 %% These are internal functions for handling all state events
153 %% and not behaviour callbacks as in gen_fsm
154 -endif.
155
156 analyze_lock(Digit, #{code := Code, remaining := Remaining} = Data) ->
157 case Remaining of
158 [Digit] ->
159 do_unlock(),
160 {open, Data#{remaining := Code}};
161 [Digit|Rest] -> % Incomplete
162 {locked, Data#{remaining := Rest}};
163 _Wrong ->
164 {locked, Data#{remaining := Code}}
165 end.
166
167 do_lock() ->
168 io:format("Lock~n", []).
169 do_unlock() ->
170 io:format("Unlock~n", []).
171
172
173
174
175Ericsson AB stdlib 3.8.2.1 gen_fsm(3)