Postupy: Použití filtru bloku zpráv

Tento dokument ukazuje, jak pomocí funkce filtru povolit asynchronní blok zpráv přijmout nebo odmítnout zprávu na základě datové části této zprávy.

Při vytváření objektu bloku zprávy, jako je souběžnost::unbounded_buffer, souběžnost::call nebo souběžnost::transformer, můžete zadat funkci filtru, která určuje, jestli blok zpráv přijme nebo odmítne zprávu. Funkce filtru je užitečný způsob, jak zaručit, že blok zpráv přijímá pouze určité hodnoty.

Funkce filtru jsou důležité, protože umožňují připojit bloky zpráv k vytvoření sítí toku dat. V síti toku dat blokují zprávy řízení toku dat zpracováním pouze těch zpráv, které splňují určitá kritéria. Porovnejte to s modelem toku řízení, kde se tok dat reguluje pomocí řídicích struktur, jako jsou podmíněné příkazy, smyčky atd.

Tento dokument obsahuje základní příklad použití filtru zpráv. Další příklady, které používají filtry zpráv a model toku dat pro připojení bloků zpráv, najdete v tématu Návod: Vytvoření agenta toku dat a návod: Vytvoření sítě pro zpracování obrázků.

Příklad: count_primes funkce

Představte si následující funkci, count_primeskterá ilustruje základní použití bloku zpráv, který nefiltruje příchozí zprávy. Blok zprávy připojí základní čísla k objektu std::vector . Funkce count_primes odešle několik čísel do bloku zprávy, přijme výstupní hodnoty z bloku zprávy a vytiskne tato čísla, která jsou vyčíslaná do konzoly.

// 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;
    }
}

Objekt transformer zpracovává všechny vstupní hodnoty, ale vyžaduje pouze ty hodnoty, které jsou základní. I když by aplikace mohla být napsána tak, aby odesílatel zprávy odeslal pouze prime čísla, požadavky příjemce zprávy nemusí být vždy známé.

Příklad: count_primes_filter funkce

Následující funkce provede count_primes_filterstejnou úlohu jako funkce count_primes . transformer Objekt v této verzi však používá funkci filtru k přijetí pouze těch hodnot, které jsou prime. Funkce, která provádí akci, přijímá pouze prime čísla; proto nemusí volat is_prime funkci.

Vzhledem k tomu, že transformer objekt přijímá pouze prvočísla, transformer může samotný objekt obsahovat základní čísla. Jinými slovy, objekt v tomto příkladu transformer není nutný k přidání primárních čísel k objektu 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;
    }
}

Objekt transformer nyní zpracovává pouze ty hodnoty, které jsou prime. V předchozím příkladu transformer objekt zpracovává všechny zprávy. Předchozí příklad proto musí přijímat stejný počet zpráv, které odesílá. Tento příklad používá výsledek funkce concurrency::send k určení, kolik zpráv má objekt přijímat transformer . Funkce send se vrátí true , když vyrovnávací paměť zprávy přijme zprávu a false když vyrovnávací paměť zprávy odmítne zprávu. Proto počet, kolikrát vyrovnávací paměť zprávy přijme zprávu, odpovídá počtu primárních čísel.

Příklad: Ukázka kódu filtru bloku dokončené zprávy

Následující kód ukazuje úplný příklad. Příklad volá count_primes funkci i count_primes_filter funkci.

// 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
    */
}

Probíhá kompilace kódu

Zkopírujte ukázkový kód a vložte ho do projektu sady Visual Studio nebo ho vložte do pojmenovaného primes-filter.cpp souboru a potom v okně příkazového řádku sady Visual Studio spusťte následující příkaz.

cl.exe /EHsc primes-filter.cpp

Robustní programování

Funkce filtru může být funkce lambda, ukazatel funkce nebo objekt funkce. Každá funkce filtru má jednu z následujících forem:

bool (T)
bool (T const &)

Pokud chcete eliminovat zbytečné kopírování dat, použijte druhý formulář, pokud máte agregovaný typ, který se přenáší podle hodnoty.

Viz také

Knihovna asynchronních agentů
Postupy: Vytvoření agenta toku dat
Návod: Vytvoření sítě pro zpracování obrázků
transformer – třída