방법: 메시지 블록 필터 사용

이 문서에서는 필터 함수를 사용하여 비동기 메시지 블록이 해당 메시지의 페이로드를 기반으로 메시지를 수락하거나 거부할 수 있도록 하는 방법을 보여 줍니다.

동시성::unbounded_buffer, 동시성::call 또는 concurrency::transformer와 같은 메시지 블록 개체를 만들 때 메시지 블록이 메시지를 수락하거나 거부하는지 여부를 결정하는 필터 함수를 제공할 수 있습니다. 필터 함수는 메시지 블록이 특정 값만 수신하도록 보장하는 유용한 방법입니다.

필터 함수는 메시지 블록을 연결하여 데이터 흐름 네트워크를 형성할 수 있기 때문에 중요합니다. 데이터 흐름 네트워크에서 메시지 블록은 특정 조건을 충족하는 메시지만 처리하여 데이터 흐름을 제어합니다. 이를 조건문, 루프 등과 같은 제어 구조를 사용하여 데이터 흐름이 규제되는 제어 흐름 모델과 비교합니다.

이 문서에서는 메시지 필터를 사용하는 방법에 대한 기본 예제를 제공합니다. 메시지 필터 및 데이터 흐름 모델을 사용하여 메시지 블록을 연결하는 추가 예제는 연습: 데이터 흐름 에이전트 만들기 및 연습: 이미지 처리 네트워크 만들기를 참조하세요.

예: count_primes 함수

들어오는 메시지를 필터링하지 않는 메시지 블록의 기본 사용을 보여 주는 다음 함수 count_primes를 고려합니다. 메시지 블록은 std::vector 개체에 소수를 추가합니다. 이 함수는 count_primes 메시지 블록에 여러 숫자를 보내고, 메시지 블록에서 출력 값을 수신하고, 해당 숫자를 콘솔에 출력합니다.

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

개체는 transformer 모든 입력 값을 처리하지만 소수인 값만 필요합니다. 메시지 발신자가 소수만 보내도록 애플리케이션을 작성할 수 있지만 메시지 수신자의 요구 사항을 항상 알 수는 없습니다.

예: count_primes_filter 함수

다음 함수는 count_primes_filter함수와 동일한 작업을 count_primes 수행합니다. 그러나 이 버전의 개체는 transformer 필터 함수를 사용하여 소수인 값만 허용합니다. 작업을 수행하는 함수는 소수만 받습니다. 따라서 함수를 호출 is_prime 할 필요가 없습니다.

개체는 transformer 소수 transformer 만 받기 때문에 개체 자체는 소수를 보유할 수 있습니다. 즉, 이 예제의 transformer 개체는 소수를 개체에 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;
    }
}

이제 개체는 transformer 소수인 값만 처리합니다. 이전 예제에서 개체는 transformer 모든 메시지를 처리합니다. 따라서 이전 예제에서는 보내는 메시지 수와 동일한 수의 메시지를 받아야 합니다. 이 예제에서는 동시성::send 함수의 결과를 사용하여 개체에서 transformer 받을 메시지 수를 결정합니다. 이 함수는 send 메시지 버퍼가 메시지를 수락하고 false 메시지 버퍼가 메시지를 거부할 때 반환 true 됩니다. 따라서 메시지 버퍼가 메시지를 수락하는 횟수는 소수 수와 일치합니다.

예: 완료된 메시지 블록 필터 코드 샘플

다음 코드에서는 전체 예제를 보여 줍니다. 이 예제에서는 함수와 함수를 count_primes 모두 호출합니다 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
    */
}

코드 컴파일

예제 코드를 복사하여 Visual Studio 프로젝트에 붙여넣거나 이름이 지정된 primes-filter.cpp 파일에 붙여넣은 다음 Visual Studio 명령 프롬프트 창에서 다음 명령을 실행합니다.

cl.exe /EHsc primes-filter.cpp

강력한 프로그래밍

필터 함수는 람다 함수, 함수 포인터 또는 함수 개체일 수 있습니다. 모든 필터 함수는 다음 형식 중 하나를 사용합니다.

bool (T)
bool (T const &)

불필요한 데이터 복사를 제거하려면 값으로 전송되는 집계 형식이 있는 경우 두 번째 양식을 사용합니다.

참고 항목

비동기 에이전트 라이브러리
연습: 데이터 흐름 에이전트 만들기
연습: 이미지 처리 네트워크 만들기
transformer 클래스