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_primes
která 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_filter
stejnou ú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