OTP Design Principles: Gen_Fsm Behaviour

6496 단어 UP
자세히 보기
1, 제한된 상태기
FSM, FSM 은 다음과 같은 형식으로 관계 집합을 설명할 수 있습니다.

State(S) x Event(E) -> Actions(A), State(S')

만약에 우리가 상태 S에 있고 이벤트 E가 보내면 우리는 동작 A를 실행하고 상태를 S로 바꿔야 한다는 뜻이다.
2, 예
코드 자물쇠가 있는 문, 입력한 코드 순서가 맞다면 30초 동안 문을 열어라
입력 코드가 완전하지 않으면 다음 단추를 기다리고, 입력 코드의 순서가 틀리면 다시 대기 단추를 누르기 시작합니다

-module(code_lock).
-behaviour(gen_fsm).

-export([start_link/1]).
-export([button/1]).
-export([init/1, locked/2, open/2]).

start_link(Code) ->
  gen_fsm:start_link({local, code_lock}, code_lock, Code, []).

button(Digit) ->
  gen_fsm:send_event(code_lock, {button, Digit}).

init(Code) ->
  {ok, locked, {[], Code}}.

locked({button, Digit}, {SoFar, Code}) ->
  case [Digit|SoFar] of
    Code ->
      do_unlock(),
      {next_state, open, {[], Code}, 3000};
      Incomplete when length(Incomplete) < length(Code) ->
        {next_state, locked, {Incomplete, Code}};
      _Wrong ->
        {next)state, locked, {[], Code}};
  end.

open(timeout, State) ->
  do_lock(),
  {next_state, locked, State}.

3, Gen 시작Fsm
위의 예에서 코드 사용lock:start_링크 시작genfsm:

start_link(Code) ->
  gen_fsm:start_link({locak, code_lock}, code_lock, Code, []).

start_link 호출genfsm:start_link/4, 새gen 시작fsm 프로세스 및 연결
1) 첫 번째 매개변수 {local, code lock} 이름을 지정하고 로컬에서 code 로 등록lock
2) 두 번째 매개변수 codelock 실행 콜백 모듈
3) 세 번째 매개 변수 코드는 콜백 메소드 init에 전달되는 매개 변수이며, 여기서 init 메소드에서 정확한 코드 잠금을 획득한 코드
4) 네 번째 채택수 []는 options
프로세스 등록이 성공하면 새genfsm 프로세스 호출 콜백 방법 codelock: init(Code), 반환 {ok, StateName, StateData}
StateName은gen 입니다.fsm의 초기 상태, 여기서 되돌아오는 것은locked입니다. 초기 상태에서 문이 잠겨 있음을 나타냅니다.
StateData는 gen 입니다.fsm의 내부 상태입니다.state 데이터는 현재 단추 순서 (처음에는 비어 있음) 와 정확한 잠금 코드입니다.

init(Code) ->
  {ok, locked, {[], Code}}.

주의genfsm:start_link는gen 까지 동기화됨fsm 프로세스가 초기화되고 요청을 받을 준비가 되었을 때 되돌아옵니다
gen_fsm:start_link는 Supervisor,genfsm:start는 단독gen 을 시작합니다fsm 프로세스
4, 이벤트 알림
gen 사용fsm:send_이벤트/2로 단추 이벤트 알림:

button(Digit) ->
  gen_fsm:send_event(code_lock, {button, Digit}).

code_lock은genfsm 프로세스의 이름, {button, Digit}은 실제 이벤트입니다.
이벤트는gen 에게 메시지로 전송됩니다fsm 프로세스, 이벤트 수신 후,genfsm에서 StateName(Event, StateData)을 호출하고 {next state, StateName1, StateData1} 반환
StateName은 현재 상태의 이름이고, StateName1은 다음 상태가 될 상태의 이름이며, StateData1은gen 입니다.fsm의 새 state data 값:

locked({button, Digit}, {SoFar, Code}) ->
  case [Digit|SoFar] of
    Code ->
      do_unlock(),
      {next_state, open, {[], Code}, 3000};
    Incomplete when length(Incomplete) < length(Code) ->
      {next_state, locked, {Incomplete, Code}};
    _Wrong ->
      {next_state, locked, {[], Code}};
  end.

open(timeout, State) ->
  do_lock(),
  {next_state, locked, State}.

만약 문이 잠겨 있다면, 이때 단추를 누르면 현재 단추의 순서와 정확한 코드 순서를 비교하고, 비교 결과에 따라 unlock문인지 계속locked인지 결정한다
5, 시간 초과
올바른 버튼 순서를 입력하면 문unlock이 다음과 같은 tuple로 돌아갑니다.

{next_state, open, {[], Code}, 30000};

30000은 시간 초과가 30000밀리초이고 30000밀리초 이후에 시간 초과가 발생하면 StateName(timeout, StateData)을 호출합니다.
여기서 문을 30초 동안 열고 다시 잠그세요.

open(timeout, State) ->
  do_lock(),
  {next_state, locked, State}.

6, 모든 상태 이벤트
때로는 한 사건이gen 에 도달할 수 있다fsm 프로세스의 모든 상태입니다. 이 메시지는gen 을 사용할 수 있습니다.fsm:send_all_state_이벤트/2로 메시지를 보내고 Module:handle이벤트/3 처리

-module(code_lock).
...
-export([stop/0]).
...

stop() ->
  gen_fsm:send_all_state_event(code_lock, stop).
...

handle_event(stop, _StateName, StateData) ->
  {stop, normal, StateData}.

7, 중지
7.1 Supervision Tree에서
하면, 만약, 만약...fsm는 Supervision tree에서 stop 방법이 필요 없음,genfsm가 자동으로 슈퍼바이저에 의해 정지됨
종료하기 전에 데이터를 정리해야 한다면 shutdown strategy는timeout이고gen 이어야 합니다fsm의 init 방법에서 exit 신호를 포획하고
gen_fsm 프로세스는 콜백 방법terminate(shutdown, StateName, StateData)를 호출합니다.

init(Args) ->
  ...,
  process_flag(trap_exit, true),
  ...,
  {ok, Statename, StateData}.
...
terminate(shutdown, StateName, StateData} ->
  ..code for cleaning up here..
  ok.

7.2 단독 GenFsms 프로세스
하면, 만약, 만약...fsm 프로세스에 supervisor가 없으면 stop 메서드가 필요합니다.

...
-export([stop/0]).
...

stop() ->
  gen_fsm:send_all_state_event(code_lock, stop).
...

handle_event(stop, _StateName, StateData) ->
  {stop, normal, StateData}.
...

terminate(normal, _StateName, _StateData) ->
  ok.

callback 방법은 stop 이벤트를 처리하고 {stop,normal,StateData1}로 되돌려줍니다.normal은 정상 정지를 표시하고 StateData1은gen 입니다fsm의 새 데이터 값
이로 인해genfsm에서terminate(normal,StateName,StateData1)를 호출하고 우아하게 멈추기
8, 기타 메시지 처리
기타 메시지 처리 콜백 방법은handlinfo(Info, StateName, StateData), 예를 들어 다른 비supervisor 프로세스에 연결하고 exit 신호를 포착할 때 exit 메시지를 처리하는 경우:

handle_info({'EXIT', Pid, Reason}, StateName, StateData) ->
  ..code to handle exits here..
  {next_state, StateName1, StateData1}.

보충:genfsm exports and callbacks

gen_fsm module                          Callback module
gen_fsm:start_link -------------------> Module:init/1
gen_fsm:start
gen_fsm:send_event -------------------> Module:StateName/2
gen_fsm:send_all_state_event ---------> Module:handle_event/3
gen_fsm:sync_send_event --------------> Module:StateName/3
gen_fsm:sync_send_all_state_event ----> Module:handle_sync_event/4
gen_fsm:reply
gen_fsm:send_event_after
gen_fsm:start_timer
gen_fsm:cancel_timer
gen_fsm:enter_loop
                                        Module:handle_info/3
                                        Module:terminate/3
                                        Module:code_change/4

좋은 웹페이지 즐겨찾기