2010-10-18 43 views
1

我注意到發送到gen_fsm進程的pid的消息在狀態回調中與事件匹配。這是偶然還是我可以依靠這個功能?我可以在gen_fsm狀態回調中處理任何收到的消息嗎?

正常情況下,我希望發送到gen_fsm的常規消息顯示在handle_info/3回調中,並且認爲我必須使用gen_fsm:send_event重新發送消息。

gen_fsm是否嘗試首先將消息與狀態回調匹配,然後用handle_info/3回調進行通信?或者僅當它與狀態回調子句不匹配?

但是,當我嘗試它時,我的消息似乎根據調試輸出處理兩次。

所以基本上這個問題也可以這樣說:如何正確處理接收到的消息作爲gen_fsm狀態函數中的事件?


澄清:,一些事件被獲取傳遞應考慮對這個問題給出的消息出現。

我知道,在很多情況下,它的清潔程度只能通過函數調用進入fsm來使協議可見。

我不太確定這是否會改善上述gen_fsm必須適用的當前框架:每個層調用connect()函數來附加(有時啓動)較低層的各種協議棧。數據包被髮送到較低層,調用一個函數(發送)並由receive收到一條消息。很像gen_tcp。

通過查看gen_fsm的代碼,我已經知道一般消息只傳遞給handle_info,因此只有使用gen_fsm:send_event直接從handle_info/3回調或resent調用狀態函數的問題仍然存在。

+0

我在這裏是否正確理解了你,你是否僅僅將gen_fsm用於某些協議棧而不是全部?如果是這樣,爲什麼?爲什麼不以同樣的方式實現堆棧的所有Erlang部分?這將使您在發送和接收郵件方面保持一致。 – rvirding 2010-10-19 12:52:49

+0

我一直在抱怨{ok,Pid} = connect(),發送(Pid,Data)和接收{resp,Data}消息。所以我在堆棧中不同模塊的API中保持一致。我不一致的地方是目前接收和發送的處理。 – 2010-10-20 09:58:11

+0

但是有很多使用這種範式的先前代碼,所以它試圖改變一切。對堆棧的所有部分不使用gen_fsm的原因是其實際上非常不同的協議(汽車總線協議)通過USB多路複用。所以堆棧的各個部分在gen_server,簡單ad/hoc服務器和無狀態編碼/解碼過濾器以及gen_fsm當然不同。 – 2010-10-20 10:05:03

回答

1

一般信息由handle_info回調處理,除非你在你的代碼是這樣的:

handle_info(信息,Statename的,StateData) - > 模塊:Statename的(信息,StateData)。

它可以避免重新發送,但我不建議這樣做,也不會重新發送。

通過封裝send_event/sync_send_event/send_all_state_event/sync_send_all_state_event的API調用完全傳遞事件使得協議顯式化。哪一個是正確的,因爲使用edoc更容易理解,維護和記錄。

+0

現在,gen_fsm必須適應協議棧的特定架構,它們是沿着模式構建的:較低級別的連接()由較高級別的數據包發送(),但是通過發送到較高級別的消息接收。類似gen_tcp處理連接的方式。所以要麼我改變整個代碼來傳遞迴調,而不是上游的消息,我現在還沒有或者我不得不處理這些消息。 – 2010-10-18 19:47:10

+0

直接撥打 - 速度更快。此外,如果重新發送,如果API與消息傳遞一起使用,則不具有「從單一來源順序交付」的保證。 – probsolver 2010-10-19 10:47:51

+0

謝謝!我已經將它作爲直接函數調用實現,並且與其他代碼很好地匹配。它也像微風一樣工作。 – 2010-10-20 09:51:45

相關問題