2011-06-14 140 views
4

我正在尋找erlang的好例子異步使用gen_server處理消息:cast/2。使用gen_server處理Erlang異步消息:cast/2

我見過的OTP SSH模塊,它接收到一個請求通過 模塊中的一個示例:handle_cast/2,它保持在模塊的一個本地隊列,後來發回對應於該請求的應答消息,通過明確地向呼叫者發送消息。當我試圖閱讀它時,我幾乎無法跟蹤代碼,並且無法理解這個想法。

讚賞一段僞代碼。

+0

這似乎說明它cast'和'call''之間的差異:http://bytefilia.com/gen_server-synchronous-vs-asynchronous/ – Stratus3D 2014-06-27 19:41:02

回答

5

我相信你指的是ssh_connection_manager模塊。

執行gen_server:cast/2時,將在Module:handle_cast/2函數中處理該請求。幾件事情要注意這裏:

  • handle_cast參數你沒有有關發件人的信息,所以你不能 - 除非你發送郵件本身這個信息 - 發回了一些成績吧。
  • 客戶在發出gen_server:cast/2後,不會等待回覆。實際上,它甚至不關心消息是否到達(有一些例外)。
  • handle_cast/2,你可以返回一個noreply停止元組,所以沒辦法返回一個答覆那裏。

說,你一直在尋找的應該(簡化的東西)的代碼背後的想法:

  • 初始同步gen_server:call/2
  • 客戶端的是傳遞給服務器並保存到其狀態(實際上,似乎用該參數創建了一個額外的過程)。這個技巧在你不能計算handle_call時的返回值時很有用。
  • 在這一點上,你有兩種可能,這取決於如果你需要更多的信息來計算從其他客戶端(A)你的結果或來自同一客戶(B):

    • A.返回類似{ noreply NewState}在handle_call中。這將使您有可能在客戶仍然持有的情況下處理其他請求。當結果準備就緒時,您可以使用gen_server:reply()將其發送回客戶端。
    • B.將{reply,ok,State}返回給客戶端。客戶端將繼續執行,也許執行一系列cast/2。然後,客戶會用新的gen_server:call/2詢問最終結果。
+0

感謝您的澄清。現在我記得代碼的流程。我應該寫這個ssh本身就是一種行爲。 – jj1bdx 2011-06-15 12:45:17

+0

當你的意思是客戶端仍在持有時,你的意思是客戶端被阻止並且無法繼續執行?有沒有辦法阻止它?可以得到延期回覆嗎?或者最好是像jj1bdx說的那樣創建一個自定義行爲? – Ale 2011-06-29 12:55:31

+0

我認爲這可能有助於http://www.trapexit.org/Building_Non_Blocking_Erlang_apps – Ale 2011-06-29 13:05:06

4

通常情況下,您不希望發送劇組時直接回復,否則您會使用gen_server:call。

一個真實世界的例子,我有一個gen_server來處理一些「通道」,並且有很多用來追加通道名稱到錯誤記錄。頻道名稱存儲在gen_server的狀態中。爲了不耽誤誰想要登錄我不使用「獲取名稱」錯誤的過程中同步調用來獲取名稱的預先準備,但發送的郵件,用石膏:

error(Pid, Tags) -> 
    gen_server:cast(Pid, {log, error_report, Tags}). 

warning(Pid, Tags) -> 
    gen_server:cast(Pid, {log, warning_report, Tags}). 

info(Pid, Tags) -> 
    gen_server:cast(Pid, {log, info_report, Tags}). 

演員被處理在一個非常簡單的處理程序中,不會返回。

handle_cast({log, Report, Tags}, #state{name=Name}=State) -> 
    error_logger:Report([{chan, Name} | Tags]), 
    {noreply, State}; 

如果你有異步消息發回,這是完全獨立的施法的處理。您無論如何都需要知道在哪裏發送這些消息,您必須以某種方式將這些消息存儲在State中,或者您使用的是固定名稱。

通常情況下,你不應該只是發送一條消息,而是調用接收處理模塊的函數(這可能是另一個強制轉換或簡單的消息發送)。

+0

感謝您的解釋。 – jj1bdx 2011-06-15 12:46:32