檢視原始碼 gen_fsm 行為 (stdlib v6.2)
已棄用,並在 OTP 20 中被 gen_statem
取代。
遷移至 gen_statem
以下是一個將 gen_fsm 轉換為 gen_statem
的簡單範例。此範例來自先前 gen_fsm 的使用者指南。
-module(code_lock).
-define(NAME, code_lock).
%-define(BEFORE_REWRITE, true).
-ifdef(BEFORE_REWRITE).
-behaviour(gen_fsm).
-else.
-behaviour(gen_statem).
-endif.
-export([start_link/1, button/1, stop/0]).
-ifdef(BEFORE_REWRITE).
-export([init/1, locked/2, open/2, handle_sync_event/4, handle_event/3,
handle_info/3, terminate/3, code_change/4]).
-else.
-export([init/1, callback_mode/0, locked/3, open/3,
terminate/3, code_change/4]).
%% Add callback__mode/0
%% Change arity of the state functions
%% Remove handle_info/3
-endif.
-ifdef(BEFORE_REWRITE).
start_link(Code) ->
gen_fsm:start_link({local, ?NAME}, ?MODULE, Code, []).
-else.
start_link(Code) ->
gen_statem:start_link({local,?NAME}, ?MODULE, Code, []).
-endif.
-ifdef(BEFORE_REWRITE).
button(Digit) ->
gen_fsm:send_event(?NAME, {button, Digit}).
-else.
button(Digit) ->
gen_statem:cast(?NAME, {button,Digit}).
%% send_event is asynchronous and becomes a cast
-endif.
-ifdef(BEFORE_REWRITE).
stop() ->
gen_fsm:sync_send_all_state_event(?NAME, stop).
-else.
stop() ->
gen_statem:call(?NAME, stop).
%% sync_send is synchronous and becomes call
%% all_state is handled by callback code in gen_statem
-endif.
init(Code) ->
do_lock(),
Data = #{code => Code, remaining => Code},
{ok, locked, Data}.
-ifdef(BEFORE_REWRITE).
-else.
callback_mode() ->
state_functions.
%% state_functions mode is the mode most similar to
%% gen_fsm. There is also handle_event mode which is
%% a fairly different concept.
-endif.
-ifdef(BEFORE_REWRITE).
locked({button, Digit}, Data0) ->
case analyze_lock(Digit, Data0) of
{open = StateName, Data} ->
{next_state, StateName, Data, 10000};
{StateName, Data} ->
{next_state, StateName, Data}
end.
-else.
locked(cast, {button,Digit}, Data0) ->
case analyze_lock(Digit, Data0) of
{open = StateName, Data} ->
{next_state, StateName, Data, 10000};
{StateName, Data} ->
{next_state, StateName, Data}
end;
locked({call, From}, Msg, Data) ->
handle_call(From, Msg, Data);
locked({info, Msg}, StateName, Data) ->
handle_info(Msg, StateName, Data).
%% Arity differs
%% All state events are dispatched to handle_call and handle_info help
%% functions. If you want to handle a call or cast event specifically
%% for this state you would add a special clause for it above.
-endif.
-ifdef(BEFORE_REWRITE).
open(timeout, State) ->
do_lock(),
{next_state, locked, State};
open({button,_}, Data) ->
{next_state, locked, Data}.
-else.
open(timeout, _, Data) ->
do_lock(),
{next_state, locked, Data};
open(cast, {button,_}, Data) ->
{next_state, locked, Data};
open({call, From}, Msg, Data) ->
handle_call(From, Msg, Data);
open(info, Msg, Data) ->
handle_info(Msg, open, Data).
%% Arity differs
%% All state events are dispatched to handle_call and handle_info help
%% functions. If you want to handle a call or cast event specifically
%% for this state you would add a special clause for it above.
-endif.
-ifdef(BEFORE_REWRITE).
handle_sync_event(stop, _From, _StateName, Data) ->
{stop, normal, ok, Data}.
handle_event(Event, StateName, Data) ->
{stop, {shutdown, {unexpected, Event, StateName}}, Data}.
handle_info(Info, StateName, Data) ->
{stop, {shutdown, {unexpected, Info, StateName}}, StateName, Data}.
-else.
-endif.
terminate(_Reason, State, _Data) ->
State =/= locked andalso do_lock(),
ok.
code_change(_Vsn, State, Data, _Extra) ->
{ok, State, Data}.
%% Internal functions
-ifdef(BEFORE_REWRITE).
-else.
handle_call(From, stop, Data) ->
{stop_and_reply, normal, {reply, From, ok}, Data}.
handle_info(Info, StateName, Data) ->
{stop, {shutdown, {unexpected, Info, StateName}}, StateName, Data}.
%% These are internal functions for handling all state events
%% and not behaviour callbacks as in gen_fsm
-endif.
analyze_lock(Digit, #{code := Code, remaining := Remaining} = Data) ->
case Remaining of
[Digit] ->
do_unlock(),
{open, Data#{remaining := Code}};
[Digit|Rest] -> % Incomplete
{locked, Data#{remaining := Rest}};
_Wrong ->
{locked, Data#{remaining := Code}}
end.
do_lock() ->
io:format("Lock~n", []).
do_unlock() ->
io:format("Unlock~n", []).
OTP 19 文件
模組
gen_fsm
模組摘要
通用有限狀態機行為。
描述
此行為模組提供一個有限狀態機。使用此模組實作的通用有限狀態機程序 (gen_fsm
) 具有一組標準的介面函數,並包含追蹤和錯誤報告的功能。它也適用於 OTP 監督樹。如需更多資訊,請參閱 OTP 設計原則。
gen_fsm
程序假設所有特定部分都位於一個回呼模組中,該模組匯出一組預先定義的函數。行為函數與回呼函數之間的關係如下:
gen_fsm module Callback module
-------------- ---------------
gen_fsm:start
gen_fsm:start_link -----> Module:init/1
gen_fsm:stop -----> Module:terminate/3
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
- -----> Module:handle_info/3
- -----> Module:terminate/3
- -----> Module:code_change/4
如果回呼函數失敗或傳回錯誤的值,gen_fsm
程序會終止。
gen_fsm
程序會按照 sys(3) 中所述的方式處理系統訊息。sys 模組可用於除錯 gen_fsm
程序。
請注意,gen_fsm
程序不會自動捕獲退出訊號,必須在回呼模組中明確啟動。
除非另有說明,否則如果指定的 gen_fsm
程序不存在或指定了錯誤的參數,此模組中的所有函數都會失敗。
如果回呼函數指定 hibernate
而不是逾時值,則 gen_fsm 程序可以進入休眠(請參閱 erlang:hibernate/3
)。如果伺服器預計會閒置很長時間,這會很有用。然而,請謹慎使用此功能,因為休眠意味著至少兩次的垃圾回收(在休眠時和喚醒後不久),而且您不希望在每次呼叫忙碌的狀態機之間執行此操作。
回呼函數
請參閱回呼函數章節,了解要從 gen_fsm
回呼模組匯出的函數。
摘要
類型
FSM 名稱規格:local
、global
或 via
已註冊。
FSM 參考 pid/0
或已註冊的 fsm_name/0
。
啟動選項,適用於 start/3,4
和 start_link/3,4
函數。
回呼:已棄用
在升級/降級期間更新內部狀態資料。
提供描述目前 gen_fsm
程序狀態的術語的可選函數。
處理非同步事件。
處理傳入的訊息
處理非同步事件。
處理同步事件。
在終止之前清除。
函數
取消通用 FSM 中的內部計時器。
進入 gen_fsm
接收迴圈。
進入 gen_fsm
接收迴圈。
進入 gen_fsm
接收迴圈。
向呼叫者傳送回覆。
將事件非同步傳送至通用 FSM。
將事件非同步傳送至通用 FSM。
在通用 FSM 中延遲傳送內部事件。
建立未註冊的獨立 gen_fsm
程序。
建立獨立的 gen_fsm
程序。
在監督樹中建立未註冊的 gen_fsm
程序。
在監督樹中建立 gen_fsm
程序。
在通用 FSM 中內部傳送逾時事件。
同步停止通用 FSM。
將事件同步傳送至通用 FSM。
將事件同步傳送至通用 FSM。
類型
-type enter_loop_opt() :: {debug, Dbgs :: [sys:debug_option()]}.
啟動選項,適用於 enter_loop/4,5,6
、start/3,4
和 start_link/3,4
函數。
請參閱 start_link/4
。
回覆目的地。請參閱 reply/2
-type fsm_name() :: {local, LocalName :: atom()} | {global, GlobalName :: term()} | {via, RegMod :: module(), ViaName :: term()}.
FSM 名稱規格:local
、global
或 via
已註冊。
當啟動 gen_fsm
時使用。請參閱 start_link/4
。
-type fsm_ref() :: pid() | (LocalName :: atom()) | {Name :: atom(), Node :: atom()} | {global, GlobalName :: term()} | {via, RegMod :: module(), ViaName :: term()}.
FSM 參考 pid/0
或已註冊的 fsm_name/0
。
例如,在 send_event/2
中使用,以指定伺服器。
-type start_opt() :: {timeout, Time :: timeout()} | {spawn_opt, [proc_lib:start_spawn_option()]} | enter_loop_opt().
啟動選項,適用於 start/3,4
和 start_link/3,4
函數。
請參閱 start_link/4
。
回呼:已棄用
-callback code_change(OldVsn, StateName, StateData, Extra) -> {ok, NextStateName, NewStateData} when OldVsn :: Vsn | {down, Vsn}, Vsn :: term(), StateName :: atom(), NextStateName :: atom(), StateData :: term(), NewStateData :: term(), Extra :: term().
在升級/降級期間更新內部狀態資料。
當 gen_fsm
程序在發布升級/降級期間更新其內部狀態資料時,會調用此函式。也就是說,當 appup 檔案中給定指令 {update, Module, Change, ...}
,其中 Change = {advanced, Extra}
時;請參閱 OTP 設計原則中的發布處理說明。 OTP 設計原則。
對於升級,OldVsn
為 Vsn
,而對於降級,OldVsn
為 {down, Vsn}
。Vsn
由回呼模組 Module
的舊版本的 vsn 屬性定義。如果沒有定義此類屬性,則版本是 Beam 檔案的校驗和。
StateName
是目前的狀態名稱,而 StateData
是 gen_fsm
程序的內部狀態資料。
Extra
是從更新指令的 {advanced, Extra}
部分「原樣」傳遞。
此函式會傳回新的目前狀態名稱和更新的內部資料。
-callback format_status(Opt, nonempty_improper_list(PDict, [StateData])) -> Status when Opt :: normal | terminate, PDict :: [{Key :: term(), Value :: term()}], StateData :: term(), Status :: term().
提供描述目前 gen_fsm
程序狀態的術語的可選函數。
第二個引數是 [PDict, StateData]
,也就是說,一個依序包含 2 個元素的清單。
注意
此回呼為選用,因此回呼模組不需要匯出它。
gen_fsm
模組提供了此函式的預設實作,會傳回回呼模組的 狀態資料。
在以下情況下,gen_fsm
程序會調用此函式
- 呼叫
sys:get_status/1,2
之一來取得gen_fsm
狀態。在此情況下,Opt
會設定為原子normal
。 gen_fsm
程序異常終止並記錄錯誤。在此情況下,Opt
會設定為原子 terminate。
此函式可用於變更這些情況下的 gen_fsm
狀態的格式和外觀。希望變更 sys:get_status/1,2
傳回值以及其狀態在終止錯誤記錄中顯示方式的回呼模組,會匯出 format_status/2
的實例,此實例會傳回描述 gen_fsm
程序目前狀態的詞彙。
PDict
是 gen_fsm
程序的程序字典的目前值。
StateData
是 gen_fsm
程序的內部狀態資料。
此函式會傳回 Status
,一個變更 gen_fsm
程序目前狀態和狀態詳細資訊的詞彙。對於 Status
可以採用的格式沒有限制,但是對於 sys:get_status/1,2
的情況(當 Opt
為 normal
時),Status
值的建議格式為 [{data, [{"StateData", Term}]}]
,其中 Term
提供 gen_fsm
狀態資料 的相關詳細資訊。不強制遵循此建議,但是這會使回呼模組狀態與 sys:get_status/1,2
傳回值的其餘部分保持一致。
此函式的一個用途是傳回壓縮的替代狀態資料表示法,以避免在記錄檔中列印大型狀態詞彙。
-callback handle_event(Event, StateName, StateData) -> Result when Event :: term(), StateName :: atom(), StateData :: term(), Result :: {next_state, NextStateName, NewStateData} | {next_state, NextStateName, NewStateData, Timeout} | {next_state, NextStateName, NewStateData, hibernate} | {stop, Reason, NewStateData}, NextStateName :: atom(), NewStateData :: term(), Timeout :: timeout(), Reason :: term().
處理非同步事件。
每當 gen_fsm
程序收到使用 send_all_state_event/2
傳送的事件時,就會調用此函式來處理事件。
StateName
是 gen_fsm
程序目前的狀態名稱。
如需其他引數和可能傳回值的說明,請參閱 Module:StateName/2
。
-callback handle_info(Info, StateName, StateData) -> Result when Info :: term(), StateName :: atom(), StateData :: term(), Result :: {next_state, NextStateName, NewStateData} | {next_state, NextStateName, NewStateData, Timeout} | {next_state, NextStateName, NewStateData, hibernate} | {stop, Reason, NewStateData}, NextStateName :: atom(), NewStateData :: term(), Timeout :: timeout(), Reason :: normal | term().
處理傳入的訊息
當 gen_fsm
程序收到任何非同步或非同步事件(或系統訊息)的其他訊息時,就會調用此函式。
Info
是收到的訊息。
如需其他引數和可能傳回值的說明,請參閱 Module:StateName/2
。
-callback handle_sync_event(Event, From, StateName, StateData) -> Result when Event :: term(), From :: from(), StateName :: atom(), StateData :: term(), Result :: {reply, Reply, NextStateName, NewStateData} | {reply, Reply, NextStateName, NewStateData, Timeout} | {reply, Reply, NextStateName, NewStateData, hibernate} | {next_state, NextStateName, NewStateData} | {next_state, NextStateName, NewStateData, Timeout} | {next_state, NextStateName, NewStateData, hibernate} | {stop, Reason, Reply, NewStateData} | {stop, Reason, NewStateData}, Reply :: term(), NextStateName :: atom(), NewStateData :: term(), Timeout :: timeout(), Reason :: term().
處理同步事件。
每當 gen_fsm
程序收到使用 sync_send_all_state_event/2,3
傳送的事件時,就會調用此函式來處理事件。
StateName
是 gen_fsm
程序目前的狀態名稱。
如需其他引數和可能傳回值的說明,請參閱 Module:StateName/3
。
-callback init(Args) -> Result when Args :: term(), Result :: {ok, StateName, StateData} | {ok, StateName, StateData, Timeout} | {ok, StateName, StateData, hibernate} | {stop, Reason} | ignore, StateName :: atom(), StateData :: term(), Timeout :: timeout(), Reason :: term().
每當使用 start/3,4
或 start_link/3,4
啟動 gen_fsm
程序時,新程序就會調用此函式進行初始化。
Args
是提供給 start 函式的 Args
引數。
如果初始化成功,此函式會傳回 {ok, StateName, StateData}、{ok, StateName, StateData, Timeout} 或 {ok, StateName, StateData, hibernate},其中 StateName
是 gen_fsm
程序的初始狀態名稱,而 StateData
是初始狀態資料。
如果提供了 integer/0
超時值,則除非在 Timeout
毫秒內收到事件或訊息,否則會發生超時。超時由原子 timeout
表示,並由 Module:StateName/2
回呼函式處理。可以使用原子 infinity
來無限期等待,這是預設值。
如果指定了 hibernate
而不是超時值,則程序會在等待下一個訊息到達時進入休眠狀態(透過呼叫 proc_lib:hibernate/3
)。
如果初始化失敗,此函式會傳回 {stop, Reason}
,其中 Reason
是任何詞彙,或者傳回 ignore
。
-callback 'StateName'(Event, StateData) -> Result when Event :: timeout | term(), StateData :: term(), Result :: {next_state, NextStateName, NewStateData} | {next_state, NextStateName, NewStateData, Timeout} | {next_state, NextStateName, NewStateData, hibernate} | {stop, Reason, NewStateData}, NextStateName :: atom(), NewStateData :: term(), Timeout :: timeout(), Reason :: term().
處理非同步事件。
對於每個可能的狀態名稱,都會有此函式的一個實例。每當 gen_fsm
程序收到使用 send_event/2
傳送的事件時,就會調用此函式的實例,此實例的名稱與目前的狀態名稱 StateName
相同,以處理事件。如果發生超時,也會調用此函式。
如果發生超時,則 Event
為原子 timeout
,否則為提供給 send_event/2
的 Event
引數。
StateData
是 gen_fsm
程序的狀態資料。
如果此函式傳回 {next_state, NextStateName, NewStateData}
、{next_state, NextStateName, NewStateData, Timeout}
或 {next_state, NextStateName, NewStateData, hibernate}
,則 gen_fsm
程序會繼續執行,目前的[狀態名稱](#state-name)會設定為 NextStateName
,並使用可能會更新的[狀態資料](#state-data) NewStateData
。如需 Timeout
和 hibernate
的說明,請參閱 [Module:init/1
](c:init/1
)。如果此函式傳回 {stop ,Reason, NewStateData}
,則 gen_fsm
程序會呼叫 Module:terminate(Reason, StateName, NewStateData)
並終止。
-callback 'StateName'(Event, From, StateData) -> Result when Event :: term(), From :: from(), StateData :: term(), Result :: {reply, Reply, NextStateName, NewStateData} | {reply, Reply, NextStateName, NewStateData, Timeout} | {reply, Reply, NextStateName, NewStateData, hibernate} | {next_state, NextStateName, NewStateData} | {next_state, NextStateName, NewStateData, Timeout} | {next_state, NextStateName, NewStateData, hibernate} | {stop, Reason, Reply, NewStateData} | {stop, Reason, NewStateData}, Reply :: term(), NextStateName :: atom(), NewStateData :: term(), Timeout :: timeout(), Reason :: normal | term().
處理同步事件。
對於每個可能的狀態名稱,此函數都會有一個實例。每當 gen_fsm
處理程序收到使用 sync_send_event/2,3
發送的事件時,會呼叫與目前狀態名稱 StateName
同名的函數實例來處理該事件。
Event
是提供給 sync_send_event/2,3
的 Event
引數。
From
是一個 tuple {Pid, Tag}
,其中 Pid
是呼叫 sync_send_event/2,3
的處理程序的 pid/0
,而 Tag
是一個唯一的標籤。
StateData
是 gen_fsm
程序的狀態資料。
如果傳回
{reply, Reply, NextStateName, NewStateData}
、{reply, Reply, NextStateName, NewStateData, Timeout}
或{reply, Reply, NextStateName, NewStateData, hibernate}
,則會將Reply
作為sync_send_event/2,3
的傳回值傳回給From
。然後,gen_fsm
處理程序會繼續執行,目前的狀態名稱設定為NextStateName
,並且使用可能已更新的 狀態資料NewStateData
。Timeout
和hibernate
的說明,請參閱Module:init/1
。如果傳回
{next_state, NextStateName, NewStateData}
、{next_state, NextStateName, NewStateData, Timeout}
或{next_state, NextStateName, NewStateData, hibernate}
,則gen_fsm
處理程序會以NewStateData
繼續在NextStateName
中執行。任何對From
的回覆都必須使用reply/2
明確指定。如果函數傳回
{stop, Reason, Reply, NewStateData}
,則會將Reply
傳回給From
。如果函數傳回 {stop, Reason, NewStateData},則任何對From
的回覆都必須使用reply/2
明確指定。然後,gen_fsm
處理程序會呼叫Module:terminate(Reason, StateName, NewStateData)
並終止。
-callback terminate(Reason, StateName, StateData) -> _ when Reason :: normal | shutdown | {shutdown, term()} | term(), StateName :: atom(), StateData :: term().
在終止之前清除。
當 gen_fsm
處理程序即將終止時,會呼叫此函數。它與 Module:init/1
相反,並且執行任何必要的清理。當它傳回時,gen_fsm
處理程序會以 Reason
終止。傳回值會被忽略。
Reason
是一個表示停止原因的詞彙,StateName
是目前的狀態名稱,而 StateData
是 gen_fsm
處理程序的 狀態資料。
Reason
取決於 gen_fsm
處理程序終止的原因。如果因為另一個回呼函數已傳回一個停止 tuple {stop, ...}
,則 Reason
的值為該 tuple 中指定的值。如果因為失敗,則 Reason
是錯誤原因。
如果 gen_fsm
處理程序是監管樹的一部分,並且由其監管者命令終止,則在以下條件適用時,會使用 Reason = shutdown
呼叫此函數
已將 gen_fsm 處理程序設定為捕獲退出訊號。
在監管者的子系規格中定義的關機策略是一個整數逾時值,而不是 brutal_kill。
即使 gen_fsm 處理程序不是監管樹的一部分,如果它從其父系收到 'EXIT'
訊息,也會呼叫此函數。Reason
與 'EXIT'
訊息中的相同。
否則,gen_fsm 處理程序會立即終止。
請注意,對於任何 normal
、shutdown
或 {shutdown, Term}
以外的原因,gen_fsm
處理程序都假設為因錯誤而終止,並使用 error_logger:format/2
發出錯誤報告。
函數
-spec cancel_timer(Ref) -> RemainingTime | false when Ref :: reference(), RemainingTime :: non_neg_integer().
取消通用 FSM 中的內部計時器。
取消在此函數呼叫的 gen_fsm
處理程序中由 Ref
參照的內部計時器。
Ref
是從 send_event_after/2
或 start_timer/2
傳回的參考。
如果計時器已逾時,但事件尚未傳遞,則會取消該事件,如同它未逾時一樣,因此從此函數傳回後,不會有錯誤的計時器事件。
如果 Ref
參照的是活動計時器,則傳回計時器過期前剩餘的毫秒數,否則傳回 false
。
-spec enter_loop(Module, Options, StateName, StateData) -> no_return() when Module :: module(), Options :: [enter_loop_opt()], StateName :: atom(), StateData :: term().
進入 gen_fsm
接收迴圈。
等同於具有 Timeout = infinity
的 enter_loop/6
,但已啟動的伺服器不會像 start_link/3
一樣註冊。
-spec enter_loop(Module, Options, StateName, StateData, FsmName) -> no_return() when Module :: module(), Options :: [enter_loop_opt()], StateName :: atom(), StateData :: term(), FsmName :: fsm_name(); (Module, Options, StateName, StateData, Timeout) -> no_return() when Module :: module(), Options :: enter_loop_opt(), StateName :: atom(), StateData :: term(), Timeout :: timeout().
進入 gen_fsm
接收迴圈。
使用引數 FsmName
等同於具有 Timeout = infinity
的 enter_loop/6
。
使用引數 Timeout
等同於 enter_loop/6
,但已啟動的伺服器不會像 start_link/3
一樣註冊。
-spec enter_loop(Module, Options, StateName, StateData, FsmName, Timeout) -> no_return() when Module :: module(), Options :: [enter_loop_opt()], StateName :: atom(), StateData :: term(), FsmName :: fsm_name() | pid(), Timeout :: timeout().
進入 gen_fsm
接收迴圈。
將現有的處理程序轉換為 gen_fsm
處理程序。不會傳回,而是呼叫處理程序進入 gen_fsm
接收迴圈,並成為 gen_fsm
處理程序。處理程序必須使用 proc_lib
中的其中一個開始函數啟動。使用者負責處理程序的任何初始化,包括註冊其名稱。
當需要比 gen_fsm
行為提供的更複雜的初始化程序時,此函數很有用。
Module
、Options
和 FsmName
的含義與呼叫 start[_link]/3,4
時的含義相同。但是,必須先根據 FsmName
註冊處理程序,然後才能呼叫此函數。
StateName
、StateData
和 Timeout
的含義與 Module:init/1
的傳回值中的含義相同。回呼模組 Module
不需要匯出 init/1
函數。
如果呼叫處理程序不是由 proc_lib
開始函數啟動,或者未根據 FsmName
註冊,則此函數將失敗。
向呼叫者傳送回覆。
當無法在 Module:StateName/3
或 Module:handle_sync_event/4
的傳回值中定義回覆時,gen_fsm
處理程序可以使用此函數,明確地將回覆傳送給呼叫 sync_send_event/2,3
或 sync_send_all_state_event/2,3
的用戶端處理程序。
Caller
必須是提供給回呼函數的 From
引數。Reply
是作為 sync_send_event/2,3
或 sync_send_all_state_event/2,3
的傳回值傳回給用戶端的任何詞彙。
傳回值 Result
沒有進一步定義,且永遠應忽略。
將事件非同步傳送至通用 FSM。
將事件以非同步方式傳送至 gen_fsm
處理程序的 FsmRef
,並立即傳回 ok
。gen_fsm
處理程序會呼叫 Module:handle_event/3
來處理事件。
如需引數的說明,請參閱 send_event/2
。
send_event/2
與 send_all_state_event/2
的區別在於使用哪個回呼函數來處理事件。當傳送在每個狀態中以相同方式處理的事件時,此函數很有用,因為只需要一個 handle_event
子句來處理事件,而不是在每個狀態名稱函數中都有一個子句。
將事件非同步傳送至通用 FSM。
將 Event
傳送至 gen_fsm
處理程序的 FsmRef
,並立即傳回 ok
。gen_fsm
處理程序會呼叫 Module:StateName/2
來處理事件,其中 StateName
是 gen_fsm
處理程序目前狀態的名稱。
pid/0
Name
,如果gen_fsm
處理程序在本機註冊{Name, Node}
,如果gen_fsm
處理程序在另一個節點上本機註冊{global, GlobalName}
,如果gen_fsm
處理程序為全域註冊{via, Module, ViaName}
,如果gen_fsm
處理程序透過替代處理程序登錄來註冊
Event
是作為 Module:StateName/2
的其中一個引數傳遞的任何詞彙。
-spec send_event_after(Time, Event) -> Ref when Time :: non_neg_integer(), Event :: term(), Ref :: reference().
在通用 FSM 中延遲傳送內部事件。
在此函數呼叫的 gen_fsm
處理程序中,在 Time
毫秒後,以內部方式傳送延遲事件。立即傳回一個參考,可用於使用 cancel_timer/1
取消延遲傳送。
gen_fsm
處理程序會呼叫 Module:StateName/2
來處理事件,其中 'StateName'
是在傳遞延遲事件時,gen_fsm
處理程序目前狀態的名稱。
Event
是作為 Module:StateName/2
的其中一個引數傳遞的任何詞彙。
-spec start(Module, Args, Options) -> Result when Module :: module(), Args :: term(), Options :: [start_opt()], Result :: {ok, Pid} | ignore | {error, Reason}, Pid :: pid(), Reason :: term().
建立未註冊的獨立 gen_fsm
程序。
等同於 start(Name, Mod, Args, Options)
,而不註冊 Name
。
如需引數和傳回值的說明,請參閱 start_link/3,4
。
-spec start(FsmName, Module, Args, Options) -> Result when FsmName :: fsm_name(), Module :: module(), Args :: term(), Options :: [start_opt()], Result :: {ok, Pid} | ignore | {error, Reason}, Pid :: pid(), Reason :: {already_started, Pid} | term().
建立獨立的 gen_fsm
程序。
建立的程序不屬於監督樹的一部分,因此沒有監督者。
有關引數和回傳值的說明,請參閱 start_link/3,4
。
-spec start_link(Module, Args, Options) -> Result when Module :: module(), Args :: term(), Options :: [start_opt()], Result :: {ok, Pid} | ignore | {error, Reason}, Pid :: pid(), Reason :: term().
在監督樹中建立未註冊的 gen_fsm
程序。
等同於 start_link(Name, Mod, Args, Options)
,但不註冊 Name
。
-spec start_link(FsmName, Module, Args, Options) -> Result when FsmName :: fsm_name(), Module :: module(), Args :: term(), Options :: [start_opt()], Result :: {ok, Pid} | ignore | {error, Reason}, Pid :: pid(), Reason :: {already_started, Pid} | term().
在監督樹中建立 gen_fsm
程序。
此程序是作為監督樹的一部分建立。此函式應由監督者直接或間接呼叫。例如,它確保 gen_fsm
程序連結到監督者。
gen_fsm
程序會呼叫 Module:init/1
進行初始化。為了確保同步啟動程序,start_link/3,4
會在 Module:init/1
回傳後才回傳。
如果
FsmName = {local, Name}
,gen_fsm
程序會使用register/2
在本機註冊為Name
。如果
FsmName = {global, GlobalName}
,gen_fsm
程序會使用global:register_name/2
全域註冊為GlobalName
。如果
FsmName = {via, Module, ViaName}
,gen_fsm
程序會向Module
代表的註冊表註冊。Module
回呼應匯出函式register_name/2
、unregister_name/1
、whereis_name/1
和send/2
,這些函式的行為應與global
中的對應函式類似。因此,{via, global, GlobalName}
是一個有效的參照。
Module
是回呼模組的名稱。
Args
是傳遞為 Module:init/1
引數的任何 term。
如果存在選項 {timeout, Time}
,則允許 gen_fsm
程序花費 Time
毫秒進行初始化,否則它會終止且啟動函式會回傳 {error, timeout}
。
如果存在選項 {debug, Dbgs}
,則會針對 Dbgs
中的每個項目呼叫對應的 sys
函式;請參閱 sys(3)
。
如果存在選項 {spawn_opt, SOpts}
,則會將 SOpts
作為選項列表傳遞給用於產生 gen_fsm
程序的 spawn_opt
BIF;請參閱 spawn_opt/2
。
注意
不允許使用產生選項
monitor
,這會導致函式因badarg
原因而失敗。
如果成功建立並初始化 gen_fsm
程序,則函式會回傳 {ok, Pid}
,其中 Pid
是 gen_fsm
程序的 pid。如果已存在具有指定 FsmName
的程序,則函式會回傳 {error, {already_started, Pid}}
,其中 Pid
是該程序的 pid。
如果 Module:init/1
因 Reason
而失敗,則函式會回傳 {error, Reason}
。如果 Module:init/1
回傳 {stop, Reason}
或 ignore
,則程序會終止,且函式會分別回傳 {error, Reason}
或 ignore
。
-spec start_timer(Time, Msg) -> Ref when Time :: non_neg_integer(), Msg :: term(), Ref :: reference().
在通用 FSM 中內部傳送逾時事件。
在呼叫此函式的 gen_fsm
程序中,在 Time
毫秒後,會在內部傳送逾時事件。立即回傳一個參考,該參考可用於使用 cancel_timer/1
取消計時器。
gen_fsm
程序會呼叫 Module:StateName/2
來處理事件,其中 'StateName'
是傳遞逾時訊息時 gen_fsm
程序的目前狀態名稱。
Msg
是任何傳遞到逾時訊息 {timeout, Ref, Msg}
中的 term,作為 Module:StateName/2
的引數之一。
-spec stop(FsmRef) -> ok when FsmRef :: fsm_ref().
-spec stop(FsmRef, Reason, Timeout) -> ok when FsmRef :: fsm_ref(), Reason :: term(), Timeout :: timeout().
同步停止通用 FSM。
命令泛型有限狀態機以指定的 Reason
結束,並等待其終止。gen_fsm
程序會在結束前呼叫 Module:terminate/3
。
如果泛型有限狀態機以預期的原因終止,則函式會回傳 ok
。任何其他原因(而非 normal
、shutdown
或 {shutdown, Term}
)都會使用 error_logger:format/2
發出錯誤報告。
Timeout
是一個大於零的整數,指定等待泛型 FSM 終止的毫秒數,或是原子 infinity
以無限期等待。如果泛型有限狀態機未在指定的時間內終止,則會引發 timeout
例外。
如果程序不存在,則會引發 noproc
例外。
-spec sync_send_all_state_event(FsmRef, Event, Timeout) -> Reply when FsmRef :: fsm_ref(), Event :: term(), Timeout :: timeout(), Reply :: term().
將事件同步傳送至通用 FSM。
將事件傳送至 gen_fsm
程序的 FsmRef
,並等待直到收到回覆或發生逾時。gen_fsm
程序會呼叫 Module:handle_sync_event/4
來處理事件。
有關 FsmRef
和 Event
的說明,請參閱 send_event/2
。有關 Timeout
和 Reply
的說明,請參閱 sync_send_event/3
。
有關 sync_send_event
和 sync_send_all_state_event
之間差異的討論,請參閱 send_all_state_event/2
。
-spec sync_send_event(FsmRef, Event, Timeout) -> Reply when FsmRef :: fsm_ref(), Event :: term(), Timeout :: timeout(), Reply :: term().
將事件同步傳送至通用 FSM。
將事件傳送至 gen_fsm
程序的 FsmRef
,並等待直到收到回覆或發生逾時。gen_fsm
程序會呼叫 Module:StateName/3
來處理事件,其中 'StateName'
是 gen_fsm
程序的目前狀態名稱。
有關 FsmRef
和 Event
的說明,請參閱 send_event/2
。
Timeout
是一個大於零的整數,指定等待回覆的毫秒數,或是原子 infinity
以無限期等待。如果在指定的時間內沒有收到回覆,則函式呼叫會失敗。
回傳值 Reply
定義於 Module:StateName/3
的回傳值中
注意
如果在 Erlang 5.6/OTP R12B 中,當伺服器在連結到用戶端的呼叫期間死亡時,有時會取用伺服器結束訊息的舊行為已移除。