방법: 완료된 작업 간 선택
이 예제에서는 concurrency::choice 및 concurrency::join 클래스를 사용하여 검색 알고리즘을 완료할 첫 번째 작업을 선택하는 방법을 보여 줍니다.
예제
다음 예제에서는 두 가지 검색 알고리즘을 병렬로 수행하고 완료할 첫 번째 알고리즘을 선택합니다. 이 예제에서는 직원에 대한 숫자 식별자 및 급여를 저장하는 employee 형식을 정의합니다. find_employee 함수는 제공된 식별자 또는 제공된 급여와 일치하는 첫 번째 직원을 찾습니다. 또한 find_employee 함수는 제공된 식별자 또는 급여에 해당하는 직원이 없는 경우도 처리합니다. wmain 함수는 employee 개체의 배열을 만들고 몇 가지 식별자 및 급여 값을 검색합니다.
이 예제에서는 choice 개체를 사용하여 다음과 같은 경우 중에서 선택합니다.
제공된 식별자를 포함하는 직원이 있는 경우
제공된 급여를 포함하는 직원이 있는 경우
제공된 식별자 또는 급여를 포함하는 직원이 없는 경우
처음의 두 경우를 위해 이 예제에서는 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, ¬_found);
// Create a task that searches for the employee with the provided id.
auto search_id_task = make_task([&]{
auto result = find_if(begin(employees), end(employees),
[&](const employee& e) { return e.id == id; });
if (result != end(employees))
{
// 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(begin(employees), end(employees),
[&](const employee& e) { return e.salary == salary; });
if (result != end(employees))
{
// 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);
}
이 예제의 결과는 다음과 같습니다.
이 예제에서는 concurrency::make_choice 도우미 함수를 사용하여 choice 개체를 만들고 concurrency::make_join 도우미 함수를 사용하여 join 개체를 만듭니다.
코드 컴파일
예제 코드를 복사하여 Visual Studio 프로젝트 또는 find-employee.cpp 파일에 붙여넣고 Visual Studio 명령 프롬프트 창에서 다음 명령을 실행합니다.
cl.exe /EHsc find-employee.cpp