다음을 통해 공유


방법: 완료된 작업 간 선택

이 예제에서는 Concurrency::choiceConcurrency::join 클래스를 사용하여 검색 알고리즘을 완료할 첫 번째 작업을 선택하는 방법을 보여 줍니다.

예제

다음 예제에서는 두 가지 검색 알고리즘을 병렬로 수행하고 완료할 첫 번째 알고리즘을 선택합니다. 이 예제에서는 직원에 대한 숫자 식별자 및 급여를 저장하는 employee 형식을 정의합니다. find_employee 함수는 제공된 식별자 또는 제공된 급여와 일치하는 첫 번째 직원을 찾습니다. 또한 find_employee 함수는 제공된 식별자 또는 급여에 해당하는 직원이 없는 경우도 처리합니다. wmain 함수는 employee 개체의 배열을 만들고 몇 가지 식별자 및 급여 값을 검색합니다.

이 예제에서는 choice 개체를 사용하여 다음과 같은 경우 중에서 선택합니다.

  1. 제공된 식별자를 포함하는 직원이 있는 경우

  2. 제공된 급여를 포함하는 직원이 있는 경우

  3. 제공된 식별자 또는 급여를 포함하는 직원이 없는 경우

처음의 두 경우를 위해 이 예제에서는 Concurrency::single_assignment 개체를 사용하여 식별자를 저장하고 다른 single_assignment 개체를 사용하여 급여를 저장합니다. 세 번째 경우를 위해서는 join 개체를 사용합니다. join 개체는 두 가지 추가 single_assignment 개체로 구성되는데, 하나는 제공된 식별자를 포함하는 직원이 없는 경우에 사용되고 다른 하나는 제공된 급여를 포함하는 직원이 없는 경우에 사용됩니다. join 개체는 각 멤버가 메시지를 받을 때 메시지를 보냅니다. 이 예제의 경우 join 개체는 제공된 식별자 또는 급여를 포함하는 직원이 없는 경우 메시지를 보냅니다.

이 예제에서는 Concurrency::structured_task_group 개체를 사용하여 두 검색 알고리즘을 병렬로 실행합니다. 각 검색 작업은 지정된 직원이 있는지 여부를 나타내기 위해 single_assignment 개체 중 하나에 씁니다. 이 예제에서는 Concurrency::receive 함수를 사용하여 메시지를 포함하는 첫 번째 버퍼의 인덱스를 가져오고 switch 블록을 사용하여 결과를 출력합니다.

// find-employee.cpp
// compile with: /EHsc
#include <agents.h>
#include <ppl.h>
#include <array>
#include <iostream>
#include <random>

using namespace Concurrency;
using namespace std;

// Contains information about an employee.
struct employee
{
   int id;
   float salary;
};

// Finds the first employee that has the provided id or salary.
template <typename T>
void find_employee(const T& employees, int id, float salary)
{
   // Holds the salary for the employee with the provided id.
   single_assignment<float> find_id_result;

   // Holds the id for the employee with the provided salary.
   single_assignment<int> find_salary_result;


   // Holds a message if no employee with the provided id exists.
   single_assignment<bool> id_not_found;

   // Holds a message if no employee with the provided salary exists.
   single_assignment<bool> salary_not_found;

   // Create a join object for the "not found" buffers.
   // This join object sends a message when both its members holds a message 
   // (in other words, no employee with the provided id or salary exists).
   auto not_found = make_join(&id_not_found, &salary_not_found);


   // Create a choice object to select among the following cases:
   // 1. An employee with the provided id exists.
   // 2. An employee with the provided salary exists.
   // 3. No employee with the provided id or salary exists.
   auto selector = make_choice(&find_id_result, &find_salary_result, &not_found);


   // Create a task that searches for the employee with the provided id.
   auto search_id_task = make_task([&]{
      auto result = find_if(employees.begin(), employees.end(), 
         [&](const employee& e) { return e.id == id; });
      if (result != employees.end())
      {
         // The id was found, send the salary to the result buffer.
         send(find_id_result, result->salary);
      }
      else
      {
         // The id was not found.
         send(id_not_found, true);
      }
   });

   // Create a task that searches for the employee with the provided salary.
   auto search_salary_task = make_task([&]{
      auto result = find_if(employees.begin(), employees.end(), 
         [&](const employee& e) { return e.salary == salary; });
      if (result != employees.end())
      {
         // The salary was found, send the id to the result buffer.
         send(find_salary_result, result->id);
      }
      else
      {
         // The salary was not found.
         send(salary_not_found, true);
      }
   });

   // Use a structured_task_group object to run both tasks.
   structured_task_group tasks;
   tasks.run(search_id_task);
   tasks.run(search_salary_task);

   wcout.setf(ios::fixed, ios::fixed);
   wcout.precision(2);

   // Receive the first object that holds a message and print a message.
   int index = receive(selector);
   switch (index)
   {
   case 0:
      wcout << L"Employee with id " << id << L" has salary " 
            << receive(find_id_result);
      break;
   case 1:
      wcout << L"Employee with salary " << salary << L" has id " 
            << receive(find_salary_result);
      break;
   case 2:
      wcout << L"No employee has id " << id << L" or salary " << salary;
      break;
   default:
      __assume(0);
   }
   wcout << L'.' << endl;

   // Cancel any active tasks and wait for the task group to finish.
   tasks.cancel();
   tasks.wait();
}

int wmain()
{
   // Create an array of employees and assign each one a 
   // random id and salary.

   array<employee, 10000> employees;

   mt19937 gen(15);
   const float base_salary = 25000.0f;
   for (int i = 0; i < employees.size(); ++i)
   {
      employees[i].id = gen()%100000;

      float bonus = static_cast<float>(gen()%5000);
      employees[i].salary = base_salary + bonus;
   }

   // Search for several id and salary values.

   find_employee(employees, 14758, 30210.00);
   find_employee(employees, 340, 29150.00);
   find_employee(employees, 61935, 29255.90);
   find_employee(employees, 899, 31223.00);
}

이 예제의 결과는 다음과 같습니다.

Employee with id 14758 has salary 27780.00.
Employee with salary 29150.00 has id 84345.
Employee with id 61935 has salary 29905.00.
No employee has id 899 or salary 31223.00.

이 예제에서는 Concurrency::make_choice 도우미 함수를 사용하여 choice 개체를 만들고 Concurrency::make_join 도우미 함수를 사용하여 join 개체를 만듭니다.

코드 컴파일

예제 코드를 복사하여 Visual Studio 프로젝트 또는 find-employee.cpp 파일에 붙여넣고 Visual Studio 2010 명령 프롬프트 창에서 다음 명령을 실행합니다.

cl.exe /EHsc find-employee.cpp

참고 항목

참조

choice 클래스

join 클래스

개념

비동기 에이전트 라이브러리

비동기 메시지 블록

메시지 전달 함수