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

通用伺服器行為。

此行為模組提供客戶端-伺服器關係中的伺服器。使用此模組實作的通用伺服器程序(gen_server)具有標準的介面函式集,並包含追蹤和錯誤回報的功能。它也適用於 OTP 監管樹。有關詳細資訊,請參閱 OTP 設計原則中的 gen_server 行為章節。

gen_server 程序假設所有特定部分都位於匯出一組預定義函式的回呼模組中。行為函式與回呼函式之間的關係如下:

gen_server module            Callback module
-----------------            ---------------
gen_server:start
gen_server:start_monitor
gen_server:start_link -----> Module:init/1

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

gen_server:call
gen_server:send_request
gen_server:multi_call -----> Module:handle_call/3

gen_server:cast
gen_server:abcast     -----> Module:handle_cast/2

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

-                     -----> Module:handle_continue/2

-                     -----> Module:terminate/2

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

如果回呼函式失敗或傳回錯誤的值,則 gen_server 程序會終止。但是,類別為 throw 的異常不會被視為錯誤,而是視為所有回呼函式的有效傳回值。

gen_server 程序會如 sys 中所述處理系統訊息。sys 模組可用於偵錯 gen_server 程序。

請注意,gen_server 程序不會自動捕獲退出訊號,必須在回呼模組中明確啟動此操作。

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

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

如果 gen_server 程序需要在初始化後執行動作,或將回呼的執行分成多個步驟,則可以傳回 {continue, Continue} 來代替逾時或休眠值,這將在接收任何外部訊息/請求之前,呼叫 Module:handle_continue/2 回呼。

如果 gen_server 程序終止,例如由於回呼模組中的函式傳回 {stop,Reason,NewState},則會向連結的程序和埠傳送具有此 Reason 的退出訊號。有關使用退出訊號處理錯誤的詳細資訊,請參閱參考手冊中的 程序

注意

有關分散式訊號的一些重要資訊,請參閱《Erlang 參考手冊》的「程序」章節中的透過分散式傳輸的封鎖訊號部分。封鎖訊號可能會導致 gen_server 中的呼叫逾時顯著延遲。

另請參閱

gen_eventgen_statemproc_libsupervisorsys

摘要

類型

用於 startenter_loop 函式的伺服器啟動選項。

描述 gen_server 狀態的映射。

呼叫的回覆目的地。

將回覆與對應請求相關聯的處理程序。

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

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

非同步呼叫的回應逾時。

伺服器名稱規格:已註冊的 localglobalvia

伺服器規格:pid/0 或已註冊的 server_name/0

來自 start_monitor/3,4 函式的傳回值。

用於 start 函式的伺服器啟動選項。

來自 start/3,4start_link/3,4 函式的傳回值。

回呼

在程式碼變更後更新伺服器狀態。

格式化/限制狀態值。

格式化/限制狀態值。

處理投射訊息。

處理回呼延續。

處理資訊訊息(常規程序訊息)。

初始化伺服器。

處理伺服器終止。

函式

將請求投射到多個節點。

將請求投射到多個節點。

呼叫伺服器:傳送請求並等待回應。

將請求投射到伺服器。

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

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

使呼叫程序成為 gen_server 程序。

使呼叫程序成為 gen_server 程序。

平行呼叫多個節點上的伺服器。

平行呼叫多個節點上的伺服器。

接收請求回應。

接收集合中的請求回應。

向用戶端傳送回覆。

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

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

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

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

傳送非同步 call 請求。

傳送非同步 call 請求,並將其新增至請求識別碼集合。

啟動伺服器,既不連結也不註冊。

啟動伺服器,既不連結也不註冊。

啟動伺服器,已連結但未註冊。

啟動伺服器,已連結但未註冊。

啟動伺服器,已監控但既未連結也未註冊。

啟動伺服器,已監控且已註冊,但未連結。

等待請求回應。

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

類型

-type enter_loop_opt() ::
          {hibernate_after, HibernateAfterTimeout :: timeout()} | {debug, Dbgs :: [sys:debug_option()]}.

用於 startenter_loop 函式的伺服器啟動選項。

透過 enter_loop/3-5 或啟動函式(例如 start_link/3,4)啟動 gen_server 伺服器時可以使用的選項。

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

  • {debug, Dbgs} - 對於 Dbgs 中的每個條目,都會呼叫 sys 中對應的函式。

-type format_status() ::
          #{state => term(), message => term(), reason => term(), log => [sys:system_event()]}.

描述 gen_server 狀態的映射。

金鑰為

  • state - gen_server 程序的內部狀態。
  • message - 導致伺服器終止的訊息。
  • reason - 導致伺服器終止的原因。
  • log - 伺服器的 sys 日誌

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

-type from() :: {Client :: pid(), Tag :: reply_tag()}.

呼叫的回覆目的地。

Destination,作為第一個參數傳遞給回呼函式 Module:handle_call/3gen_server,用於透過 reply/2 回覆 (而不是透過回呼函式的回傳值) 給使用 call/2,3 呼叫 gen_server 的程序 ClientTag 是一個對於此呼叫/請求實例來說唯一的詞。

-opaque reply_tag()

將回覆與對應請求相關聯的處理程序。

-opaque request_id()

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

-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) 的截止期限時,使用絕對值指定逾時特別方便,因為您不必一遍又一遍地重新計算到截止期限的相對時間。

-type server_name() ::
          {local, LocalName :: atom()} |
          {global, GlobalName :: term()} |
          {via, RegMod :: module(), ViaName :: term()}.

伺服器名稱規格:已註冊的 localglobalvia

在啟動 gen_server 時使用。請參閱函式 start/3,4start_link/3,4start_monitor/3,4enter_loop/3,4,5 和類型 server_ref/0

  • {local, LocalName} - 使用 register/2gen_server 在本地註冊為 LocalName

  • {global, GlobalName} - 使用 global:register_name/2gen_server 程序識別碼全域註冊為 GlobalName

  • {via, RegMod, ViaName} - 使用 RegMod 代表的註冊表註冊 gen_server 程序。RegMod 回呼應匯出函式 register_name/2unregister_name/1whereis_name/1send/2,這些函式的行為應類似於 global 中的對應函式。因此,{via, global, GlobalName} 是一個有效的參照,等同於 {global, GlobalName}

-type server_ref() ::
          pid() |
          (LocalName :: atom()) |
          {Name :: atom(), Node :: atom()} |
          {global, GlobalName :: term()} |
          {via, RegMod :: module(), ViaName :: term()}.

伺服器規格:pid/0 或已註冊的 server_name/0

在處理 gen_server 時使用。請參閱 call/2,3cast/2send_request/2check_response/2wait_response/2stop/2,3 和類型 server_name/0

它可以是

  • pid/0 - gen_server 的程序識別碼。

  • LocalName - gen_server 在本地使用 register/2 註冊為 LocalName

  • {Name,Node} - gen_server 在另一個節點上本地註冊。

  • {global, GlobalName} - gen_serverglobal 中全域註冊。

  • {via, RegMod, ViaName} - gen_server 在替代程序註冊表中註冊。請參閱 server_name/0 描述的相同詞彙。

-type start_mon_ret() ::
          {ok, {Pid :: pid(), MonRef :: reference()}} | ignore | {error, Reason :: term()}.

來自 start_monitor/3,4 函式的傳回值。

與類型 start_ret/0 相同,但對於成功啟動,它會回傳程序識別碼 Pidmonitor/2,3 MonRef

-type start_opt() ::
          {timeout, Timeout :: timeout()} |
          {spawn_opt, SpawnOptions :: [proc_lib:start_spawn_option()]} |
          enter_loop_opt().

用於 start 函式的伺服器啟動選項。

透過例如 start_link/3,4 啟動 gen_server 伺服器時可以使用的選項。

  • {timeout, Timeout} - gen_server 程序允許花費多少毫秒初始化,否則將終止,並且啟動函式會回傳 {error, timeout}

  • {spawn_opt, SpawnOptions} - SpawnOptions 選項清單會傳遞給用於衍生 gen_server 的函式;請參閱 proc_lib:start_spawn_option/0)。

    注意

    不允許使用衍生選項 monitor - 這會導致 badarg 失敗。

  • enter_loop_opt/0 - 請參閱下方類型 enter_loop_opt/0,了解 enter_loop/3,4,5 也允許的其他啟動選項。

-type start_ret() :: {ok, Pid :: pid()} | ignore | {error, Reason :: term()}.

來自 start/3,4start_link/3,4 函式的傳回值。

  • {ok, Pid} - gen_server 程序已成功建立和初始化,其程序識別碼為 Pid

  • {error, {already_started, OtherPid}} - 具有指定 ServerName 的程序已存在,其程序識別碼為 OtherPid。此函式無法啟動 gen_server。它在呼叫 Module:init/1 之前以 normal 原因結束。

  • {error, timeout} - gen_server 程序無法初始化,因為 Module:init/1 未在 啟動逾時內回傳。該 gen_server 程序已使用 exit(_, kill) 終止。

  • ignore - gen_server 程序無法初始化,因為 Module:init/1 回傳了 ignore

  • {error,Reason} - gen_server 程序無法初始化,因為 Module:init/1 回傳了 {stop,Reason}{error,Reason},或因為 Reason 而失敗。

請參閱 Module:init/1,了解 gen_server 程序初始化失敗時的退出原因。

回呼

連結到此回呼

code_change(OldVsn, State, Extra)

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

在程式碼變更後更新伺服器狀態。

gen_server 程序要在版本升級/降級期間更新其內部狀態時,即當 appup 檔案中指定指令 {update, Module, Change, ...} 時,將會呼叫此函式。

如需更多資訊,請參閱 OTP 設計原則中的「版本處理指令」章節。

對於升級,OldVsnVsn,對於降級,OldVsn{down,Vsn}Vsn 由回呼模組 Module 的舊版本的 vsn 屬性定義。如果未定義此類屬性,則版本為 Beam 檔案的總和檢查碼。

Stategen_server 程序的內部狀態。

Extra 會從更新指令的 {advanced,Extra} 部分「原封不動」地傳遞。

如果成功,此函式必須回傳更新後的內部狀態。

如果此函式回傳 {error,Reason},則進行中的升級會失敗並回復至舊版本。

注意

如果在未實作 Module:code_change/3 時,當 .appup 檔案中指定 Change = {advanced, Extra} 時,進行版本升級/降級,則回呼呼叫會因為 undef 錯誤原因而當機。

連結到此回呼

format_status(Status)

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

格式化/限制狀態值。

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

會在以下情況中呼叫它

  • 呼叫 sys:get_status/1,2 以取得 gen_server 狀態。
  • gen_server 程序異常終止並記錄錯誤。

此回呼用於限制 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_server 模組提供此函式的預設實作,該實作回傳回呼模組狀態。

如果匯出了此回呼但失敗,為了隱藏可能敏感的資料,預設函式反而會回傳 Module:format_status/1 已當機的事實。

連結到此回呼

format_status(Opt, StatusData)

檢視原始碼 (可選) (自 OTP R13B04 起)
此回呼已過時。回呼 gen_server: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_server 程序會呼叫此函式以格式化/限制伺服器狀態。

會在以下情況中呼叫它

  • 呼叫 sys:get_status/1,2 之一以取得 gen_server 狀態。Opt 設定為原子 normal
  • gen_server 程序異常終止並記錄錯誤。Opt 設定為原子 terminate

此函式對於變更這些情況下的 gen_server 狀態的形式和外觀非常有用。想要變更 sys:get_status/1,2 回傳值以及其狀態在終止錯誤記錄中的顯示方式的回呼模組,會匯出 Module:format_status/2 的實例,該實例會回傳描述 gen_server 程序目前狀態的詞彙。

PDictgen_server 程序程序字典的目前值。

Stategen_server 程序的內部狀態。

此函數會回傳 Status,此術語會變更 gen_server 程序的目前狀態與狀況的詳細資訊。Status 可以採用的形式沒有限制,但對於 sys:get_status/1,2 的情況(當 Optnormal 時),建議的 Status 值形式為 [{data, [{"State", Term}]}],其中 Term 提供 gen_server 狀態的相關詳細資訊。遵循此建議並非必要,但它可讓回呼模組的狀態與 sys:get_status/1,2 的其他回傳值保持一致。

此函數的一個用途是回傳精簡的替代狀態表示法,以避免在記錄檔中印出大型狀態術語。

注意

此回呼是可選的,因此回呼模組不需要匯出它。gen_server 模組提供此函式的預設實作,該實作回傳回呼模組狀態。

連結到此回呼

handle_call(Request, From, State)

檢視原始碼
-callback handle_call(Request :: term(), From :: from(), State :: term()) ->
                         {reply, Reply :: term(), NewState :: term()} |
                         {reply,
                          Reply :: term(),
                          NewState :: term(),
                          timeout() | hibernate | {continue, term()}} |
                         {noreply, NewState :: term()} |
                         {noreply, NewState :: term(), timeout() | hibernate | {continue, term()}} |
                         {stop, Reason :: term(), Reply :: term(), NewState :: term()} |
                         {stop, Reason :: term(), NewState :: term()}.

處理呼叫。

每當 gen_server 程序收到使用 call/2,3multi_call/2,3,4send_request/2,4 傳送的要求時,就會呼叫此函數來處理該要求。

Stategen_server 程序的內部狀態,而 NewState 則可能是更新後的狀態。

Request 是從提供給 callmulti_call 的相同引數傳遞而來。

回傳值 Result 的解譯方式如下

  • {reply,Reply,NewState}
    {reply,Reply,NewState,_}
    - Reply 值會傳回給用戶端要求,並成為其回傳值。

    gen_server 程序會繼續以可能更新的內部狀態 NewState 執行。

  • {noreply,NewState}
    {noreply,NewState,_}
    - gen_server 程序會繼續以可能更新的內部狀態 NewState 執行。

    必須透過呼叫 reply(From, Reply) 在此或稍後的回呼中建立用戶端要求的答覆。

  • {reply,_,_,Timeout}
    {noreply,_,Timeout}
    - 如果提供整數 Timeout,則除非在該毫秒數內收到要求或訊息,否則會發生逾時。逾時由原子 timeout 表示,並由 Module:handle_info/2 回呼函數處理。Timeout =:= infinity 可用於無限期等待,這與回傳沒有 Timeout 成員的值相同。

  • {reply,_,_,hibernate}
    {noreply,_,hibernate}
    - 程序會透過呼叫 proc_lib:hibernate/3 進入休眠狀態,等待下一個訊息抵達

  • {reply,_,_,{continue,Continue}}
    {noreply,_,{continue,Continue}}
    - 程序會執行 Module:handle_continue/2 回呼函數,並將 Continue 作為第一個引數。

  • {stop,Reason,NewState}
    {stop,Reason,Reply,NewState}
    - gen_server 程序會呼叫 Module:terminate(Reason,NewState),然後終止。

    {stop,_,Reply,_} 會建立用戶端要求的答覆,就像 {reply,Reply,...} 一樣,而 {stop,_,_} 則不會,因此就像 {noreply,NewState,...} 一樣,必須在回傳 {stop,_,_} 之前呼叫 reply(From, Reply) 來建立答覆。

連結到此回呼

handle_cast(Request, State)

檢視原始碼
-callback handle_cast(Request :: term(), State :: term()) ->
                         {noreply, NewState :: term()} |
                         {noreply, NewState :: term(), timeout() | hibernate | {continue, term()}} |
                         {stop, Reason :: term(), NewState :: term()}.

處理投射訊息。

每當 gen_server 程序收到使用 cast/2abcast/2,3 傳送的要求時,就會呼叫此函數來處理該要求。

如需引數與可能回傳值的說明,請參閱 Module:handle_call/3

連結到此回呼

handle_continue(Info, State)

檢視原始碼 (選用) (自 OTP 21.0 起)
-callback handle_continue(Info :: term(), State :: term()) ->
                             {noreply, NewState :: term()} |
                             {noreply, NewState :: term(), timeout() | hibernate | {continue, term()}} |
                             {stop, Reason :: term(), NewState :: term()}.

處理回呼延續。

當先前回呼回傳包含 {continue, Continue} 的其中一個元組時,gen_server 程序就會呼叫此函數。此呼叫會在先前回呼之後立即叫用,因此適用於在初始化之後執行工作,或將回呼中的工作分成多個步驟,同時更新程序狀態。

如需其他引數與可能回傳值的說明,請參閱 Module:handle_call/3

注意

此回呼為選用,因此只有在回傳來自另一個回呼的包含 {continue,Continue} 的其中一個元組時,回呼模組才需要匯出此回呼。如果使用這類 {continue,_} 元組且未實作回呼,則程序將會以 undef 錯誤結束。

連結到此回呼

handle_info(Info, State)

檢視原始碼 (選用)
-callback handle_info(Info :: timeout | term(), State :: term()) ->
                         {noreply, NewState :: term()} |
                         {noreply, NewState :: term(), timeout() | hibernate | {continue, term()}} |
                         {stop, Reason :: term(), NewState :: term()}.

處理資訊訊息(常規程序訊息)。

當發生逾時,或當 gen_server 程序收到同步或非同步要求(或系統訊息)以外的任何其他訊息時,gen_server 程序就會呼叫此函數。

Info 為原子 timeout(如果發生逾時),或收到的訊息。

如需其他引數與可能回傳值的說明,請參閱 Module:handle_call/3

注意

此回呼為選用,因此回呼模組不需要匯出此回呼。gen_server 模組提供此函數的預設實作,它會記錄有關非預期 Info 訊息的資訊,並捨棄該訊息,然後回傳 {noreply, State}

-callback init(Args :: term()) ->
                  {ok, State :: term()} |
                  {ok, State :: term(), timeout() | hibernate | {continue, term()}} |
                  {stop, Reason :: term()} |
                  ignore |
                  {error, Reason :: term()}.

初始化伺服器。

每當使用 start/3,4start_monitor/3,4start_link/3,4 啟動 gen_server 程序時,新程序就會呼叫此函數來初始化伺服器。

Args 是提供給啟動函數的 Args 引數。

回傳值 Result 的解譯方式如下

  • {ok,State}
    {ok,State,_}
    - 初始化成功,而 Stategen_server 程序的內部狀態。

  • {ok,_,Timeout}
    {ok,_,hibernate}
    {ok,_,{continue,Continue}}
    - 如需此元組成員的說明,請參閱 Module:handle_call/3 的對應回傳值。

  • {stop,Reason} - 初始化失敗。gen_server 程序會以原因 Reason 結束。

  • {error,Reason} 自 OTP 26.0 起
    ignore
    - 初始化失敗。gen_server 程序會以原因 normal 結束。

在這些不同的情況下,請參閱函數 start_link/3,4 的回傳值 start_ret/0

連結到此回呼

terminate(Reason, State)

檢視原始碼 (選用)
-callback terminate(Reason :: normal | shutdown | {shutdown, term()} | term(), State :: term()) -> term().

處理伺服器終止。

gen_server 程序即將終止時,就會呼叫此函數。

它與 Module:init/1 相反,並執行任何必要的清除動作。當此函數回傳時,gen_server 程序會以 Reason 終止。回傳值會被忽略。

Reason 是表示停止原因的術語,而 Stategen_server 程序的內部狀態。

Reason 取決於 gen_server 程序終止的原因。如果終止原因是因為另一個回呼函數回傳停止元組 {stop,..},則 Reason 的值為該元組中指定的值。如果終止原因是因為失敗,則 Reason 為錯誤原因。

如果 gen_server 程序是監督樹狀結構的一部分,且由其監督程式下令終止,則如果適用下列條件,就會呼叫此函數,並將 Reason=shutdown 作為引數

  • gen_server 程序已設定為攔截結束訊號。
  • 監督程式的子規格中定義的關閉策略是整數逾時值,而不是 brutal_kill

即使 gen_server 程序不是監督樹狀結構的一部分,如果收到來自其父系的 'EXIT' 訊息,也會呼叫此函數。Reason'EXIT' 訊息中的原因相同。

如果 gen_server 程序未攔截結束訊號,則 gen_server 程序會立即終止。

請注意,對於 normalshutdown{shutdown,Term} 以外的任何其他原因,請參閱 stop/3gen_server 程序會假定因錯誤而終止,且會使用 logger 發出錯誤報告。

當 gen_server 程序結束時,會將具有相同原因的結束訊號傳送給連結的程序與埠。

注意

此回呼為選用,因此回呼模組不需要匯出此回呼。gen_server 模組提供沒有清除動作的預設實作。

函數

-spec abcast(Name :: atom(), Request :: term()) -> abcast.

將請求投射到多個節點。

abcast(Nodes, Name, Request) 等效,其中 Nodes 是連接至呼叫節點的所有節點,包括呼叫節點本身。

此函數的連結

abcast(Nodes, Name, Request)

檢視原始碼
-spec abcast(Nodes :: [node()], Name :: atom(), Request :: term()) -> abcast.

將請求投射到多個節點。

將非同步要求傳送至在指定節點中以 Name 局部註冊的 gen_server 程序。此函數會立即回傳,並忽略不存在的節點,或 gen_server Name 不存在的節點。gen_server 程序會呼叫 Module:handle_cast/2 來處理要求。

如需引數的說明,請參閱 multi_call/2,3,4

此函數的連結

call(ServerRef, Request)

檢視原始碼
-spec call(ServerRef :: server_ref(), Request :: term()) -> Reply :: term().

等同於 call(ServerRef, Request, 5000)

此函數的連結

call(ServerRef, Request, Timeout)

檢視原始碼
-spec call(ServerRef :: server_ref(), Request :: term(), Timeout :: timeout()) -> Reply :: term().

呼叫伺服器:傳送請求並等待回應。

透過傳送要求並等待直到收到答覆或發生逾時,對 gen_server 程序的 ServerRef 進行同步呼叫。gen_server 程序會呼叫 Module:handle_call/3 來處理要求。

另請參閱 ServerRef 的類型 server_ref/0

Request 是作為第一個引數傳遞給 Module:handle_call/3 的任何術語。

Timeout 是一個整數,指定等待回覆的毫秒數,或使用原子 infinity 來無限期等待。如果在指定時間內沒有收到回覆,此函式會終止呼叫的程序,並使用包含 Reason = timeout 的終止詞,如下所述。

注意

在 OTP 24 之前,如果呼叫者使用 (try...)catch 來避免程序終止,而且伺服器碰巧只是回覆延遲,則回覆可能會在稍後任何時間到達程序的訊息佇列。因此,呼叫程序在捕獲逾時終止後,必須準備好接收 {reference(), _} 形式的垃圾訊息,並適當處理它們(丟棄它們),以免它們阻塞程序的訊息佇列,或被誤認為其他訊息。

從 OTP 24 開始,gen_server:call 使用程序別名,因此不會收到延遲回覆。

回傳值 Reply 是從 Module:handle_call/3 的回傳值傳遞而來。

此呼叫可能會終止呼叫的程序,並使用 {Reason, Location} 形式的終止詞,其中 Location = {gen_server, call, ArgList},而 Reason 可以是(至少)下列其中之一:

  • timeout - 如上所述,在等待回覆 Timeout 毫秒後,呼叫被中止。

  • noproc - ServerRef 是指透過名稱 (而不是 pid/0) 參照的伺服器,而且查詢伺服器程序失敗,或 pid/0 已終止。

  • {nodedown,Node} - ServerRef 是指遠端節點 Node 上的伺服器,而且與該節點的連線失敗。

  • calling_self - 呼叫 self/0 會無限期掛起。

  • shutdown - 伺服器在呼叫期間被其監督者停止。另請參閱 stop/3

  • normal
    {shutdown,Term}
    - 伺服器在呼叫期間停止,原因是從其回呼函式之一傳回 {stop,Reason,_} 而沒有回覆此呼叫。另請參閱 stop/3

  • _OtherTerm - 伺服器程序在呼叫期間終止,原因是 Reason。可能是從其回呼函式之一傳回 {stop,Reason,_}(沒有回覆此呼叫),或是引發例外狀況,或是因為收到未捕獲的終止訊號。

此函數的連結

cast(ServerRef, Request)

檢視原始碼
-spec cast(ServerRef :: server_ref(), Request :: term()) -> ok.

將請求投射到伺服器。

將非同步請求傳送到 gen_server ServerRef,並立即傳回 ok,忽略目的地節點或 gen_server 程序是否存在。

gen_server 程序會呼叫 Module:handle_cast(Request, _) 來處理請求。

此函數的連結

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(), server_ref()}},
                            Result :: Response | no_reply.

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

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

如果 Msg 是對控制代碼 ReqId 的回覆,則請求的結果會傳回至 Reply。否則,此函式會傳回 no_reply,且不會執行清除動作,因此應重複叫用此函式,直到傳回回應為止。

回傳值 Reply 是從 Module:handle_call/3 的回傳值傳遞而來。

如果呼叫此函式時 gen_statem 伺服器程序已終止,也就是 Msg 報告伺服器已終止,則此函式會傳回 error 回傳值,並帶有終止 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(), server_ref()}},
                            Result ::
                                {Response,
                                 Label :: term(),
                                 NewReqIdCollection :: request_id_collection()} |
                                no_request | no_reply.

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

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

回應中的 Label 等於回應所對應的請求識別碼相關聯的 Label。請求識別碼的 Label 會在 將請求 ID 儲存在集合中時,或在使用 send_request/4 發送請求時相關聯。

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

如果 ReqIdCollection 是空的,則會傳回 no_request

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

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

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

此函數的連結

enter_loop(Module, Options, State)

檢視原始碼
-spec enter_loop(Module :: module(), Options :: [enter_loop_opt()], State :: term()) -> no_return().

等同於 enter_loop(Mod, Options, State, self())

-spec enter_loop(Module :: module(),
                 Options :: [enter_loop_opt()],
                 State :: term(),
                 ServerName :: server_name() | pid()) ->
                    no_return();
                (Module :: module(),
                 Options :: [enter_loop_opt()],
                 State :: term(),
                 How :: timeout() | hibernate | {continue, term()}) ->
                    no_return().

使呼叫程序成為 gen_server 程序。

使用與 enter_loop(Module, Options, State, ServerName, infinity) 等效的引數 ServerName

使用與 enter_loop(Module, Options, State, self(), How) 等效的引數 How

-spec enter_loop(Module :: module(),
                 Options :: [enter_loop_opt()],
                 State :: term(),
                 ServerName :: server_name() | pid(),
                 Timeout :: timeout()) ->
                    no_return();
                (Module :: module(),
                 Options :: [enter_loop_opt()],
                 State :: term(),
                 ServerName :: server_name() | pid(),
                 Hibernate :: hibernate) ->
                    no_return();
                (Module :: module(),
                 Options :: [enter_loop_opt()],
                 State :: term(),
                 ServerName :: server_name() | pid(),
                 Cont :: {continue, term()}) ->
                    no_return().

使呼叫程序成為 gen_server 程序。

不傳回任何值,而是呼叫程序進入 gen_server 程序接收迴圈並成為 gen_server 程序。此程序必須已使用 proc_lib 中的其中一個啟動函式啟動。使用者負責程序的任何初始化,包括為其註冊名稱。

當需要比 gen_server Module:init/1; 回呼提供的更複雜的初始化程序時,此函式很有用。

ModuleOptionsServerName 的意義與呼叫 start[_link|_monitor]/3,4 時相同,或是 ServerName 可以是匿名伺服器的 self/0,這與呼叫沒有 ServerName 引數的 enter_loop/3,4 函式相同。但是,如果指定了 ServerName(而不是 self/0),則必須在呼叫此函式之前,依據此名稱註冊程序。

StateTimeoutHibernateCont 的意義與 Module:init/1 的回傳值相同,當使用 enter_loop/3,4,5不會呼叫此回傳值。請注意,為了遵守 gen_server 行為,需要定義此類回呼函式,而且它也可能是在透過 proc_lib 啟動 gen_server 程序時使用的函式,然後成為呼叫 enter_loop/3,4,5 的函式。但是,如果例如在錯誤情況下,此類 Module:init/1 函式無法呼叫 enter_loop/3,4,5,則應傳回符合 Module:init/1 的型別規格的值,例如 ignore,儘管在傳回至產生函式時,該值將會遺失。

如果呼叫程序不是由 proc_lib 啟動函式啟動,或是未根據 ServerName 註冊,則此函式會失敗。

此函數的連結

multi_call(Name, Request)

檢視原始碼
-spec multi_call(Name :: atom(), Request :: term()) ->
                    {Replies :: [{Node :: node(), Reply :: term()}], BadNodes :: [node()]}.

平行呼叫多個節點上的伺服器。

等同於 multi_call(Nodes, Name, Request),其中 Nodes 是連線至呼叫節點的所有節點,包括呼叫節點本身。

此函數的連結

multi_call(Nodes, Name, Request)

檢視原始碼
-spec multi_call(Nodes :: [node()], Name :: atom(), Request :: term()) ->
                    {Replies :: [{Node :: node(), Reply :: term()}], BadNodes :: [node()]}.

等同於 multi_call(Nodes, Name, Request, infinity)

此函數的連結

multi_call(Nodes, Name, Request, Timeout)

檢視原始碼
-spec multi_call(Nodes :: [node()], Name :: atom(), Request :: term(), Timeout :: timeout()) ->
                    {Replies :: [{Node :: node(), Reply :: term()}], BadNodes :: [node()]}.

平行呼叫多個節點上的伺服器。

透過先將請求傳送到節點,然後等待回覆,對指定節點上所有本地註冊為 Namegen_server 程序進行同步呼叫。節點上的 gen_server 程序會呼叫 Module:handle_call/3 來處理請求。

此函式會傳回元組 {Replies, BadNodes},其中 Replies{Node, Reply} 元組的清單,而 BadNodes 則是不存在、Name 不是已註冊的 gen_server 或未回覆的節點清單。

Nodes 是要將請求傳送至的節點名稱清單。

Name 是每個 gen_server 程序的本地註冊名稱。

Request 是作為第一個引數傳遞給 Module:handle_call/3 的任何術語。

Timeout 是一個整數,指定等待所有回覆的毫秒數,或是使用原子 infinity 來無限期等待。如果在指定的時間內沒有收到來自節點的回覆,該節點會被加入到 BadNodes 中。

當從節點 Node 上的 gen_server 處理程序收到回覆 Reply 時,{Node,Reply} 會被加入到 Replies 中。Reply 是從 Module:handle_call/3 的返回值傳遞而來的。

警告

如果其中一個節點無法處理監控,例如 C 或 Java 節點,並且 gen_server 處理程序在發送請求時尚未啟動,但在 2 秒內啟動,此函數會等待整個 Timeout 時間,這可能是無限長。

如果所有節點都是 Erlang 節點,則不會有這個問題。

為了防止延遲的回應(在超時之後)污染呼叫者的訊息佇列,會使用一個中間處理程序來執行呼叫。當延遲的回應到達已終止的中間處理程序時,它們會被丟棄。

此函數的連結

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(), server_ref()}},
                              Result :: Response | timeout.

接收請求回應。

接收與請求識別碼 ReqId 相對應的回應。該請求必須是由 send_request/2 發出的,並且必須由呼叫此函數的同一個處理程序發出。

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

回傳值 Reply 是從 Module:handle_call/3 的回傳值傳遞而來。

如果 gen_server 在發送回覆之前死掉,則該函數會回傳錯誤。

receive_response/2wait_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(), server_ref()}},
                              Result ::
                                  {Response,
                                   Label :: term(),
                                   NewReqIdCollection :: request_id_collection()} |
                                  no_request | timeout.

接收集合中的請求回應。

ReqIdCollection 中接收回應。ReqIdCollection 的所有請求識別碼都必須對應於使用 send_request/2send_request/4 發出的請求,並且所有請求都必須由呼叫此函數的處理程序發出。

回應中的 Label 是與回應對應的請求識別碼相關聯的 Label。請求識別碼的 Label 在將請求 ID 加入集合時,或使用 send_request/4 發送請求時相關聯。

receive_response/2 相比,與特定請求識別碼相關聯的返回結果或異常將被包裝在一個三元組 {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,則與 Label 的關聯會從結果的 NewReqIdCollection 中的 ReqIdCollection 中刪除。如果 Deletefalse,則 NewReqIdCollection 將等於 ReqIdCollection。請注意,刪除關聯並非免費的,並且包含已處理請求的集合仍然可以被後續的 receive_response/3check_response/3wait_response/3 呼叫使用。

然而,如果不刪除已處理的關聯,上述呼叫將無法檢測到何時不再有未處理的請求,因此您必須以其他方式追蹤這一點,而不是依賴 no_request 返回值。請注意,如果您將僅包含已處理或已放棄請求的關聯的集合傳遞給此函數,它將始終阻塞直到 Timeout 過期,然後回傳 timeout

-spec reply(Client :: from(), Reply :: term()) -> ok.

向用戶端傳送回覆。

當回覆無法在 Module:handle_call/3 的返回值中傳遞時,gen_server 處理程序可以使用此函數來顯式地將回覆發送給呼叫 call/2,3multi_call/2,3,4 的用戶端。

Client 必須是提供給 handle_call/3 回呼函數的 From 參數。Reply 是傳回給用戶端作為 call/2,3multi_call/2,3,4 返回值的任何 term。

此函數的連結

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 並將 Label 與請求識別碼關聯,方法是將此資訊加入到 ReqIdCollection 並回傳結果的請求識別碼集合。

此函數的連結

reqids_new()

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

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

回傳一個新的空請求識別碼集合。請求識別碼集合可以用於處理多個未完成的請求。

使用 send_request/2 發出的請求的請求識別碼可以使用 reqids_add/3 儲存在集合中。此類請求識別碼集合稍後可以用於取得集合中與請求相對應的一個回應,方法是將該集合作為參數傳遞給 receive_response/3wait_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(ServerRef, Request)

查看原始碼 (自 OTP 23.0 起)
-spec send_request(ServerRef :: server_ref(), Request :: term()) -> ReqId :: request_id().

傳送非同步 call 請求。

Request 發送到由 ServerRef 識別的 gen_server 處理程序,並回傳請求識別碼 ReqId

返回值 ReqId 稍後應與 receive_response/2wait_response/2check_response/2 一起使用,以提取請求的實際結果。除了直接將請求識別碼傳遞給這些函數之外,它也可以使用 reqids_add/3 儲存在請求識別碼集合中。此類請求識別碼集合稍後可以用於取得集合中與請求相對應的一個回應,方法是將該集合作為參數傳遞給 receive_response/3wait_response/3check_response/3。如果您打算將請求識別碼儲存在集合中,您可能需要考慮改用 send_request/4

呼叫 gen_server:receive_response(gen_server:send_request(ServerRef, Request), Timeout) 可以視為等效於 gen_server:call(ServerRef, Request, Timeout),忽略錯誤處理。

gen_server 處理程序會呼叫 Module:handle_call/3 來處理請求。

請參閱類型 server_ref/0 以了解 ServerRef 的可能值。

Request 是作為第一個引數傳遞給 Module:handle_call/3 的任何術語。

此函數的連結

send_request(ServerRef, Request, Label, ReqIdCollection)

查看原始碼 (自 OTP 25.0 起)
-spec send_request(ServerRef :: server_ref(),
                   Request :: term(),
                   Label :: term(),
                   ReqIdCollection :: request_id_collection()) ->
                      NewReqIdCollection :: request_id_collection().

傳送非同步 call 請求,並將其新增至請求識別碼集合。

Request 發送到由 ServerRef 識別的 gen_server 處理程序。Label 將與操作的請求識別碼相關聯,並添加到回傳的請求識別碼集合 NewReqIdCollection 中。該集合稍後可以用於取得集合中與請求相對應的一個回應,方法是將該集合作為參數傳遞給 receive_response/3wait_response/3check_response/3

與呼叫 reqids_add(send_request(ServerRef, Request), Label, ReqIdCollection) 相同,但效率稍高。

此函數的連結

start(Module, Args, Options)

檢視原始碼
-spec start(Module :: module(), Args :: term(), Options :: [start_opt()]) -> start_ret().

啟動伺服器,既不連結也不註冊。

start/4 相同,除了 gen_server 處理程序沒有在任何 名稱服務 中註冊。

此函數的連結

start(ServerName, Module, Args, Options)

檢視原始碼
-spec start(ServerName :: server_name(), Module :: module(), Args :: term(), Options :: [start_opt()]) ->
               start_ret().

啟動伺服器,既不連結也不註冊。

建立一個獨立的 gen_server 處理程序,也就是一個不屬於監管樹的 gen_server 處理程序,因此沒有監管者。

其他請參閱 start_link/4

此函數的連結

start_link(Module, Args, Options)

檢視原始碼
-spec start_link(Module :: module(), Args :: term(), Options :: [start_opt()]) -> start_ret().

啟動伺服器,已連結但未註冊。

start_link/4 相同,除了 gen_server 處理程序沒有在任何 名稱服務 中註冊。

此函數的連結

start_link(ServerName, Module, Args, Options)

檢視原始碼
-spec start_link(ServerName :: server_name(),
                 Module :: module(),
                 Args :: term(),
                 Options :: [start_opt()]) ->
                    start_ret().

啟動伺服器,已連結但未註冊。

建立一個 gen_server 程序,作為監督樹的一部分。此函數應由監督者直接或間接呼叫。例如,它確保 gen_server 程序以連結到呼叫者(監督者)的方式產生。

gen_server 程序會呼叫 Module:init/1 進行初始化。為了確保同步的啟動程序,start_link/3,4 會等到 Module:init/1 返回或失敗後才會返回。

ServerName 指定伺服器名稱的註冊名稱和方式。有關不同的名稱註冊,請參閱 server_name/0 類型。

Module 是回呼模組的名稱。

Args 是傳遞給 Module:init/1 的任何項。

有關啟動 gen_server 程序的 Options,請參閱 start_opt/0 類型。

有關此函數的返回值描述,請參閱 start_ret/0 類型。

如果 start_link/3,4 返回 ignore{error, _},則啟動的 gen_server 程序已終止。如果由於程序連結而將 'EXIT' 訊息傳遞給呼叫程序,則該訊息已被消耗。

警告

在 OTP 26.0 之前,如果啟動的 gen_server 程序從 Module:init/1 返回例如 {stop, Reason},則此函數可能會在啟動的 gen_server 程序終止之前返回 {error, Reason},因此再次啟動可能會失敗,因為 VM 資源(例如已註冊的名稱)尚未取消註冊。稍後可能會將 'EXIT' 訊息傳遞給呼叫此函數的程序。

但是,如果啟動的 gen_server 程序在 Module:init/1 期間失敗,則程序連結 {'EXIT', Pid, Reason} 訊息會導致此函數返回 {error, Reason},因此 'EXIT' 訊息已被消耗,並且啟動的 gen_server 程序已終止。

由於無法從 start_link/3,4 的返回值中分辨這兩種情況之間的差異,因此此不一致之處已在 OTP 26.0 中解決。

Module:init/1 返回 {stop, _}{error, _} 之間的差異在於,{error, _} 會導致正常(「靜默」)終止,因為 gen_server 程序會以原因 normal 退出。

此函數的連結

start_monitor(Module, Args, Options)

檢視原始碼 (自 OTP 23.0 起)
-spec start_monitor(Module :: module(), Args :: term(), Options :: [start_opt()]) -> start_mon_ret().

啟動伺服器,已監控但既未連結也未註冊。

等同於 start_monitor/4,但 gen_server 程序未在任何 名稱服務中註冊。

此函數的連結

start_monitor(ServerName, Module, Args, Options)

檢視原始碼 (自 OTP 23.0 起)
-spec start_monitor(ServerName :: server_name(),
                    Module :: module(),
                    Args :: term(),
                    Options :: [start_opt()]) ->
                       start_mon_ret().

啟動伺服器,已監控且已註冊,但未連結。

建立一個獨立的 gen_server 程序,也就是說,一個不屬於監督樹(因此沒有監督者)的 gen_server 程序,並自動設定一個監視器來監視新建立的伺服器。

除此之外,請參閱 start_link/3,4。請注意,成功啟動的返回值不同,它會返回一個監視器 reference。請參閱 start_mon_ret/0 類型。

如果啟動不成功,則呼叫者將被封鎖,直到收到監視器的 'DOWN' 訊息並從訊息佇列中移除。

此函數的連結

stop(ServerRef)

檢視原始碼 (自 OTP 18.0 起)
-spec stop(ServerRef :: server_ref()) -> ok.

等同於 stop(ServerRef, normal, infinity)

此函數的連結

stop(ServerRef, Reason, Timeout)

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

停止伺服器。

命令由 ServerRef 指定的通用伺服器以指定的 Reason 退出,並等待其終止。gen_server 程序在退出前會呼叫 Module:terminate/2

如果伺服器以預期的原因終止,則該函數返回 ok。除了 normalshutdown{shutdown,Term} 之外的任何其他原因都會導致使用 logger 發出錯誤報告。具有相同原因的退出訊號會傳送至連結的程序和埠。

Timeout 是一個整數,指定等待伺服器終止的毫秒數,或是原子 infinity 以無限期等待。如果伺服器未在指定時間內終止,則呼叫會以原因 timeout 退出呼叫程序。

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

此函數的連結

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(), server_ref()}},
                           Result :: Response | timeout.

等待請求回應。

等待請求識別碼 ReqId 的回應。請求必須由 send_request/2 發出,並且必須由呼叫此函數的同一程序發出。

WaitTime 指定等待回覆的時間長度。如果在指定時間內未收到回覆,則函數返回 timeout,並且不執行任何清除。因此,可以重複調用該函數,直到返回回覆為止。

回傳值 Reply 是從 Module:handle_call/3 的回傳值傳遞而來。

如果 gen_server 在發送回覆之前死掉,則該函數會回傳錯誤。

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(), server_ref()}},
                           Result ::
                               {Response,
                                Label :: term(),
                                NewReqIdCollection :: request_id_collection()} |
                               no_request | timeout.

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

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

回應中的 Label 是與回應對應的請求識別碼相關聯的 Label。請求識別碼的 Label 在將請求 ID 加入集合時,或使用 send_request/4 發送請求時相關聯。

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