Erlang explained: Selective receive
If you worked with Erlang you've probably heard about selective receive. But do you actually know how it works? I want to post here an excerpt from Joe Armstrong's book Programming Erlang where he explains how it works exactly (Section 8.6, p.153):
receive
Pattern1 [when Guard1] -> Expressions1;
Pattern2 [when Guard2] -> Expressions2;
...
after
Time -> ExpressionTimeout
end
When we enter a receive statement, we start a timer (but only if an after section is present in the expression).
Take the first message in the mailbox and try to match it against Pattern1, Pattern2, and so on. If the match succeeds, the message is removed from the mailbox, and the expressions following the pattern are evaluated.
If none of the patterns in the receive statement matches the first message in the mailbox, then the first message is removed from the mailbox and put into a "save queue." The second message in the mailbox is then tried. This procedure is repeated until a matching message is found or until all the messages in the mailbox have been examined.
If none of the messages in the mailbox matches, then the process is suspended and will be rescheduled for execution the next time a new message is put in the mailbox. Note that when a new message arrives, the messages in the save queue are not rematched; only the new message is matched.
As soon as a message has been matched, then all messages that have been put into the save queue are reentered into the mailbox in the order in which they arrived at the process. If a timer was set, it is cleared.
If the timer elapses when we are waiting for a message, then evaluate the expressions ExpressionsTimeout and put any saved messages back into the mailbox in the order in which they arrived at the process.
Did you notice the concept of "save queue"? That's what many people are not aware of. Let's play with various scenarios and see the mailbox and save queue in action.
The first scenario is simple, nothing to test there in regards to mailbox. The second one is also straightforward:
1> self() ! a.
a
2> process_info(self()).
...
{message_queue_len,1},
{messages,[a]},
...
3> receive a -> 1; b -> 2 end.
1
4> process_info(self()).
...
{message_queue_len,0},
{messages,[]},
...
You send a message to the shell, you see it in the process mailbox, then you receive it by matching, after which the queue is empty. Standard queue behaviour.
Now let's test scenario 3,5:
1> self() ! c, self() ! d, self() ! a.
a
2> process_info(self()).
...
{message_queue_len,3},
{messages,[c,d,a]},
...
3> receive a -> 1; b -> 2 end.
1
4> process_info(self()).
...
{message_queue_len,2},
{messages,[c,d]},
...
Again, no surprises. Actually, this example demonstrates what people think when they hear about selective receive. Unfortunately we don't see what happened internally between lines 3 and 4. We are going to investigate it now by testing scenario 3,4.
This time start the shell in distributed mode so that we can connect to it later from the remote shell.
(foo@bar)1> register(shell, self()).
true
(foo@bar)2> shell ! c, shell ! d.
d
(foo@bar)3> process_info(whereis(shell)).
...
{current_function,{erl_eval,do_apply,5}},
...
{message_queue_len,2},
{messages,[c,d]},
...
(foo@bar)4> receive a -> 1; b -> 2 end.
At this moment the shell is suspended - we are exactly at step 4. Go to remote shell, and type the following:
(foo@bar)1> process_info(whereis(shell)).
...
{current_function,{erl_eval,receive_clauses,6}},
...
{message_queue_len,0},
{messages,[]},
...
That's interesting: no messages in the mailbox. As Joe said, they are in the save queue. Now send a matching message:
(foo@bar)2> shell ! a.
a
Go back to initial shell, which should be resumed now, and check the mailbox again:
1
(foo@bar)5> process_info(whereis(shell)).
...
{current_function,{erl_eval,do_apply,5}},
...
{message_queue_len,2},
{messages,[c,d]},
...
That's what we saw in the previous test, but now you know what happens behind the scenes: messages are moved from the mailbox to the save queue and then back to the mailbox after the matching message arrives.
Now you should understand better how selective receive works. Next time you explore your Erlang process, keep in mind the save queue and disappearing and reappearing messages.
相关推荐
queue.cpp -- function definitions for the Array implementation of a Queue
在使用Subversion(SVN)版本控制系统的过程中,有时会遇到“Failed to run the WC DB work queue”的错误提示,这通常是由于工作副本(Working Copy)数据库出现问题导致的。SVN使用SQLite3作为其本地数据库来存储...
1.将sqlite3.exe放到.svn的同级目录 2.启动cmd执行sqlite3 .svn/wc.db 3. "select * from work_queue"; 4. delete from work_queue; 5.svn目录下右键:TortoiseSVN->Clean up
THis is an example source code for the queue implemented by systemc.
C语言头文件 QUEUE.HC语言头文件 QUEUE.HC语言头文件 QUEUE.HC语言头文件 QUEUE.HC语言头文件 QUEUE.HC语言头文件 QUEUE.HC语言头文件 QUEUE.HC语言头文件 QUEUE.HC语言头文件 QUEUE.HC语言头文件 QUEUE.HC语言...
This letter presents the recursive formulas of the moments of queue length for the M/M/1 queue and M/M/1/B queue, respectively. The higher moments of queue length are important for optimization ...
We provide plenty of examples along the way to help you understand each concept. You will get the also get a clear picture of reactive programming, binary searches, sorting, search trees, undirected ...
A very good book! You can loaddown then take it back home and Study!
The 80x86 MOV Instruction 4.8 - Some Final Comments on the MOV Instructions <br>4.9 Laboratory Exercises 4.9.1 The UCR Standard Library for 80x86 Assembly Language Programmers 4.9.2 ...
SAFMQ,即Save and Forward Message Queue,是一种基于C/C++编程语言实现的消息中间件。它在版本8.0中提供了强大的功能和性能优化,旨在为分布式系统提供可靠、高效的消息传递服务。作为一个专业的IT大师,我们将...
Apache Hadoop YARN is the modern distributed operating system for big data applications....And you’ll leave with all the knowledge of how to upgrade painlessly from 2.x to 3.x to get all the benefits.
On the Spark Streaming front, two major features have been added: mapWithState to maintain state across batches and using back pressure to throttle the input rate in case of queue buildup.2 In ...
在"Implementation-of-the-Queue-Interface-master.zip"文件中,我们可以预见到源码可能包含一个或多个类,这些类实现了队列接口。这些类可能使用不同的数据结构来存储元素,例如数组、链表或者双端队列(deque)。...
MessageQueue,又称消息队列,是C#中处理异步通信和解耦组件的重要技术。它允许应用程序之间通过消息传递数据,而无需彼此直接交互。下面将详细介绍C#中的MessageQueue以及如何使用它来发送和接收消息。 1. **...
'description' => 'Listen the queue', 'options' => [ 'connection' => ['short' => 'c', 'help' => 'Queue connection name'], ], ], ]); ``` 通过运行`php build.php queue:listen`命令,即可启动队列监听器...
标题 "解决Can't locate ThreadQueue.pm" 指出的问题是,在尝试运行一个Perl脚本时,系统无法找到模块“ThreadQueue”。这个问题通常出现在你试图使用一个依赖于ThreadQueue模块的Perl程序,但该模块尚未在你的Perl...
Queue 与 Topic 的比较 Queue 和 Topic 是 JMS(Java Message Service)中两种基本的消息模式,分别对应 Point-to-Point 和 Publish/Subscribe 模式。 Queue 模式 在 Queue 模式中,一条消息仅能被一个消费者...
Queue-Queue-Queue
The availability of drivers that support the features of the specification will simplify the process of developing Windows appli¬cation programs that in-corporate absolute coordinate input, and ...
throw std::out_of_range("Queue is empty"); } return queue.front(); } bool empty() const { return queue.empty(); } int size() const { return queue.size(); } }; ``` 以上两种方法都能有效地...