分享方式:


如何:使用訊息區篩選條件

本檔示範如何使用篩選函式,讓非同步消息區塊根據該訊息的承載來接受或拒絕訊息。

當您建立訊息區塊物件,例如 concurrency::unbounded_buffer concurrency::call concurrency::transformer 時,您可以提供 篩選 函式來判斷消息塊是否接受或拒絕訊息。 篩選函式是保證訊息區塊只接收特定值的實用方式。

篩選函式很重要,因為它們可讓您連接消息塊以形成 資料流程網路 。 在資料流程網路中,訊息會藉由只處理符合特定準則的訊息來控制資料流程。 比較這與控制流程模型,其中資料流程會使用條件陳述式、迴圈等控制結構進行管制。

本檔提供如何使用訊息篩選的基本範例。 如需使用訊息篩選準則和資料流程模型來連接訊息區塊的其他範例,請參閱 逐步解說:建立資料流程代理程式和 逐步解說:建立映射處理網路

範例:count_primes函式

請考慮下列函式, count_primes 其中說明不會篩選傳入訊息的訊息區塊基本用法。 消息塊會將質數附加至 std::vector 物件。 函 count_primes 式會將數個數字傳送至訊息區塊、接收來自消息塊的輸出值,並將那些為主機的質數列印。

// Illustrates usage of a message buffer that does not use filtering.
void count_primes(unsigned long random_seed)
{
    // Holds prime numbers.
    vector<unsigned long> primes;

    // Adds numbers that are prime to the vector object.
    transformer<unsigned long, unsigned long> t([&primes](unsigned long n) -> unsigned long
    {
        if (is_prime(n))
        {
            primes.push_back(n);
        }
        return n;
    });

    // Send random values to the message buffer.
    mt19937 generator(random_seed);
    for (int i = 0; i < 20; ++i)
    {
        send(t, static_cast<unsigned long>(generator()%10000));
    }

    // Receive from the message buffer the same number of times
    // to ensure that the message buffer has processed each message.
    for (int i = 0; i < 20; ++i)
    {
        receive(t);
    }

    // Print the prime numbers to the console.
    wcout << L"The following numbers are prime: " << endl;
    for(unsigned long prime : primes)
    {
        wcout << prime << endl;
    }
}

物件 transformer 會處理所有輸入值;不過,它只需要那些是質值。 雖然應用程式可以寫入,讓訊息傳送者只傳送質數,但訊息接收者的需求不一定是已知的。

範例:count_primes_filter函式

下列函式 count_primes_filter 會執行與 函式 count_primes 相同的工作。 不過, transformer 此版本中的物件會使用篩選函式只接受質值。 執行動作的函式只會接收質數;因此,不需要呼叫 函 is_prime 式。

transformer因為物件只接收質數, transformer 因此物件本身可以保存質數。 換句話說, transformer 此範例中的 物件不需要將質數 vector 加入物件。

// Illustrates usage of a message buffer that uses filtering.
void count_primes_filter(unsigned long random_seed)
{
    // Accepts numbers that are prime.
    transformer<unsigned long, unsigned long> t([](unsigned long n) -> unsigned long
    {
        // The filter function guarantees that the input value is prime.
        // Return the input value.
        return n;
    },
    nullptr,
    [](unsigned long n) -> bool
    {
        // Filter only values that are prime.
        return is_prime(n);
    });

    // Send random values to the message buffer.
    mt19937 generator(random_seed);
    size_t prime_count = 0;
    for (int i = 0; i < 20; ++i)
    {
        if (send(t, static_cast<unsigned long>(generator()%10000)))
        {
            ++prime_count;
        }
    }

    // Print the prime numbers to the console. 
    wcout << L"The following numbers are prime: " << endl;
    while (prime_count-- > 0)
    {
        wcout << receive(t) << endl;
    }
}

物件 transformer 現在只會處理質值。 在上一個範例中, transformer 物件會處理所有訊息。 因此,上一個範例必須接收它所傳送的相同訊息數目。 這個範例會使用 concurrency::send 函式的結果 來判斷要從 transformer 物件接收的訊息數目。 當訊息緩衝區接受訊息,以及 false 訊息緩衝區拒絕訊息時,函 send 式會傳回 true 。 因此,訊息緩衝區接受訊息符合質數計數的次數。

範例:已完成的訊息區塊篩選程式代碼範例

下列程式碼顯示完整範例。 此範例會同時 count_primes 呼叫 函式和 函 count_primes_filter 式。

// primes-filter.cpp
// compile with: /EHsc
#include <agents.h>
#include <algorithm>
#include <iostream>
#include <random>

using namespace concurrency;
using namespace std;

// Determines whether the input value is prime.
bool is_prime(unsigned long n)
{
    if (n < 2)
        return false;
    for (unsigned long i = 2; i < n; ++i)
    {
        if ((n % i) == 0)
            return false;
    }
    return true;
}

// Illustrates usage of a message buffer that does not use filtering.
void count_primes(unsigned long random_seed)
{
    // Holds prime numbers.
    vector<unsigned long> primes;

    // Adds numbers that are prime to the vector object.
    transformer<unsigned long, unsigned long> t([&primes](unsigned long n) -> unsigned long
    {
        if (is_prime(n))
        {
            primes.push_back(n);
        }
        return n;
    });

    // Send random values to the message buffer.
    mt19937 generator(random_seed);
    for (int i = 0; i < 20; ++i)
    {
        send(t, static_cast<unsigned long>(generator()%10000));
    }

    // Receive from the message buffer the same number of times
    // to ensure that the message buffer has processed each message.
    for (int i = 0; i < 20; ++i)
    {
        receive(t);
    }

    // Print the prime numbers to the console.
    wcout << L"The following numbers are prime: " << endl;
    for(unsigned long prime : primes)
    {
        wcout << prime << endl;
    }
}

// Illustrates usage of a message buffer that uses filtering.
void count_primes_filter(unsigned long random_seed)
{
    // Accepts numbers that are prime.
    transformer<unsigned long, unsigned long> t([](unsigned long n) -> unsigned long
    {
        // The filter function guarantees that the input value is prime.
        // Return the input value.
        return n;
    },
    nullptr,
    [](unsigned long n) -> bool
    {
        // Filter only values that are prime.
        return is_prime(n);
    });

    // Send random values to the message buffer.
    mt19937 generator(random_seed);
    size_t prime_count = 0;
    for (int i = 0; i < 20; ++i)
    {
        if (send(t, static_cast<unsigned long>(generator()%10000)))
        {
            ++prime_count;
        }
    }

    // Print the prime numbers to the console. 
    wcout << L"The following numbers are prime: " << endl;
    while (prime_count-- > 0)
    {
        wcout << receive(t) << endl;
    }
}

int wmain()
{
    const unsigned long random_seed = 99714;

    wcout << L"Without filtering:" << endl;
    count_primes(random_seed);

    wcout << L"With filtering:" << endl;
    count_primes_filter(random_seed);

    /* Output:
    9973
    9349
    9241
    8893
    1297
    7127
    8647
    3229
    With filtering:
    The following numbers are prime:
    9973
    9349
    9241
    8893
    1297
    7127
    8647
    3229
    */
}

編譯程式碼

複製範例程式碼,並將其貼到 Visual Studio 專案中,或貼到名為 primes-filter.cpp 的檔案中,然後在 Visual Studio 命令提示字元視窗中執行下列命令。

cl.exe /EHsc primes-filter.cpp

穩固程式設計

篩選函式可以是 Lambda 函式、函式指標或函式物件。 每個篩選函式都會採用下列其中一種形式:

bool (T)
bool (T const &)

若要消除不必要的資料複製,當您有以傳值傳輸的匯總類型時,請使用第二個表單。

另請參閱

非同步代理程式程式庫
逐步解說:建立資料流程代理程式
逐步解說:建立影像處理網路
transformer 類別