Erlang/OTP Finite State Machine behaviour
Одним из паттернов поведений приложений в платформе OTP является паттерн поведения детерминированного конечного автомата (gen_fsm). Как и в случае с паттерном поведения сервера (gen_server), необходимо реализовать модуль, содержащий обратные вызовы. Среди обратных вызовов можно выделить init, terminate, которые вызываются во время инициализации и завершения процесса соответственно и функции имеющие вид StateName(Event, StateData). Последний тип функций описывает состояние автомата с именем StateName. В модуле должно присутствовать по одной функции такого вида на каждое состояние. Рассмотрим пример приложения, имеющего 4 состояния.
-module(testotp_fsm).
-behaviour(gen_fsm).
-export([init/1,beg_state/2,
mid_state1/2,mid_state2/2,end_state/2,terminate/3]).
init(Args) ->
{ok,beg_state,infinity}.
beg_state(go_mid_one,_) ->
io:format("Going to middle state 1~n",[]),
{next_state,mid_state1,"data"};
beg_state(go_mid_two,_) ->
io:format("Going to middle state 2~n",[]),
{next_state,mid_state2,"data"};
beg_state(_,_) ->
io:format("Unknown event!~n",[]),
{next_state,mid_state2,"data"}.
mid_state1(go_last,_) ->
io:format("Going to the last state from middle state 1~n",[]),
{next_state,end_state,"data"};
mid_state1(_,_) ->
io:format("Unknown event!~n",[]),
{next_state,mid_state1,"data"}.
mid_state2(go_last,_) ->
io:format("Goint to the last state from middle state 2~n",[]),
{next_state,end_state,"data"};
mid_state2(_,_) ->
io:format("Unknown event!~n",[]),
{next_state,mid_state2,"data"}.
end_state(finish,_) ->
io:format("This is the third state~n",[]),
{stop,normal,ok,"data"};
end_state(_,_) ->
io:format("Unknown event!~n",[]),
{next_state,end_state,"data"}.
terminate(_,_,_) ->
io:format("Terminated.~n",[]).
Запустим приложение и походим между состояниями.
> {ok,FSMPid} = gen_fsm:start_link(testotp_fsm,any,[any]).
> gen_fsm:send_event(FSMPid,go_mid_two).
Going to middle state 2
ok
> gen_fsm:send_event(FSMPid,go_last).
Goint to the last state from middle state 2
ok
> gen_fsm:send_event(FSMPid,fin).
Unknown event!
ok
> gen_fsm:send_event(FSMPid,finish).
This is the third state
ok
Terminated.
That’s it! Паттерны поведений сильно упрощают код и делают его совместимым с деревьями контроля OTP. Удачи!

