Como: Use um filtro de bloco de mensagem

Este documento demonstra como usar uma função de filtro para ativar um bloco assíncrona de mensagem para aceitar ou descartar uma mensagem com base na carga da mensagem.

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

Funções de filtro é importante porque permitem você se conectar blocos de mensagem para formar redes do fluxo de dados.Em uma rede do fluxo de dados, blocos de mensagem controlar o fluxo de dados processando somente as mensagens que atendem aos critérios específicos.Compare isso para o modelo de fluxo de controle, onde o fluxo de dados é regulado usando estruturas de controle como instruções condicionais, loop, e assim por diante.

Este documento básico fornece um exemplo de como usar um filtro de mensagem.Para exemplos adicionais que usam filtros de mensagem e o modelo de fluxo de dados para conectar blocos de mensagem, consulte Passo a passo: Criando um agente do fluxo de dados e Passo a passo: Criando uma rede Processamento de imagens.

Exemplo

Considere a função a seguir, count_primes, que ilustra o uso mais básico de um bloco de mensagem que não filtra mensagens de entrada.O bloco de mensagem acrescenta números primos para um objeto de std::vector .A função de count_primes envia vários números para o bloco de mensagem, recebe os valores de saída do bloco de mensagem, e imprime todos esses números que são principais no 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;
    }
}

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

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

Porque o objeto de transformer receberá apenas números primos, o próprio objeto de transformer pode armazenar números primos.Ou seja o objeto de transformer neste exemplo não é necessário adicionar os números primos para o objeto de 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;
    }
}

O objeto de transformer agora processa somente os valores que são chave.No exemplo anterior, o objeto de transformer processa todas as mensagens.Como consequência, o exemplo anterior deve receber o mesmo número de mensagens que envia.Este exemplo usa o resultado da função de concurrency::send para determinar quantas a receber mensagens de transformer objeto.A função de send retorna true quando o buffer de mensagem aceita a mensagem e false quando o buffer de mensagem descarta a mensagem.Como consequência, o número de vezes que o buffer de mensagem aceita a mensagem corresponde a contagem de números primos.

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

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

Compilando o código

Copie o código de exemplo e cole-o em um projeto do Visual Studio, ou cole em um arquivo denominado primes-filter.cpp e execute o seguinte comando em uma janela de prompt de comando do Visual Studio.

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 utiliza uma das seguintes formas:

  

Para eliminar copiar desnecessário de dados, use o segundo formulário quando você tiver um agregado tipo que seja passado por valor.

Consulte também

Tarefas

Passo a passo: Criando um agente do fluxo de dados

Passo a passo: Criando uma rede Processamento de imagens

Referência

classe transformador

Conceitos

Biblioteca de agentes assíncrono