Warning: strpos() [function.strpos]: Empty needle in /home/dealer/kasat/pkg/cahir/web/html/lib/plugins/translation2/action.php on line 53

Warning: Cannot modify header information - headers already sent by (output started at /home/dealer/kasat/pkg/cahir/web/html/lib/plugins/translation2/action.php:53) in /home/dealer/kasat/pkg/cahir/web/html/inc/actions.php on line 163
erlang:otp-fsm [Krystian Bacławski Wiki]
 

Szablon uogólnionej maszyny stanów

Opis działania

Zachowanie gen_fsm służy do implementacji procesu zachowującego się jak skończona maszyna stanów tzn. implementuje pewną akcję przejścia:

transition(State, Event) -> State'

gdzie State = {StateName,StateData}. Akcja przejścia jest zaimplementowana jako zestaw funkcji o nazwie StateName przyjmujących za parametr nazwę zdarzenia.

Na wypadek gdybyśmy pewne zdarzenia chcieli interpretować niezależnie od stanu, nasza maszyna stanów może go ignorować przy wykonywaniu akcji przejścia.

transition(Event) -> State'

Wysłanie zdarzenia do maszyny stanów może być asynchroniczne lub synchroniczne. W drugim przypadku proces wysyłający dostanie od skończonej maszyny stanów komunikat z odpowiedzią.

Część uniwersalna

Startowanie

gen_fsm:start(Module, Args, Options) -> Result
gen_fsm:start(FsmName, Module, Args, Options) -> Result
 
gen_fsm:start_link(Module, Args, Options) -> Result
gen_fsm:start_link(FsmName, Module, Args, Options) -> Result

Zachowanie powyższych funkcji jest identyczne jak w gen_server.

Powiadamianie o zdarzeniach

Wersje z all_state wysyłają komunikat, który będzie obsłużony przez funkcje ignorujące stan.

Asynchroniczne

gen_fsm:send_event(FsmRef, Event) -> ok
gen_fsm:send_all_state_event(FsmRef, Event) -> ok

Synchroniczne

gen_fsm:sync_send_event(FsmRef, Event, Timeout) -> Reply
gen_fsm:sync_send_all_state_event(FsmRef, Event, Timeout) -> Reply

Limity czasowe

Wewnątrz procesu skończonej maszyny stanów można implementować posługiwać się alarmem.

gen_fsm:send_event_after(Time, Event) -> Ref

Startuje alarm, który po upłynięciu czasu dostarczy zdarzenie Event do funkcji Module:StateName/2.

gen_fsm:start_timer(Time, Msg) -> Ref

Startuje alarm, który po upłynięciu czasu dostarczy zdarzenie {timeout, Ref, Msg} do funkcji Module:StateName/2.

gen_fsm:cancel_timer(Ref) -> RemainingTime | false

Przerywa odliczanie czasu i zwalnia alarm.

Wysyłanie odpowiedzi

gen_fsm:reply(Caller, Reply)

Służy do ręcznego odsyłania odpowiedzi do procesu wywołującego.

Funkcje zwrotne

Wynik

Znaczenie pól w krotce wyniku:

  • StateName jest atomem wyrażającym nazwę stanu naszej maszyny. Jeśli nasz proces znajduje się w stanie StateName i przychodzi do niego komunikat, to wołana jest funkcja o identycznej nazwie z modułu procesu;
  • StateData jest dowolnym wyrażeniem reprezentującym stan wewnętrzny naszego automatu;
  • atom hibernate to proces będzie czekał na następny komunikat będąc zamrożonym;
  • wartość Timeout to proces po odczekaniu odpowiedniej ilości milisekund wyśle do Module:StateName/2 komunikat timeout.

Dla wywołań synchronicznych

{reply,Reply,NextStateName,NewStateData}
{reply,Reply,NextStateName,NewStateData,Timeout}
{reply,Reply,NextStateName,NewStateData,hibernate}
{stop,Reason,Reply,NewStateData}

Oznaczają, że nasz proces:

  • odeśle komunikat Reply do wysyłającego,
  • dla reply:
    • przejdzie do stanu NextStateName,
  • zmieni stan wewnętrzny na NewStateData,
  • dla stop:
    • wywoła funkcję terminate/3 z powodem zakończenia Reason.

Dla wywołań asynchronicznych

{next_state,NextStateName,NewStateData}
{next_state,NextStateName,NewStateData,Timeout}
{next_state,NextStateName,NewStateData,hibernate}
{stop,Reason,NewStateData}

Oznaczają, że nasz proces:

  • dla next_state:
    • przejdzie do stanu NextStateName,
  • zmieni stan wewnętrzny na NewStateData.
  • dla stop:
    • wywoła funkcję terminate/3 z powodem zakończenia Reason.

Inicjalizacja i kończenie

Module:init(Args) -> Result
Module:terminate(Reason, StateName, StateData)
 
Return =
  {ok,StateName,StateData} |
  {ok,StateName,StateData,Timeout} |
  {ok,StateName,StateData,hibernate} |
  {stop,Reason} |
  ignore

Obsługa zdarzeń

Synchroniczne

Module:StateName(Event, From, StateData) -> Result

Obsługuje komunikat wysłany przy pomocy funkcji gen_fsm:sync_send_event/2 i gen_fsm:sync_send_event/3.

Module:handle_sync_event(Event, From, StateName, StateData) -> Result

Obsługuje komunikat wysłany przy pomocy funkcji gen_fsm:sync_send_all_state_event/2 i gen_fsm:sync_send_all_state_event/3.

Funkcja musi zatroszczyć się odesłaniem komunikatu z odpowiedzią (przy pomocy gen_fsm:reply/2), jeżeli zwraca wynik dla wywołań asynchronicznych.

Asynchroniczne

Module:StateName(Event, StateData) -> Result

Obsługuje komunikat wysłany przy pomocy funkcji gen_fsm:send_event/2.

Module:handle_event(Event, StateName, StateData) -> Result

Obsługuje komunikat wysłany przy pomocy funkcji gen_fsm:send_all_state_event/2.

Obsługa pozostałych komunikatów

Module:handle_info(Info, StateName, StateData) -> Result

Wymiana kodu

Module:code_change(OldVsn, StateName, StateData, Extra) -> {ok, NextStateName, NewStateData}

Przykład

Maszyna stanów implementująca drzwi z zamkiem kodowym

 1: -module(code_lock).
 2: -behaviour(gen_fsm).
 3: -export([start_link/1]).
 4: -export([button/1]).
 5: -export([init/1, locked/2, open/2, stop/0]).
 6: -export([handle_event/3, handle_sync_event/4, handle_info/3, code_change/4, terminate/3]).
 7:
 8: start_link(Code) ->
 9:   gen_fsm:start_link({local, code_lock}, code_lock, Code, []).
10:
11: stop() ->
12:   gen_fsm:send_all_state_event(code_lock, stop).
13:
14: button(Digit) ->
15:   gen_fsm:send_event(code_lock, {button, Digit}).
16:
17: init(Code) ->
18:   {ok, locked, {[], Code}}.
19:
20: locked({button, Digit}, {SoFar, Code}) ->
21:   case [Digit|SoFar] of
22:     Code ->
23:       do_unlock(),
24:       {next_state, open, {[], Code}, 30000};
25:     Incomplete when length(Incomplete)<length(Code) ->
26:       {next_state, locked, {Incomplete, Code}};
27:     _Wrong ->
28:       {next_state, locked, {[], Code}}
29:   end.
30:
31: open(timeout, State) ->
32:   do_lock(),
33:   {next_state, locked, State}.
34:
35: do_lock() ->
36:   io:format("Door locked~n").
37:
38: do_unlock() ->
39:   io:format("Door unlocked~n").
40:
41: handle_event(stop, _StateName, StateData) ->
42:   {stop, normal, StateData}.
43:
44: handle_sync_event(Event, _From, StateName, StateData) ->
45:   {reply, Event, StateName, StateData}.
46:
47: handle_info(_Info, StateName, StateData) ->
48:   {next_state, StateName, StateData}.
49:
50: code_change(_OldVsn, StateName, StateData, _Extra) ->
51:   {ok, StateName, StateData}.
52:
53: terminate(_Reason, _StateName, _StateData) ->
54:   ok.

Źródła

Podręczniki:

Moduły:

 
erlang/otp-fsm.txt · Last modified: 2010/05/07 17:50 by Krystian Baclawski
 
Except where otherwise noted, content on this wiki is licensed under the following license:CC Attribution-Noncommercial-No Derivative Works 3.0 Unported
Recent changes RSS feed Donate Powered by PHP Valid XHTML 1.0 Valid CSS Driven by DokuWiki