Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Checking whether mailbox is empty? in erlang

Tags:

erlang

I need to do a check, which returns true or false, depending on whether the current process has any message in its mailbox in erlang.

like image 426
damned Avatar asked Oct 21 '11 15:10

damned


3 Answers

You can use the process_info/2 BIF to access process information including the message queue. So

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

and

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

The second one is inefficient if there are many messages in the queue as the list is created for each call (though not the messages of course). There are many interesting things you can find out about a process. There are no restrictions on which process you can get info, you can do it for any process.

like image 87
rvirding Avatar answered Oct 09 '22 04:10

rvirding


You should be able to use 0 for the receive timeout. In the example below, it will try to get a message out of the queue, if there are none in there it will return the atom false.

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

Be warning this will consume a message.

One other way would be to use erlang:process_info but this is supposedly only for debugging.

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

Altogether now:

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
like image 42
Matt Williamson Avatar answered Oct 09 '22 03:10

Matt Williamson


Internally there are means to test if there is a message in the process mailbox.

But beware! I don't think Erlang is meant to be used like that:

{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}}.

Compile: erlc +from_asm hasMsg.S.

The module hasMsg contains:

  • hasMsg/0 returns a boolean whether there are messages in the mailbox.
  • peekMsg/1 returns the oldest message without removing it. Returns its argument, if the mailbox is empty.
  • lastMsg/1 returns the newest message without removing it. Returns its argument, if the mailbox is empty.
like image 30
kay Avatar answered Oct 09 '22 03:10

kay