次の方法で共有


方法: 完了したタスクから選択する

次の使用例を使用する方法を示しています、 concurrency::choiceconcurrency::join クラスは、検索アルゴリズムを実行するのには、最初のタスクを選択します。

使用例

次の例では 2 つの検索アルゴリズムを並列で実行し、最初のアルゴリズムを選択して完了します。この例では、従業員の数値 ID と給与を格納する employee 型を定義します。find_employee 関数は、指定された ID と指定された給与に該当する最初の従業員を検索します。また、find_employee 関数は、指定された ID または指定された給与に該当する従業員がいない場合の処理も行います。wmain 関数は、employee オブジェクトの配列を作成して複数の ID および給与の値を検索します。

次の例では、choice オブジェクトを使用して、次の事例を選択します。

  1. 指定された ID を持つ従業員。

  2. 指定された給与の従業員。

  3. 指定された ID または給与に該当しない従業員。

最初の 2 つの場合は、この例を使用して、 concurrency::single_assignment と、識別子を保持するオブジェクトsingle_assignment給料を保持するオブジェクト。この例は、3 番目の事例に対して join オブジェクトを使用します。join オブジェクトは、2 つの別の single_assignment オブジェクトで構成されます。1 つは、指定された ID を持つ従業員がいない事例に使用し、もう 1 つは指定された給与に該当する従業員がいない事例に使用します。join オブジェクトは、その各メンバーがメッセージを受信したときにメッセージを送信します。この例では、join オブジェクトは、指定された ID または給与に該当する従業員がいない場合にメッセージを送信します。

例で使用して、 concurrency::structured_task_group 同時に両方の検索アルゴリズムを実行するオブジェクト。各検索タスクが、指定された従業員が存在するかどうかを示す値を single_assignment オブジェクトの 1 つに書き込みます。この例を使用して、 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(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);
}

この例を実行すると、次の出力が生成されます。

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 プロジェクトでは、貼り付けるまたはという名前のファイルに貼り付けて検索-employee.cpp と、Visual Studio のコマンド プロンプト ウィンドウで次のコマンドを実行します。

cl.exe /EHsc find-employee.cpp

参照

関連項目

choice クラス

join クラス

概念

非同期エージェント ライブラリ

非同期メッセージ ブロック

メッセージ パッシング関数