Delen via


Procedure: Een berichtblokfilter gebruiken

In dit document ziet u hoe u een filterfunctie gebruikt om een asynchroon berichtblok in staat te stellen een bericht te accepteren of af te wijzen op basis van de nettolading van dat bericht.

Wanneer u een berichtblokobject maakt, zoals gelijktijdigheid::unbounded_buffer, een gelijktijdigheid::aanroep of een gelijktijdigheid::transformer, kunt u een filterfunctie opgeven die bepaalt of het berichtblok een bericht accepteert of weigert. Een filterfunctie is een handige manier om te garanderen dat een berichtblok alleen bepaalde waarden ontvangt.

Filterfuncties zijn belangrijk omdat u berichtenblokken kunt verbinden met formuliergegevensstroomnetwerken. In een gegevensstroomnetwerk controleren berichtblokken de stroom van gegevens door alleen die berichten te verwerken die voldoen aan specifieke criteria. Vergelijk dit met het controlestroommodel, waarbij de gegevensstroom wordt gereguleerd met behulp van besturingsstructuren zoals voorwaardelijke instructies, lussen, enzovoort.

Dit document bevat een eenvoudig voorbeeld van het gebruik van een berichtfilter. Zie voor meer voorbeelden die gebruikmaken van berichtfilters en het gegevensstroommodel om berichtblokken te verbinden, Walkthrough: Een Gegevensstroomagent Maken en Walkthrough: Een Image-Processing Netwerk Maken.

Voorbeeld: count_primes functie

Houd rekening met de volgende functie, count_primesdie het basisgebruik illustreert van een berichtblok dat geen binnenkomende berichten filtert. Het berichtblok voegt priemgetallen toe aan een std::vector-object . De count_primes functie verzendt verschillende getallen naar het berichtblok, ontvangt de uitvoerwaarden van het berichtblok en drukt deze getallen af die priem zijn op de console.

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

Het transformer object verwerkt alle invoerwaarden. Het object vereist echter alleen de waarden die prime zijn. Hoewel de toepassing zodanig kan worden geschreven dat de afzender van het bericht alleen priemgetallen verzendt, kunnen de vereisten van de ontvanger van het bericht niet altijd bekend zijn.

Voorbeeld: count_primes_filter functie

Met de volgende functie wordt count_primes_filterdezelfde taak uitgevoerd als de count_primes functie. transformer Het object in deze versie gebruikt echter een filterfunctie om alleen de waarden te accepteren die primen zijn. De functie die de actie uitvoert, ontvangt alleen priemgetallen; daarom hoeft de is_prime functie niet aan te roepen.

Omdat het transformer object alleen priemgetallen ontvangt, kan het transformer object zelf de priemgetallen bevatten. Met andere woorden, het transformer object in dit voorbeeld is niet vereist om de priemgetallen aan het vector object toe te voegen.

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

Het transformer object verwerkt nu alleen de waarden die prime zijn. In het vorige voorbeeld transformer verwerkt het object alle berichten. Daarom moet het vorige voorbeeld hetzelfde aantal berichten ontvangen als het verzendt. In dit voorbeeld wordt het resultaat van de gelijktijdigheidsfunctie::verzenden gebruikt om te bepalen hoeveel berichten van het transformer object moeten worden ontvangen. De send functie retourneert true wanneer de berichtbuffer het bericht accepteert en false wanneer de berichtbuffer het bericht weigert. Daarom komt het aantal keren dat de berichtbuffer het bericht accepteert overeen met het aantal priemgetallen.

Voorbeeld: Voorbeeld van filtercode voor berichtblok voltooid

De volgende code toont het volledige voorbeeld. In het voorbeeld worden zowel de count_primes functie als de count_primes_filter functie aangeroepen.

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

De code compileren

Kopieer de voorbeeldcode en plak deze in een Visual Studio-project, of plak deze in een bestand met de naam primes-filter.cpp en voer vervolgens de volgende opdracht uit in een Visual Studio-opdrachtpromptvenster.

cl.exe /EHsc-primes-filter.cpp

Robuuste programmering

Een filterfunctie kan een lambda-functie, een functie aanwijzer of een functieobject zijn. Elke filterfunctie heeft een van de volgende formulieren:

bool (T)
bool (T const &)

Als u het onnodig kopiƫren van gegevens wilt elimineren, gebruikt u het tweede formulier wanneer u een aggregatietype hebt dat per waarde wordt verzonden.

Zie ook

Bibliotheek met asynchrone agents
Overzicht: Een gegevensstroomagent maken
Overzicht: Een Image-Processing-netwerk maken
transformatorklasse