消息筛选
创建消息块对象时,可以提供一个筛选器函数来确定消息块是接受还是拒绝消息。 筛选器函数是保证消息块仅接收特定值的有效方式。
以下示例演示如何创建一个使用筛选器函数来仅接受偶数的 unbounded_buffer 对象。 unbounded_buffer 对象会拒绝奇数,因此不会将奇数传播到其目标块。
// filter-function.cpp
// compile with: /EHsc
#include <agents.h>
#include <iostream>
using namespace concurrency;
using namespace std;
int wmain()
{
// Create an unbounded_buffer object that uses a filter
// function to accept only even numbers.
unbounded_buffer<int> accept_evens(
[](int n) {
return (n%2) == 0;
});
// Send a few values to the unbounded_buffer object.
unsigned int accept_count = 0;
for (int i = 0; i < 10; ++i)
{
// The asend function returns true only if the target
// accepts the message. This enables us to determine
// how many elements are stored in the unbounded_buffer
// object.
if (asend(accept_evens, i))
{
++accept_count;
}
}
// Print to the console each value that is stored in the
// unbounded_buffer object. The unbounded_buffer object should
// contain only even numbers.
while (accept_count > 0)
{
wcout << receive(accept_evens) << L' ';
--accept_count;
}
}
该示例产生下面的输出:
0 2 4 6 8
筛选器函数可以是 lambda 函数、函数指针或函数对象。 每个筛选器函数采用以下格式之一。
bool (T)
bool (T const &)
为了消除不必要的数据复制,需要按值传播聚合类型时,请使用第二种格式。消息筛选支持数据流编程模型,其中的组件在接收数据时会执行计算。
消息保留
消息保留使消息块能够保留消息供以后使用。 通常,消息保留不是直接使用的。 但是,了解消息预留有助于更好地了解某种预定义消息块类型的行为。
考虑非贪婪和贪婪联接。 这两种联接都使用消息保留来保留消息供以后使用。 如前所述,非贪婪联接分两个阶段接收消息。 在第一阶段,非贪婪 join 对象等待其每个源接收消息。 然后,非贪婪联接尝试保留其中的每个消息。 如果它可以保留每条消息,则会使用所有消息并将其传播到目标。 否则,它会释放或取消消息保留,并再次等待每个源接收消息。
贪婪联接也从多个源读取输入消息,它使用消息保留来读取其他消息,同时等待从每个源接收消息。 例如,考虑一个从消息块 A 和 B 接收消息的贪婪联接。 如果贪婪联接从 B 收到了两条消息,但尚未收到来自 A 的消息,则贪婪联接会保存来自 B 的第二条消息的唯一消息标识符。 在贪婪联接收到来自 A 的消息并传播这些消息后,它会使用保存的消息标识符来查看来自 B 的第二条消息是否仍然可用。
当你实现自己的自定义消息块类型时,可以使用消息保留。
send 和 asend
concurrency::send 函数可将消息同步发送到指定目标,concurrency::asend 函数可将消息异步发送到指定目标。 send 和 asend 函数都会等待,直到目标指示它最终将接受或拒绝消息。
send 函数会等到目标接受或拒绝消息,然后再返回。 如果消息已传递,则 send 函数返回 true,否则返回 false。 由于 send 函数是同步工作的,因此 send 函数在返回之前会等待目标接收消息。
相反,asend 函数在返回之前不会等待目标接受或拒绝消息。 如果目标接受消息并且最终将接收该消息,则 asend 函数返回 true。 否则,asend 返回 false,指示目标拒绝了消息或推迟了有关是否接收消息的决定。
receive 和 try_receive
concurrency::receive 和 concurrency::try_receive 函数从给定的源读取数据。 receive 函数会等待数据变为可用,而 try_receive 函数会立即返回。
如果必须具有数据才能继续操作,请使用 receive 函数。 如果不能阻止当前上下文,或者不需要数据就能继续操作,请使用 try_receive 函数。