Megosztás:


Útmutató: Üzenetblokkszűrő használata

Ez a dokumentum bemutatja, hogyan lehet egy szűrőfüggvény használatával egy aszinkron üzenetblokkot képessé tenni arra, hogy elfogadja vagy elutasítsa az üzenetet annak hasznos terhe alapján.

Amikor létrehoz egy üzenetblokk-objektumot, például egyidejűséget::unbounded_buffer, egyidejűséget::hívás vagy egyidejűség::transzformátort, megadhat egy szűrőfüggvényt , amely meghatározza, hogy az üzenetblokk elfogad-e vagy elutasít egy üzenetet. A szűrőfüggvények segítségével garantálható, hogy az üzenetblokkok csak bizonyos értékeket kapnak.

A szűrőfüggvények azért fontosak, mert lehetővé teszik az üzenetblokkok adatfolyam-hálózatok létrehozásához való csatlakoztatását. Az adatfolyam-hálózatokban az üzenetblokkok úgy szabályozzák az adatáramlást, hogy csak azokat az üzeneteket dolgoznak fel, amelyek megfelelnek bizonyos feltételeknek. Hasonlítsa össze ezt a vezérlőfolyamat-modellel, ahol az adatáramlás szabályozása vezérlőstruktúrák, például feltételes utasítások, hurkok stb. használatával történik.

Ez a dokumentum egy egyszerű példa az üzenetszűrő használatára. Az üzenetszűrőket és az adatfolyam-modellt üzenetblokkok csatlakoztatására használó további példákért lásd : Útmutató: Adatfolyam-ügynök létrehozása és útmutató: Image-Processing hálózat létrehozása.

Példa: count_primes függvény

Vegye figyelembe az alábbi függvényt, amely egy olyan üzenetblokk alapszintű használatát mutatja be, count_primesamely nem szűri a bejövő üzeneteket. Az üzenetblokk prímszámokat fűz egy std::vector objektumhoz. A count_primes függvény több számot küld az üzenetblokkba, megkapja az üzenetblokk kimeneti értékeit, és kinyomtatja azokat a számokat, amelyek elsődlegesek a konzolon.

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

Az transformer objektum az összes bemeneti értéket feldolgozza, azonban csak azokat az értékeket igényli, amelyek prímértékek. Bár az alkalmazás írható úgy, hogy az üzenet feladója csak prímszámokat küldjön, az üzenet fogadójának követelményei nem mindig ismertek.

Példa: count_primes_filter függvény

Az alábbi függvény ugyanazt a feladatot hajtja végre, count_primes_filtermint a count_primes függvény. Az ebben a transformer verzióban lévő objektum azonban egy szűrőfüggvény használatával csak azokat az értékeket fogadja el, amelyek elsődlegesek. A műveletet végrehajtó függvény csak prímszámokat kap; ezért nem kell meghívnia a függvényt is_prime .

Mivel az transformer objektum csak prímszámokat kap, maga az transformer objektum is megtarthatja a prímszámokat. Más szóval a transformer példában szereplő objektumnak nem kell az elsődleges számokat hozzáadnia az vector objektumhoz.

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

Az transformer objektum most már csak azokat az értékeket dolgozza fel, amelyek elsődlegesek. Az előző példában transformer az objektum az összes üzenetet feldolgozza. Ezért az előző példának ugyanannyi üzenetet kell kapnia, mint ahány üzenetet küld. Ez a példa az egyidejűség::send függvény eredményét használja annak meghatározásához, hogy hány üzenetet fogadjon az transformer objektum. A send függvény akkor ad true vissza, ha az üzenetpuffer elfogadja az üzenetet, és false amikor az üzenetpuffer elutasítja az üzenetet. Ezért az a szám, amikor az üzenetpuffer elfogadja az üzenetet, egyezik a prímszámok számával.

Példa: Kész üzenetblokk szűrőkód mintája

Az alábbi kód a teljes példát mutatja be. A példa meghívja a függvényt count_primes és a függvényt count_primes_filter is.

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

A kód összeállítása

Másolja ki a példakódot, és illessze be egy Visual Studio-projektbe, vagy illessze be egy elnevezett primes-filter.cpp fájlba, majd futtassa a következő parancsot egy Visual Studio parancssori ablakban.

cl.exe /EHsc primes-filter.cpp

Robusztus programozás

A szűrőfüggvény lehet lambda függvény, függvénymutató vagy függvényobjektum. Minden szűrőfüggvény a következő formák egyikét használja:

bool (T)
bool (T const &)

Az adatok szükségtelen másolásának kiküszöböléséhez használja a második űrlapot, ha egy érték által továbbított összesítési típussal rendelkezik.

Lásd még

Aszinkron ügynökök könyvtára
Útmutató: Adatfolyam-ügynök létrehozása
Útmutató: Image-Processing-hálózat létrehozása
transformer class