2011-10-21 58 views

回答

4

對於receive超時,您應該可以使用0。在下面的例子中,它將嘗試從隊列中獲取消息,如果沒有消息,它將返回原子false

1> receive _ -> true 
1> after 0 -> 
1> false 
1> end. 
empty 

被警告這消耗的消息。

另一種方法是使用erlang:process_info,但這只是用於調試。

6> {message_queue_len, QueueLen} = erlang:process_info(self(), message_queue_len). 
{message_queue_len,0} 
7> QueueLen. 
0 

共現:

16> HasMessages = fun(Pid) ->           
16>  element(2, erlang:process_info(Pid, message_queue_len)) > 0  
16> end. 
#Fun<erl_eval.6.80247286> 
17> HasMessages(self()).                  
false 
18> self() ! test. 
test 
19> HasMessages(self()). 
true 
+0

對不起,但你的回答是錯誤的。您的代碼浪費了一條消息,從而破壞了任何計算的正確性。 –

+0

有兩個答案,請仔細閱讀。 –

+0

此外,還有一個警告消息會消失。 –

1

在內部有裝置來測試是否存在的過程中信箱的消息。

但要小心!我不認爲厄蘭是這樣使用的:

{module, hasMsg}. 
{exports, [{module_info,0},{module_info,1},{hasMsg,0},{peekMsg,1},{lastMsg,1}]}. 
{attributes, []}. 
{labels, 17}. 

{function, hasMsg, 0, 2}. 
    {label,1}. 
     {func_info,{atom,hasMsg},{atom,hasMsg},0}. 
    {label,2}. 
     {loop_rec,{f,4},{x,0}}. 
     {move,{atom,true},{x,0}}. 
     return. 
    {label,3}. 
     {loop_rec_end,{f,2}}. 
    {label,4}. 
     timeout. 
     {move,{atom,false},{x,0}}. 
     return. 

{function, peekMsg, 1, 6}. 
    {label,5}. 
     {func_info,{atom,hasMsg},{atom,peekMsg},1}. 
    {label,6}. 
     {loop_rec,{f,8},{x,0}}. 
     return. 
    {label,7}. 
     {loop_rec_end,{f,6}}. 
    {label,8}. 
     timeout. 
     return. 

{function, lastMsg, 1, 10}. 
    {label,9}. 
     {func_info,{atom,hasMsg},{atom,lastMsg},1}. 
    {label,10}. 
     {loop_rec,{f,12},{x,0}}. 
     {test,is_eq_exact,{f,11},[]}. 
    {label,11}. 
     {loop_rec_end,{f,10}}. 
    {label,12}. 
     timeout. 
     return. 

{function, module_info, 0, 14}. 
    {label,13}. 
     {func_info,{atom,hasMsg},{atom,module_info},0}. 
    {label,14}. 
     {move,{atom,hasMsg},{x,0}}. 
     {call_ext_only,1,{extfunc,erlang,get_module_info,1}}. 

{function, module_info, 1, 16}. 
    {label,15}. 
     {func_info,{atom,hasMsg},{atom,module_info},1}. 
    {label,16}. 
     {move,{x,0},{x,1}}. 
     {move,{atom,hasMsg},{x,0}}. 
     {call_ext_only,2,{extfunc,erlang,get_module_info,2}}. 

編譯:erlc +from_asm hasMsg.S

模塊hasMsg包含:

  • hasMsg/0返回一個布爾值是否有郵箱中的郵件。
  • peekMsg/1返回最舊的消息而不刪除它。如果郵箱爲空,則返回它的參數。
  • lastMsg/1返回最新的消息而不刪除它。如果郵箱爲空,則返回它的參數。
+2

我不會這樣做,除非你有自殺傾向和愛彙編黑客。這些說明沒有定義,也沒有保證。我在下面給出一個更簡潔的方法。 – rvirding

+0

@rvirding,我永遠不會使用這樣的代碼。我只想看看是否有可能。黑客到極限。 ;)我會說一個人的算法徹底壞了,如果有人要查看郵箱中最新或最舊的郵件...... – kay

9

您可以使用process_info/2 BIF訪問過程信息,包括消息隊列。所以

process_info(self(), message_queue_len) => {message_queue_len,Length} 

process_info(self(), messages) => {messages,MessageList} 

如果在隊列中許多消息對於每個調用創建列表中的第二個是無效的(雖然不是當然的消息)。有很多有趣的事情你可以找到一個過程。您可以獲取信息的過程沒有限制,您可以爲任何過程執行此過程。