Compartilhar via


Como: Use um filtro de bloco de mensagem

Este documento demonstra como usar uma função de filtro para permitir que um bloco de mensagens assíncronas aceitar ou rejeitar uma mensagem na Base de carga da mensagem.

Quando você cria um objeto de bloco de mensagem como um Concurrency::unbounded_buffer, um Concurrency::call, ou um Concurrency::transformer, você pode fornecer um a função de filtro que determina se o bloco de mensagens aceita ou rejeita uma mensagem. Uma função de filtro é uma maneira útil para garantir que um bloco de mensagens recebe apenas certos valores.

Funções de filtro são importantes, pois permitem que você se conecte os blocos de mensagem para o formulário redes de fluxo de dados. Em uma rede de fluxo de dados, blocos de mensagens controlam o fluxo de dados, processando apenas as mensagens que atendem a critérios específicos. Compare isso com o modelo de fluxo de controle, onde o fluxo de dados está regulamentado por meio de estruturas de controle como instruções condicionais, loops, e assim por diante.

Este documento fornece um exemplo básico de como usar o filtro de mensagens. Para obter exemplos adicionais que usam filtros de mensagens e o modelo de fluxo de dados para conectar os blocos de mensagem, consulte Demonstra Passo a passo: Criando um agente de fluxo de dados e Demonstra Passo a passo: A criação de uma rede de processamento de imagens.

Exemplo

Considere a seguinte função, count_primes, que ilustra o uso básico de um bloco de mensagem não filtra mensagens de entrada. O bloco de mensagem acrescenta os números primos para um std:: Vector objeto. O count_primes função envia vários números de bloco de mensagens, recebe os valores de saída do bloco de mensagem e imprime os números que são primos ao 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, 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_each(primes.begin(), primes.end(), [](unsigned long prime) {
      wcout << prime << endl;
   });
}

O transformer objeto processa todos os valores de entrada; No entanto, ele requer que apenas os valores que são primos. Embora o aplicativo poderia ser escrito para que o remetente envia somente os números primos, os requisitos do receptor da mensagem não podem sempre ser conhecidos.

A função a seguir, count_primes_filter, executa a mesma tarefa como a count_primes função. No entanto, o transformer objeto nesta versão usa uma função de filtro para aceitar somente os valores que são primos. A função que realiza a ação recebe apenas os números primos; Portanto, não precisa chamar o is_prime função.

Porque o transformer objeto recebe apenas os números primos, o transformer próprio objeto pode conter números primos. Em outras palavras, o transformer objeto neste exemplo não é necessário adicionar os números primos para o vector objeto.

// 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;
      },
      NULL,      
      [](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, 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;
}

O transformer objeto agora processa somente os valores que são primos. No exemplo anterior, transformer objeto processa todas as mensagens. Portanto, o exemplo anterior deve receber o mesmo número de mensagens que envia. Este exemplo usa o resultado do Concurrency::send função para determinar quantos as mensagens a receber da transformer objeto. O send retorna a função true quando o buffer de mensagem aceita a mensagem e false quando o buffer de mensagem rejeita a mensagem. Portanto, o número de vezes que o buffer de mensagem aceita a mensagem corresponde a contagem dos números primos.

O código a seguir mostra o exemplo completo. O exemplo chama a ambos os count_primes função e o count_primes_filter função.

// 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, 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_each(primes.begin(), primes.end(), [](unsigned long prime) {
      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;
      },
      NULL,      
      [](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, 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);
}

Esse exemplo produz a seguinte saída.

Without filtering:
The following numbers are prime:
9973
9349
9241
8893
1297
7127
8647
3229
With filtering:
The following numbers are prime:
9973
9349
9241
8893
1297
7127
8647
3229

Compilando o código

Copie o código de exemplo e colá-lo em um Visual Studio do projeto, ou colá-lo em um arquivo que é chamado primes filter.cpp e, em seguida, execute o seguinte comando um Visual Studio 2010 janela do Prompt de comando.

cl.exe /EHsc primes-filter.cpp

Programação robusta

Uma função de filtro pode ser uma função lambda, um ponteiro de função ou um objeto de função. Cada função de filtro leva a uma das seguintes formas:

bool (_Type)
bool (_Type const &)

Para eliminar a cópia desnecessária de dados, use o segundo formulário quando você tem um tipo de agregação é transmitido por valor.

Consulte também

Referência

Transformador de classe

Conceitos

Biblioteca de agentes assíncronos

Outros recursos

Demonstra Passo a passo: Criando um agente de fluxo de dados

Demonstra Passo a passo: A criação de uma rede de processamento de imagens