檢視原始碼 gen_event 行為 (stdlib v6.2)

通用事件處理行為。

此行為模組提供事件處理功能。它包含一個通用事件管理器進程,可以動態新增和刪除任意數量的事件處理程序。

使用此模組實作的事件管理器具有一組標準的介面函式,並且包含追蹤和錯誤報告的功能。它也適用於 OTP 監督樹。有關更多資訊,請參閱OTP 設計原則

每個事件處理程序都實作為一個回呼模組,該模組匯出一組預定義的函式。行為函式和回呼函式之間的關係如下:

gen_event module                   Callback module
----------------                   ---------------
gen_event:start
gen_event:start_monitor
gen_event:start_link       ----->  -

gen_event:add_handler
gen_event:add_sup_handler  ----->  Module:init/1

gen_event:notify
gen_event:sync_notify      ----->  Module:handle_event/2

gen_event:send_request
gen_event:call             ----->  Module:handle_call/2

-                          ----->  Module:handle_info/2

gen_event:delete_handler   ----->  Module:terminate/2

gen_event:swap_handler
gen_event:swap_sup_handler ----->  Module1:terminate/2
                                   Module2:init/1

gen_event:which_handlers   ----->  -

gen_event:stop             ----->  Module:terminate/2

-                          ----->  Module:code_change/3

由於每個事件處理程序都是一個回呼模組,因此一個事件管理器擁有多個可以動態新增和刪除的回呼模組。gen_event 因此比其他行為對回呼模組的錯誤更寬容。如果已安裝事件處理程序的回呼函式失敗並返回 Reason,或返回錯誤的值 Term,事件管理器不會失敗。它會呼叫回呼函式 Module:terminate/2 並使用 {error, {'EXIT', Reason}}{error, Term} 作為引數來刪除事件處理程序。不會影響其他事件處理程序。

gen_event 進程會如 sys 中所述處理系統訊息。sys 模組可用於除錯事件管理器。

請注意,事件管理器自動捕獲退出訊號。

如果處理程序模組中的回呼函式在其傳回值中指定 hibernategen_event 進程可以進入休眠狀態(請參閱 erlang:hibernate/3)。如果預期伺服器閒置很長時間,這可能會很有用。但是,請謹慎使用此功能,因為休眠意味著至少兩次垃圾收集(休眠時和喚醒後不久),並且不希望在忙碌的事件管理器處理的每個事件之間執行此操作。

請注意,當調用多個事件處理程序時,只要有一個事件處理程序返回 hibernate 請求,整個事件管理器就會進入休眠狀態。

除非另有說明,否則如果指定的事件管理器不存在或指定了錯誤的引數,則此模組中的所有函式都會失敗。

注意

有關分散式訊號的一些重要資訊,請參閱《Erlang 參考手冊》的「進程」章節中的跨分散式阻塞訊號。 阻塞訊號可能會導致 gen_event 中的呼叫逾時顯著延遲。

另請參閱

supervisorsys

摘要

類型

事件管理器名稱規格:已註冊的 localglobalvia

用於定位事件管理器的參考。

描述 gen_event 進程狀態的映射。

可用於配置事件處理程序啟動時的選項。

不透明的請求識別碼。 有關詳細資訊,請參閱 send_request/3

不透明的請求識別碼集合(request_id/0)。

非同步呼叫的回應逾時。

回呼

在程式碼變更後更新事件處理程序狀態。

格式化/限制狀態值。

格式化/限制狀態值。

處理呼叫。

處理事件。

處理資訊訊息(一般進程訊息)。

初始化事件處理程序。

處理事件處理程序終止。

函式

向事件管理器新增新的事件處理程序。

向事件管理器新增新的事件處理程序,並進行監督。

同步呼叫事件處理程序。

檢查收到的訊息是否為請求回應。

檢查收到的訊息是否為集合中的請求回應。

從事件管理器刪除事件處理程序。

將非同步事件通知傳送到事件管理器。

接收請求回應。

接收集合中的請求回應。

在集合中儲存請求識別碼。

建立空的請求識別碼集合。

傳回 ReqIdCollection 中的請求識別碼數量。

將請求識別碼集合轉換為清單。

將非同步 call 請求傳送到事件處理程序。

將非同步 call 請求傳送到事件處理程序,並將其儲存在請求識別碼集合中。

等同於 start([])

建立獨立的事件管理器進程,可能沒有名稱。

建立獨立的事件管理器進程。

建立事件管理器進程作為監督樹的一部分,可能沒有名稱。

建立事件管理器進程作為監督樹的一部分。

建立獨立的事件管理器進程,並進行監控,可能沒有名稱。

建立獨立的事件管理器進程,並進行監控。

停止事件管理器。

取代事件處理程序,並進行監督。

將同步事件通知傳送到事件管理器。

等待請求回應。

等待集合中的任何請求回應。

傳回事件管理器中的所有事件處理程序。

類型

-type add_handler_ret() :: ok | term() | {'EXIT', term()}.
連結到此類型

debug_flag()

檢視原始碼 (未匯出)
-type debug_flag() :: trace | log | statistics | debug | {logfile, string()}.
-type del_handler_ret() :: ok | term() | {'EXIT', term()}.
連結到此類型

emgr_name()

檢視原始碼 (未匯出)
-type emgr_name() :: {local, atom()} | {global, term()} | {via, atom(), term()}.

事件管理器名稱規格:已註冊的 localglobalvia

  • {local, Name} - 事件管理器會在本地註冊為 Name,使用 register/2
  • {global, GlobalName} - 事件管理器會使用 global:register_name/2 在全域註冊為 GlobalName。 如果未提供名稱,則不會註冊事件管理器。
  • {via, Module, ViaName},事件管理器會使用 Module 表示的登錄檔進行註冊。 Module 回呼會匯出函式 register_name/2unregister_name/1whereis_name/1send/2,它們的行為應與 global 中的對應函式相同。 因此,{via, global, GlobalName} 是有效的參考。
連結到此類型

emgr_ref()

檢視原始碼 (未匯出)
-type emgr_ref() :: atom() | {atom(), node()} | {global, term()} | {via, atom(), term()} | pid().

用於定位事件管理器的參考。

參考可以是以下任何一種

  • 事件管理器的 PID
  • Name,如果事件管理器在本機註冊
  • {Name, Node},如果事件管理器在另一個節點在本機註冊
  • {global, GlobalName},如果事件管理器在全域註冊
  • {via, Module, ViaName},如果事件管理器通過替代的進程登錄檔註冊
-type format_status() ::
          #{state => term(), message => term(), reason => term(), log => [sys:system_event()]}.

描述 gen_event 進程狀態的映射。

鍵是

  • state - 事件處理程序的內部狀態。
  • message - 導致事件處理程序終止的訊息。
  • reason - 導致事件處理程序終止的原因。
  • log - 伺服器的 sys 記錄

可以在不事先通知的情況下將新關聯新增到狀態映射中。

-type handler() :: atom() | {atom(), term()}.
-type handler_args() :: term().
連結到此類型

options()

檢視原始碼 (未匯出)
-type options() ::
          [{timeout, timeout()} |
           {debug, [debug_flag()]} |
           {spawn_opt, [proc_lib:start_spawn_option()]} |
           {hibernate_after, timeout()}].

可用於配置事件處理程序啟動時的選項。

-opaque request_id()

不透明的請求識別碼。 有關詳細資訊,請參閱 send_request/3

-opaque request_id_collection()

不透明的請求識別碼集合(request_id/0)。

每個請求識別碼都可以與使用者選擇的標籤關聯。 有關詳細資訊,請參閱 reqids_new/0

連結到此類型

response_timeout()

檢視原始碼 (未匯出)
-type response_timeout() :: timeout() | {abs, integer()}.

非同步呼叫的回應逾時。

用於設定等待回應的時限,適用於 receive_response/2receive_response/3wait_response/2wait_response/3。時間單位為 毫秒。目前有效的數值為:

  • 0..4294967295 - 相對於目前時間的逾時時間,單位為毫秒。

  • infinity - 無限逾時。也就是說,操作永遠不會逾時。

  • {abs, Timeout} - 絕對的 Erlang 單調時間逾時,單位為毫秒。也就是說,當 erlang:monotonic_time(millisecond) 返回的值大於或等於 Timeout 時,操作將會逾時。Timeout 不允許指定超過未來 4294967295 毫秒的時間。當您有一系列請求 (request_id_collection/0) 對應的回應期限時,使用絕對逾時值來指定逾時特別方便,因為您不必反覆重新計算直到期限的相對時間。

連結到此類型

start_mon_ret()

檢視原始碼 (未匯出)
-type start_mon_ret() :: {ok, {pid(), reference()}} | {error, term()}.
-type start_ret() :: {ok, pid()} | {error, term()}.

回呼函式

連結到此回呼函式

code_change(OldVsn, State, Extra)

檢視原始碼 (選用)
-callback code_change(OldVsn :: term() | {down, term()}, State :: term(), Extra :: term()) ->
                         {ok, NewState :: term()}.

在程式碼變更後更新事件處理程序狀態。

當在發布升級/降級期間,也就是當 appup 檔案中指定了 {update, Module, Change,...} 指令時,會呼叫此函式,讓已安裝的事件處理器更新其內部狀態。

如需詳細資訊,請參閱 OTP 設計原則

在升級時,OldVsnVsn,而在降級時,OldVsn{down, Vsn}Vsn 由舊版回呼模組 Modulevsn 屬性定義。如果未定義此類屬性,則版本為 Beam 檔案的校驗和。

State 是事件處理器的內部狀態。

Extra 是從更新指令的 {advanced, Extra} 部分「按原樣」傳遞的。

此函式會返回更新後的內部狀態。

注意

如果在 .appup 檔案中指定 Change={advanced, Extra} 的情況下進行發布升級/降級,而 code_change/3 未實作,則事件處理器將會因 undef 錯誤原因而崩潰。

連結到此回呼函式

format_status(Status)

檢視原始碼 (選用) (自 OTP 25.0 起)
-callback format_status(Status) -> NewStatus when Status :: format_status(), NewStatus :: format_status().

格式化/限制狀態值。

此函式由 gen_event 程序呼叫,目的是為了格式化/限制伺服器狀態,以進行除錯和記錄。

會在以下情況下呼叫:

  • 呼叫 sys:get_status/1,2 其中之一,以取得 gen_event 狀態。

  • 事件處理器異常終止,且 gen_event 記錄錯誤。

此回呼函式用於限制 sys:get_status/1,2 返回或傳送到 logger 的事件處理器狀態。

此回呼函式會取得一個描述目前狀態的映射 Status,並且應返回一個具有相同鍵的映射 NewStatus,但可能會轉換某些值。

此回呼函式的兩種可能用例是從狀態中移除敏感資訊,以防止其列印在記錄檔中,或是精簡大型不相關的狀態項目,這些項目只會使記錄檔變得雜亂。

範例:

format_status(Status) ->
  maps:map(
    fun(state,State) ->
            maps:remove(private_key, State);
       (message,{password, _Pass}) ->
            {password, removed};
       (_,Value) ->
            Value
    end, Status).

注意

此回呼函式為選用,因此事件處理器模組不需要匯出它。如果處理器未匯出此函式,gen_event 模組會直接使用處理器狀態來達到以下描述的目的。

如果匯出了此回呼函式但失敗,為了隱藏可能敏感的資料,預設函式將會返回 format_status/1 已崩潰的事實。

連結到此回呼函式

format_status(Opt, StatusData)

檢視原始碼 (選用) (自 OTP R14B 起)
此回呼函式已棄用。回呼函式 gen_event:format_status(_,_) 已棄用;請改用 format_status/1。
-callback format_status(Opt, StatusData) -> Status
                           when
                               Opt :: normal | terminate,
                               StatusData :: [PDict | State],
                               PDict :: [{Key :: term(), Value :: term()}],
                               State :: term(),
                               Status :: term().

格式化/限制狀態值。

此函式由 gen_event 程序呼叫,目的是為了格式化/限制伺服器狀態,以進行除錯和記錄。

會在以下情況下呼叫:

  • 呼叫 sys:get_status/1,2 其中之一,以取得 gen_event 狀態。在此情況下,Opt 設定為原子 normal

  • 事件處理器異常終止,且 gen_event 記錄錯誤。在此情況下,Opt 設定為原子 terminate

此函式可用於在這些情況下變更事件處理器狀態的形式和外觀。希望變更 sys:get_status/1,2 返回值,以及其狀態在終止錯誤記錄中的顯示方式的事件處理器回呼模組,會匯出 format_status/2 的實例,該實例會返回描述事件處理器目前狀態的詞彙。

PDictgen_event 程序字典的目前值。

State 是事件處理器的內部狀態。

此函式會返回 Status,這是一個會變更事件處理器目前狀態詳細資訊的詞彙。任何詞彙都可以作為 Statusgen_event 模組會按以下方式使用 Status

  • 當呼叫 sys:get_status/1,2 時,gen_event 會確保其返回值包含 Status,以取代事件處理器的狀態詞彙。

  • 當事件處理器異常終止時,gen_event 會記錄 Status,以取代事件處理器的狀態詞彙。

此函式的一種用途是返回精簡的替代狀態表示法,以避免在記錄檔中列印大型狀態詞彙。

注意

此回呼函式為選用,因此事件處理器模組不需要匯出它。如果處理器未匯出此函式,gen_event 模組會直接使用處理器狀態來達到以下描述的目的。

連結到此回呼函式

handle_call(Request, State)

檢視原始碼
-callback handle_call(Request :: term(), State :: term()) ->
                         {ok, Reply :: term(), NewState :: term()} |
                         {ok, Reply :: term(), NewState :: term(), hibernate} |
                         {swap_handler,
                          Reply :: term(),
                          Args1 :: term(),
                          NewState :: term(),
                          Handler2 :: atom() | {atom(), Id :: term()},
                          Args2 :: term()} |
                         {remove_handler, Reply :: term()}.

處理呼叫。

每當事件管理器收到使用 call/3,4 發送的請求時,就會呼叫此函式,以讓指定的事件處理器處理該請求。

Requestcall/3,4Request 引數。

State 是事件處理器的內部狀態。

返回值與 Module:handle_event/2 的返回值相同,但它們還包含一個詞彙 Reply,這是客戶端的答覆,作為 call/3,4 的返回值。

連結到此回呼函式

handle_event(Event, State)

檢視原始碼
-callback handle_event(Event :: term(), State :: term()) ->
                          {ok, NewState :: term()} |
                          {ok, NewState :: term(), hibernate} |
                          {swap_handler,
                           Args1 :: term(),
                           NewState :: term(),
                           Handler2 :: atom() | {atom(), Id :: term()},
                           Args2 :: term()} |
                          remove_handler.

處理事件。

每當事件管理器收到使用 notify/2sync_notify/2 發送的事件時,就會為每個已安裝的事件處理器呼叫此函式,以處理該事件。

Eventnotify/2 / sync_notify/2Event 引數。

State 是事件處理器的內部狀態。

  • 如果返回 {ok, NewState}{ok, NewState, hibernate},則事件處理器會留在事件管理器中,並使用可能已更新的內部狀態 NewState

  • 如果返回 {ok, NewState, hibernate},則事件管理器也會進入休眠狀態(透過呼叫 proc_lib:hibernate/3),等待下一個事件發生。只要其中一個事件處理器返回 {ok, NewState, hibernate},整個事件管理器程序就會進入休眠狀態。

  • 如果返回 {swap_handler, Args1, NewState, Handler2, Args2},則會使用 Handler2 取代事件處理器,方法是先呼叫 Module:terminate(Args1, NewState),然後呼叫 Module2:init({Args2, Term}),其中 TermModule:terminate/2 的返回值。如需詳細資訊,請參閱 swap_handler/3

  • 如果返回 remove_handler,則會透過呼叫 Module:terminate(remove_handler, State) 來刪除事件處理器。

連結到此回呼函式

handle_info(Info, State)

檢視原始碼 (選用)
-callback handle_info(Info :: term(), State :: term()) ->
                         {ok, NewState :: term()} |
                         {ok, NewState :: term(), hibernate} |
                         {swap_handler,
                          Args1 :: term(),
                          NewState :: term(),
                          Handler2 :: atom() | {atom(), Id :: term()},
                          Args2 :: term()} |
                         remove_handler.

處理資訊訊息(一般進程訊息)。

當事件管理器收到事件或同步請求(或系統訊息)以外的任何其他訊息時,就會為每個已安裝的事件處理器呼叫此函式。

Info 是接收到的訊息。

特別是,當程序在呼叫 add_sup_handler/3 後終止時,就會呼叫此回呼函式。任何附加到事件管理器的事件處理器,而該事件管理器又具有受監視的處理器時,都應預期收到 Module:handle_info({'EXIT', Pid, Reason}, State) 形狀的回呼函式。

有關 State 和可能的返回值的描述,請參閱 Module:handle_event/2

注意

此回呼函式為選用,因此回呼模組不需要匯出它。gen_event 模組會提供此函式的預設實作,記錄關於非預期的 Info 訊息、捨棄它並返回 {ok, State}

-callback init(InitArgs :: term()) ->
                  {ok, State :: term()} | {ok, State :: term(), hibernate} | {error, Reason :: term()}.

初始化事件處理程序。

每當新的事件處理器被加入事件管理器時,就會呼叫此函式來初始化事件處理器。

如果事件處理器是因為呼叫 add_handler/3add_sup_handler/3 而加入的,則 InitArgs 會是這些函式的 Args 參數。

如果事件處理器是因為呼叫 swap_handler/3swap_sup_handler/3,或是因為其他回呼函式傳回 swap 元組而取代另一個事件處理器,則 InitArgs 會是一個 {Args, Term} 元組,其中 Args 是函式呼叫/傳回元組中提供的參數,而 Term 是終止舊事件處理器的結果,請參閱 swap_handler/3

如果成功,此函式會傳回 {ok, State}{ok, State, hibernate},其中 State 是事件處理器的初始內部狀態。

如果傳回 {ok, State, hibernate},事件管理器會進入休眠(透過呼叫 proc_lib:hibernate/3),等待下一個事件發生。

連結到此回呼函式

terminate(Args, State)

查看原始碼 (選用)
-callback terminate(Args ::
                        term() |
                        {stop, Reason :: term()} |
                        stop | remove_handler |
                        {error, {'EXIT', Reason :: term()}} |
                        {error, term()},
                    State :: term()) ->
                       term().

處理事件處理程序終止。

每當事件處理器從事件管理器中刪除時,就會呼叫此函式。它應該是 Module:init/1 的相反操作,並執行任何必要的清理工作。

如果事件處理器是因為呼叫 delete_handler/3swap_handler/3swap_sup_handler/3 而刪除的,則 Arg 會是此函式呼叫的 Args 參數。

如果事件處理器與一個因 Reason 原因而終止的程序有監督連線,則 Arg = {stop, Reason}

如果事件處理器是因為事件管理器正在終止而被刪除,則 Arg = stop

如果事件管理器是監督樹的一部分,並且其監督者命令其終止,則該管理器會終止。即使它不是監督樹的一部分,如果它收到來自其父代的 'EXIT' 訊息,也會終止。

如果事件處理器是因為另一個回呼函式傳回 remove_handler{remove_handler, Reply} 而被刪除,則 Arg = remove_handler

如果事件處理器是因為回呼函式傳回非預期的值 Term 而被刪除,則 Arg = {error, Term},如果回呼函式失敗,則 Arg = {error, {'EXIT', Reason}}

State 是事件處理器的內部狀態。

此函式可以傳回任何項。如果事件處理器是因為呼叫 gen_event:delete_handler/3 而刪除的,則該函式的傳回值會成為此函式的傳回值。如果事件處理器要被另一個事件處理器取代,因為發生交換,則傳回值會傳遞給新事件處理器的 init 函式。否則,傳回值會被忽略。

注意

此回呼是可選的,因此回呼模組不需要匯出它。gen_event 模組提供不進行清理的預設實作。

函式

連結到此函式

add_handler(EventMgrRef, Handler, Args)

檢視原始碼
-spec add_handler(EventMgrRef :: emgr_ref(), Handler :: handler(), Args :: term()) -> term().

向事件管理器新增新的事件處理程序。

新的事件處理器會加入事件管理器 EventMgrRef。事件管理器會呼叫 Module:init/1 來初始化事件處理器及其內部狀態。

Handler 是回呼模組 Module 的名稱,或是一個 {Module, Id} 元組,其中 Id 是任何項。{Module, Id} 表示法使得當許多事件處理器使用相同的回呼模組時,可以識別特定的事件處理器。

Args 是任何作為參數傳遞給 Module:init/1 的項。

如果 Module:init/1 傳回表示成功完成的正確值,則事件管理器會加入事件處理器,而此函式會傳回 ok。如果 Module:init/1 因為 Reason 而失敗,或傳回 {error,Reason},則事件處理器會被忽略,而此函式會分別傳回 {'EXIT',Reason}{error,Reason}

連結到此函式

add_sup_handler(EventMgrRef, Handler, Args)

檢視原始碼
-spec add_sup_handler(EventMgrRef :: emgr_ref(), Handler :: handler(), Args :: term()) -> term().

向事件管理器新增新的事件處理程序,並進行監督。

新的事件處理器會依照 add_handler/3 的方式加入,但事件管理器也會透過連結事件處理器和呼叫程序來監督連線。

  • 如果呼叫程序稍後因 Reason 而終止,事件管理器會透過呼叫 Module:terminate/2 來刪除任何被監督的事件處理器,然後針對每個剩餘的處理器呼叫 Module:handle_info/2

  • 如果事件處理器稍後被刪除,事件管理器會傳送訊息 {gen_event_EXIT,Handler,Reason} 給呼叫程序。Reason 是以下之一:

    • 如果事件處理器是因為呼叫 delete_handler/3 而被移除,或是回呼函式傳回 remove_handler(請參閱下方),則為 normal
    • 如果事件處理器是因為事件管理器正在終止而被移除,則為 shutdown
    • 如果程序 Pid 透過呼叫 swap_handler/3swap_sup_handler/3,以另一個事件處理器 NewHandler 取代了事件處理器,則為 {swapped, NewHandler, Pid}
    • 如果事件處理器是因為錯誤而被移除,則為其他 term/0。哪個項取決於錯誤。

如需參數和傳回值的說明,請參閱 add_handler/3

連結到此函式

call(EventMgrRef, Handler, Request)

檢視原始碼
-spec call(EventMgrRef :: emgr_ref(), Handler :: handler(), Request :: term()) -> term().

等同於 call(EventMgrRef, Handler, Request, 5000)

連結到此函式

call(EventMgrRef, Handler, Request, Timeout)

檢視原始碼
-spec call(EventMgrRef :: emgr_ref(), Handler :: handler(), Request :: term(), Timeout :: timeout()) ->
              term().

同步呼叫事件處理程序。

呼叫會傳送給安裝在事件管理器 EventMgrRef 中的 Handler,方法是傳送請求並等待回覆到達,或發生逾時。事件管理器會呼叫 Module:handle_call/2 來處理請求。

Request 是任何作為參數傳遞給 Module:handle_call/2 的項。

Timeout 是一個大於零的整數,指定等待回覆的毫秒數,或是原子 infinity 以無限期等待。預設值為 5000。如果在指定時間內未收到回覆,則函式呼叫會失敗。

傳回值 Reply 定義於 Module:handle_call/2 的傳回值中。如果未安裝指定的事件處理器,則函式會傳回 {error, bad_module}。如果回呼函式因 Reason 而失敗,或傳回非預期的值 Term,則此函式會分別傳回 {error, {'EXIT', Reason}}{error, Term}

當此呼叫失敗時,它會 終止 呼叫程序。終止項的形式為 {Reason, Location},其中 Location = {gen_event, call, ArgList}。請參閱 gen_server:call/3,其中說明了終止項中 Reason 的相關值。

連結到此函式

check_response(Msg, ReqId)

查看原始碼 (自 OTP 23.0 起)
-spec check_response(Msg, ReqId) -> Result
                        when
                            Msg :: term(),
                            ReqId :: request_id(),
                            Response ::
                                {reply, Reply :: term()} | {error, {Reason :: term(), emgr_ref()}},
                            Result :: Response | no_reply.

檢查收到的訊息是否為請求回應。

檢查 Msg 是否為對應於請求識別碼 ReqId 的回應。請求必須由 send_request/3 發出,並由呼叫此函式的相同程序發出。

如果 Msg 是對應於 ReqId 的回應,則回應會以 Reply 傳回。否則,此函式會傳回 no_reply,並且不會進行清理。因此,必須重複呼叫此函式,直到傳回回應為止。

如果未安裝指定的事件處理器,則函式會傳回 {error, bad_module}。如果回呼函式因 Reason 而失敗,或傳回非預期的值 Term,則此函式會分別傳回 {error, {'EXIT', Reason}}{error, Term}。如果事件管理器在此函式被呼叫之前就已死亡,也就是說;如果 Msg 報告伺服器的死亡,則此函式會傳回 {error,{Reason, EventMgrRef}},其中 Reason 是終止原因。

連結到此函式

check_response(Msg, ReqIdCollection, Delete)

查看原始碼 (自 OTP 25.0 起)
-spec check_response(Msg, ReqIdCollection, Delete) -> Result
                        when
                            Msg :: term(),
                            ReqIdCollection :: request_id_collection(),
                            Delete :: boolean(),
                            Response ::
                                {reply, Reply :: term()} | {error, {Reason :: term(), emgr_ref()}},
                            Result ::
                                {Response,
                                 Label :: term(),
                                 NewReqIdCollection :: request_id_collection()} |
                                no_request | no_reply.

檢查收到的訊息是否為集合中的請求回應。

檢查 Msg 是否為對應於儲存在 ReqIdCollection 中的請求識別碼的回應。ReqIdCollection 的所有請求識別碼都必須對應於使用 send_request/3send_request/5 發出的請求,並且所有請求都必須由呼叫此函式的程序發出。

回應中的 Label 是與回應對應的請求識別碼相關聯的 Label。請求識別碼的 Label 會在 將請求識別碼儲存在集合中,或使用 send_request/5 發送請求時建立關聯。

check_response/2 相比,與特定請求識別碼相關聯的傳回結果或例外情況會被包裝在 3 元組 {Response, Label, NewReqIdCollection} 中。Response 是由 check_response/2 產生的值,Label 是與特定 請求識別碼 相關聯的值,而 NewReqIdCollection 是一個可能已修改的請求識別碼集合。

如果 ReqIdCollection 為空,則會傳回 no_request

如果 Msg 不對應於 ReqIdCollection 中的任何請求識別符,則會返回 no_reply

如果 Deletetrue,則在產生的 NewReqIdCollection 中,與 Label 的關聯會從 ReqIdCollection 中刪除。如果 Deletefalse,則 NewReqIdCollection 將等於 ReqIdCollection。請注意,刪除關聯並非沒有成本,而且包含已處理請求的集合仍然可以被後續呼叫 check_response/3)、receive_response/3) 和 wait_response/3)使用。

然而,如果不刪除已處理的關聯,上述呼叫將無法偵測到何時沒有更多待處理的請求需要處理,因此您必須以其他方式追蹤此資訊,而不是依賴 no_request 的返回值。請注意,如果您將僅包含已處理或已放棄請求關聯的集合傳遞給 check_response/3,它將始終返回 no_reply

連結到此函式

delete_handler(EventMgrRef, Handler, Args)

檢視原始碼
-spec delete_handler(EventMgrRef :: emgr_ref(), Handler :: handler(), Args :: term()) -> term().

從事件管理器刪除事件處理程序。

此函數會從事件管理器 EventMgrRef 中刪除事件處理程序 Handler。事件管理器會呼叫 Module:terminate/2 來終止事件處理程序。

Args 是傳遞給 Module:terminate/2 作為引數的任何詞彙。

返回值是 Module:terminate/2 的返回值。如果未安裝指定的事件處理程序,函數會返回 {error, module_not_found}。如果回呼函數因 Reason 而失敗,則函數會返回 {'EXIT', Reason}

連結到此函式

notify(EventMgrRef, Event)

檢視原始碼
-spec notify(EventMgrRef :: emgr_ref(), Event :: term()) -> ok.

將非同步事件通知傳送到事件管理器。

事件會傳送到 EventMgrRef,後者會針對每個已安裝的事件處理程序呼叫 Module:handle_event/2 以處理事件。

Event 是傳遞給 Module:handle_event/2 作為引數的任何詞彙。

即使指定的事件管理器不存在,notify/1 也不會失敗,除非將其指定為 Name

連結到此函式

receive_response(ReqId, Timeout)

查看原始碼 (自 OTP 24.0 起)
-spec receive_response(ReqId, Timeout) -> Result
                          when
                              ReqId :: request_id(),
                              Timeout :: response_timeout(),
                              Response ::
                                  {reply, Reply :: term()} | {error, {Reason :: term(), emgr_ref()}},
                              Result :: Response | timeout.

接收請求回應。

接收與請求識別符 ReqId 對應的回應。請求必須由 send_request/3 發出,且必須由呼叫此函數的相同程序發出。

Timeout 指定等待回應的時間長度。如果在指定時間內未收到回應,此函數會返回 timeout。假設伺服器在支援別名(在 OTP 24 中引入)的節點上執行,則請求也會被放棄。也就是說,逾時後將不會收到任何回應。否則,稍後可能會收到錯誤的回應。

返回值 ReplyModule:handle_call/2 的返回值中定義。

如果未安裝指定的事件處理程序,此函數會返回 {error, bad_module}。如果回呼函數因 Reason 而失敗或返回意外的值 Term,則此函數會分別返回 {error, {'EXIT', Reason}}{error,Term}。如果事件管理器在請求之前或期間死掉,此函數會返回 {error, {Reason, EventMgrRef}}

wait_response/2receive_response/2 之間的差異在於 receive_response/2 會在逾時時放棄請求,以便忽略潛在的未來回應,而 wait_response/2 則不會。

連結到此函式

receive_response(ReqIdCollection, Timeout, Delete)

查看原始碼 (自 OTP 25.0 起)
-spec receive_response(ReqIdCollection, Timeout, Delete) -> Result
                          when
                              ReqIdCollection :: request_id_collection(),
                              Timeout :: response_timeout(),
                              Delete :: boolean(),
                              Response ::
                                  {reply, Reply :: term()} | {error, {Reason :: term(), emgr_ref()}},
                              Result ::
                                  {Response,
                                   Label :: term(),
                                   NewReqIdCollection :: request_id_collection()} |
                                  no_request | timeout.

接收集合中的請求回應。

ReqIdCollection 中接收回應。ReqIdCollection 的所有請求識別符都必須對應於使用 send_request/3send_request/5 發出的請求,而且所有請求都必須由呼叫此函數的程序發出。

回應中的 Label 是與回應對應的請求識別符相關聯的 Label。請求識別符的 Label 會在將 請求 ID 新增 到集合時,或使用 send_request/5 發送請求時關聯。

receive_response/2 相比,與特定請求識別符相關聯的返回結果或例外狀況將會封裝在 3 元組 {Response, Label, NewReqIdCollection} 中。Responsereceive_response/2 將產生的值,Label 是與特定 請求識別符 相關聯的值,而 NewReqIdCollection 則是可能修改過的請求識別符集合。

如果 ReqIdCollection 為空,則會傳回 no_request

Timeout 指定等待回應的時間長度。如果在指定時間內未收到回應,函數會返回 timeout。假設伺服器在支援別名(在 OTP 24 中引入)的節點上執行,則 ReqIdCollection 所識別的所有請求也將會被放棄。也就是說,逾時後將不會收到任何回應。否則,稍後可能會收到錯誤的回應。

receive_response/3wait_response/3 之間的差異在於 receive_response/3 會在逾時時放棄請求,以便忽略潛在的未來回應,而 wait_response/3 則不會。

如果 Deletetrue,則在產生的 NewReqIdCollection 中,與 Label 的關聯會從 ReqIdCollection 中刪除。如果 Deletefalse,則 NewReqIdCollection 將等於 ReqIdCollection。請注意,刪除關聯並非沒有成本,而且包含已處理請求的集合仍然可以被後續呼叫 receive_response/3)、check_response/3) 和 wait_response/3) 使用。

然而,如果不刪除已處理的關聯,上述呼叫將無法偵測到何時沒有更多待處理的請求需要處理,因此您必須以其他方式追蹤此資訊,而不是依賴 no_request 的返回值。請注意,如果您將僅包含已處理或已放棄請求關聯的集合傳遞給 receive_response/3,它將始終阻塞直到 Timeout 過期,然後返回 timeout

連結到此函式

reqids_add(ReqId, Label, ReqIdCollection)

查看原始碼 (自 OTP 25.0 起)
-spec reqids_add(ReqId :: request_id(), Label :: term(), ReqIdCollection :: request_id_collection()) ->
                    NewReqIdCollection :: request_id_collection().

在集合中儲存請求識別碼。

儲存 ReqId,並透過將此資訊新增至 ReqIdCollection 並返回產生的請求識別符集合,將 Label 與請求識別符關聯。

連結到此函式

reqids_new()

查看原始碼 (自 OTP 25.0 起)
-spec reqids_new() -> NewReqIdCollection :: request_id_collection().

建立空的請求識別碼集合。

返回新的空請求識別符集合。請求識別符集合可用於處理多個待處理的請求。

send_request/3 發出的請求的請求識別符可以使用 reqids_add/3 儲存在請求識別符集合中。此類請求識別符集合稍後可用於透過將集合作為引數傳遞給 receive_response/3)、wait_response/3check_response/3 來取得集合中與請求對應的一個回應。

reqids_size/1 可用於判斷集合中請求識別符的數量。

連結到此函式

reqids_size(ReqIdCollection)

查看原始碼 (自 OTP 25.0 起)
-spec reqids_size(ReqIdCollection :: request_id_collection()) -> non_neg_integer().

傳回 ReqIdCollection 中的請求識別碼數量。

連結到此函式

reqids_to_list(ReqIdCollection)

查看原始碼 (自 OTP 25.0 起)
-spec reqids_to_list(ReqIdCollection :: request_id_collection()) ->
                        [{ReqId :: request_id(), Label :: term()}].

將請求識別碼集合轉換為清單。

返回 {ReqId, Label} 元組的列表,該列表對應於 ReqIdCollection 中所有具有相關聯標籤的請求識別符。

連結到此函式

send_request(EventMgrRef, Handler, Request)

查看原始碼 (自 OTP 23.0 起)
-spec send_request(EventMgrRef :: emgr_ref(), Handler :: handler(), Request :: term()) ->
                      ReqId :: request_id().

將非同步 call 請求傳送到事件處理程序。

此函數會將呼叫請求 Request 發送到由 EventMgrRef 識別的事件管理器中安裝的事件處理程序 Handler,並返回請求識別符 ReqId。返回值 ReqId 稍後應與 receive_response/2)、wait_response/2) 或 check_response/2)一起使用,以提取請求的實際結果。

除了將請求識別符直接傳遞給這些函數之外,還可以透過 reqids_add/3 將其儲存在請求識別符集合中。此類請求識別符集合稍後可用於透過將集合作為引數傳遞給 receive_response/3)、wait_response/3) 或 check_response/3 來取得集合中與請求對應的一個回應。如果您即將將請求識別符儲存在集合中,您可能會想考慮改用 send_request/5

呼叫 gen_event:receive_response(gen_event:send_request(EventMgrRef, Handler, Request), Timeout) 可以被視為等同於 gen_event:call(EventMgrRef, Handler, Request, Timeout),忽略錯誤處理。

事件管理器會呼叫 Module:handle_call/2 來處理請求。

Request 可以是任何詞彙,並作為其中一個參數傳遞給 Module:handle_call/2

連結到此函式

send_request(EventMgrRef, Handler, Request, Label, ReqIdCollection)

檢視原始碼 (自 OTP 25.0 起)
-spec send_request(EventMgrRef :: emgr_ref(),
                   Handler :: handler(),
                   Request :: term(),
                   Label :: term(),
                   ReqIdCollection :: request_id_collection()) ->
                      NewReqIdCollection :: request_id_collection().

將非同步 call 請求傳送到事件處理程序,並將其儲存在請求識別碼集合中。

此函數將呼叫請求 Request 發送至由 EventMgrRef 識別的事件管理器中安裝的事件處理程式 HandlerLabel 將與操作的請求識別碼相關聯,並新增至返回的請求識別碼集合 NewReqIdCollection

該集合稍後可用於透過將該集合作為參數傳遞給 receive_response/3wait_response/3check_response/3,來取得集合中與請求相對應的單個回應。

與呼叫 gen_event:reqids_add(gen_event:send_request(EventMgrRef, Handler, Request), Label, ReqIdCollection) 相同,但效率稍高。

-spec start() -> start_ret().

等同於 start([])

-spec start(EventMgrName :: emgr_name()) -> start_ret();
           (Options :: options()) -> start_ret().

建立獨立的事件管理器進程,可能沒有名稱。

等同於 start(EventMgrName, Options)

使用參數 EventMgrName 時,Options[]

使用參數 Options 時,將建立一個無名的事件管理器。

有關參數和傳回值的說明,請參閱 start_link/2

連結到此函式

start(EventMgrName, Options)

檢視原始碼 (自 OTP 20.0 起)
-spec start(EventMgrName :: emgr_name(), Options :: options()) -> start_ret().

建立獨立的事件管理器進程。

建立的事件管理器程序不屬於監督樹的一部分,因此沒有監督者。

有關參數和傳回值的說明,請參閱 start_link/2

-spec start_link() -> start_ret().

等同於 start_link([])

-spec start_link(EventMgrName :: emgr_name()) -> start_ret();
                (Options :: options()) -> start_ret().

建立事件管理器進程作為監督樹的一部分,可能沒有名稱。

等同於 start_link(EventMgrName, Options)

使用參數 EventMgrName 時,Options[]

使用參數 Options 時,將建立一個無名的事件管理器。

有關參數和傳回值的說明,請參閱 start_link/2

連結到此函式

start_link(EventMgrName, Options)

檢視原始碼 (自 OTP 20.0 起)
-spec start_link(EventMgrName :: emgr_name(), Options :: options()) -> start_ret().

建立事件管理器進程作為監督樹的一部分。

此函數應由監督者直接或間接地呼叫。例如,它可以確保事件管理器連結到呼叫者(監督者)。

  • 如果存在選項 {hibernate_after, HibernateAfterTimeout},則 gen_event 程序會等待任何訊息 HibernateAfterTimeout 毫秒,如果沒有收到任何訊息,則該程序會自動進入休眠狀態(透過呼叫 proc_lib:hibernate/3)。

如果事件管理器成功建立,則函數會傳回 {ok, Pid},其中 Pid 是事件管理器的 pid/0

如果已存在具有指定 EventMgrName 的程序,則該函數會傳回 {error,{already_started,OtherPid}},其中 OtherPid 是該程序的 pid,且事件管理器程序會以原因 normal 結束。

如果事件管理器在指定的啟動逾時時間 {timeout, Time} 內啟動失敗,這不太可能發生,因為啟動不會與其他程序互動,則該函數會傳回 {error, timeout},且失敗的事件管理器會被 exit(_, kill) 強制終止。

如果 start_link/1,2 傳回 {error, _},則啟動的事件管理器程序已終止。如果已將 'EXIT' 訊息傳遞至呼叫程序(由於程序連結),則已使用該訊息。

警告

在 OTP 26.0 之前,如果啟動的事件管理器未能註冊其名稱,則此函數可能在啟動的事件管理器程序終止之前傳回 {error, {already_started, OtherPid}},因此再次啟動可能會失敗,因為註冊的名稱尚未取消註冊,且 'EXIT' 訊息可能會稍後送達呼叫此函數的程序。

但如果啟動逾時,此函數會強制終止啟動的事件管理器程序,並傳回 {error, timeout},然後會使用程序連結 {'EXIT', Pid, killed} 訊息。

啟動在 OTP 26.0 中同步進行,並實施了一項保證,即失敗啟動的任何程序連結 'EXIT' 訊息都不會留在呼叫者的收件匣中。

連結到此函式

start_monitor()

檢視原始碼 (自 OTP 23.0 起)
-spec start_monitor() -> start_mon_ret().

等同於 start_monitor([])

連結到此函式

start_monitor(EventMgrNameOrOptions)

檢視原始碼 (自 OTP 23.0 起)
-spec start_monitor(EventMgrNameOrOptions :: emgr_name() | options()) -> start_mon_ret().

建立獨立的事件管理器進程,並進行監控,可能沒有名稱。

等同於 start_monitor(EventMgrName, Options)

使用參數 EventMgrName 時,Options[]

使用參數 Options 時,將建立一個無名的事件管理器。

有關參數和傳回值的說明,請參閱 start_monitor/2start_link/1

連結到此函式

start_monitor(EventMgtName, Options)

檢視原始碼 (自 OTP 23.0 起)
-spec start_monitor(EventMgtName :: emgr_name(), Options :: options()) -> start_mon_ret().

建立獨立的事件管理器進程,並進行監控。

建立的事件管理器程序不屬於監督樹的一部分,因此沒有監督者。會以原子方式為新建立的程序設定監視器。

有關參數和傳回值的說明,請參閱 start_link/2。請注意,成功啟動的傳回值與 start_link/2 不同。 start_monitor/0,1,2 會傳回 {ok, {Pid, Mon}},其中 Pid 是程序的程序識別碼,而 Mon 是設定為監視程序的監視器參考。如果啟動不成功,呼叫者將被封鎖,直到收到 DOWN 訊息並從訊息佇列中移除為止。

-spec stop(EventMgrRef :: emgr_ref()) -> ok.

等同於 stop(EventMgrRef, normal, infinity)

連結到此函式

stop(EventMgrRef, Reason, Timeout)

檢視原始碼 (自 OTP 18.0 起)
-spec stop(EventMgrRef :: emgr_ref(), Reason :: term(), Timeout :: timeout()) -> ok.

停止事件管理器。

命令事件管理器 EventMgrRef 以指定 Reason 結束,並等待其終止。在終止之前,gen_event 會針對每個已安裝的事件處理程式呼叫 Module:terminate(stop,...)

如果事件管理器以預期的原因終止,則函數會傳回 ok。除了 normalshutdown{shutdown, Term} 以外的任何其他原因都會使用 logger 發出錯誤報告。

Timeout 是一個大於零的整數,指定等待事件管理器終止的毫秒數,或是原子 infinity,表示無限期等待。如果事件管理器未在指定時間內終止,則呼叫會以原因 timeout 結束呼叫程序。

如果程序不存在,則呼叫會以原因 noproc 結束呼叫程序;如果與執行伺服器的遠端 Node 的連線失敗,則會以原因 {nodedown, Node} 結束。

連結到此函式

swap_handler(EventMgrRef, OldHandler, NewHandler)

檢視原始碼
-spec swap_handler(EventMgrRef :: emgr_ref(),
                   OldHandler :: {handler(), term()},
                   NewHandler :: {handler(), term()}) ->
                      ok | {error, term()}.

取代事件處理程序。

此函數會取代事件管理器 EventMgrRef 中的事件處理程式。

有關 OldHandlerNewHandler 的說明,請參閱 add_handler/3

首先會刪除舊的事件處理程式 OldHandler。事件管理器會呼叫 OldModule:terminate(Args1, ...),其中 OldModuleOldHandler 的回呼模組,並收集傳回值。

然後會新增新的事件處理程式 NewHandler,並透過呼叫 NewModule:init({Args2,Term}) 來初始化,其中 NewModuleNewHandler 的回呼模組,而 TermOldModule:terminate/2 的傳回值。這可以將資訊從 OldHandler 傳輸到 NewHandler

即使未安裝指定的舊事件處理程式,在這種情況下 Term = error,或如果 OldModule:terminate/2Reason 而失敗(在這種情況下,Term = {'EXIT', Reason}),也會新增新的處理程式。即使 NewModule:init/1 失敗,也會刪除舊的處理程式。

如果 OldHandler 與程序 Pid 之間存在受監督的連線,則 NewHandlerPid 之間會存在受監督的連線。

如果 NewModule:init/1 傳回正確的值,則此函數會傳回 ok。如果 NewModule:init/1Reason 而失敗,或傳回非預期的值 Term,則此函數會分別傳回 {error, {'EXIT', Reason}}{error, Term}

連結到此函式

swap_sup_handler(EventMgrRef, OldHandler, NewHandler)

檢視原始碼
-spec swap_sup_handler(EventMgrRef :: emgr_ref(),
                       OldHandler :: {handler(), term()},
                       NewHandler :: {handler(), term()}) ->
                          ok | {error, term()}.

取代事件處理程序,並進行監督。

以與 swap_handler/3 相同的方式取代事件管理器 EventMgrRef 中的事件處理程式,但也會監督 NewHandler 與呼叫程序之間的連線。

有關參數和傳回值的說明,請參閱 swap_handler/3

連結到此函式

sync_notify(EventMgrRef, Event)

檢視原始碼
-spec sync_notify(EventMgrRef :: emgr_ref(), Event :: term()) -> ok.

將同步事件通知傳送到事件管理器。

該事件會傳送至 EventMgrRef,該事件會針對每個已安裝的事件處理程式呼叫 Module:handle_event/2 以處理該事件。此函數會在所有事件處理程式處理完事件後傳回 ok

Event 是傳遞給 Module:handle_event/2 作為引數的任何詞彙。

連結到此函式

wait_response(ReqId, WaitTime)

檢視原始碼 (自 OTP 23.0 起)
-spec wait_response(ReqId, WaitTime) -> Result
                       when
                           ReqId :: request_id(),
                           WaitTime :: response_timeout(),
                           Response ::
                               {reply, Reply :: term()} | {error, {Reason :: term(), emgr_ref()}},
                           Result :: Response | timeout.

等待請求回應。

等待請求識別碼 ReqId 的回應。請求必須由 send_request/3 提出,且來自呼叫 send_request/3 的相同程序。

WaitTime 指定等待回應的時間長度。如果在指定時間內未收到回應,則該函數會傳回 timeout,且不會進行清理。因此,可以重複調用該函數,直到傳回回覆為止。

返回值 ReplyModule:handle_call/2 的返回值中定義。

如果未安裝指定的事件處理常式,則此函式會傳回 {error, bad_module}。如果回呼函式失敗並帶有 Reason,或傳回非預期的值 Term,則此函式會分別傳回 {error,{'EXIT',Reason}}{error,Term}。如果事件管理員在請求之前或期間停止運作,則此函式會傳回 {error, {Reason, EventMgrRef}}

receive_response/2wait_response/2 之間的差異在於,receive_response/2 在逾時時會放棄請求,因此潛在的未來回應會被忽略,而 wait_response/2 則不會。

連結到此函式

wait_response(ReqIdCollection, WaitTime, Delete)

檢視原始碼 (自 OTP 25.0 起)
-spec wait_response(ReqIdCollection, WaitTime, Delete) -> Result
                       when
                           ReqIdCollection :: request_id_collection(),
                           WaitTime :: response_timeout(),
                           Delete :: boolean(),
                           Response ::
                               {reply, Reply :: term()} | {error, {Reason :: term(), emgr_ref()}},
                           Result ::
                               {Response,
                                Label :: term(),
                                NewReqIdCollection :: request_id_collection()} |
                               no_request | timeout.

等待集合中的任何請求回應。

ReqIdCollection 中等待回應。 ReqIdCollection 的所有請求識別碼都必須對應到使用 send_request/3send_request/5 發出的請求,並且所有請求都必須由呼叫此函式的程序發出。

回應中的 Label 是與回應對應的請求識別符相關聯的 Label。請求識別符的 Label 會在將 請求 ID 新增 到集合時,或使用 send_request/5 發送請求時關聯。

wait_response/2 相比,與特定請求識別碼相關聯的傳回結果或例外情況將會被包裝在一個 3 元組 {Response, Label, NewReqIdCollection} 中。 Responsewait_response/2 將會產生的值,Label 是與特定 請求識別碼 相關聯的值,而 NewReqIdCollection 則是一個可能會修改的請求識別碼集合。

如果 ReqIdCollection 為空,則會傳回 no_request

如果在 WaitTime 過期之前沒有收到任何回應,則會傳回 timeout。在接收到回應並由 check_response()receive_response()wait_response() 完成之前,可以根據需要多次繼續等待回應。

receive_response/3wait_response/3 之間的差異在於,receive_response/3 在逾時時會放棄請求,因此潛在的未來回應會被忽略,而 wait_response/3 則不會。

如果 Deletetrue,則與 Label 的關聯會從結果 NewReqIdCollection 中的 ReqIdCollection 中刪除。如果 Deletefalse,則 NewReqIdCollection 將等於 ReqIdCollection。請注意,刪除關聯並非免費,而且包含已處理請求的集合仍然可以被後續對 wait_response/3check_response/3receive_response/3 的呼叫使用。

然而,如果沒有刪除已處理的關聯,則上述呼叫將無法偵測到何時沒有更多待處理的請求需要處理,因此您必須以其他方式追蹤此資訊,而不是依賴 no_request 的傳回值。請注意,如果您將僅包含已處理或放棄請求的關聯的集合傳遞給此函式,它將始終阻塞直到 WaitTime 過期,然後傳回 timeout

連結到此函式

which_handlers(EventMgrRef)

檢視原始碼
-spec which_handlers(EventMgrRef :: emgr_ref()) -> [handler()].

傳回事件管理器中的所有事件處理程序。

此函式會傳回事件管理員 EventMgrRef 中安裝的所有事件處理常式的列表。

如需 Handler 的說明,請參閱 add_handler/3