Sdílet prostřednictvím


Postupy: Výběr z dokončených úloh

Tento příklad ukazuje, jak pomocí třídy concurrency::choice a concurrency::join vybrat první úkol pro dokončení vyhledávacího algoritmu.

Příklad

Následující příklad provádí paralelně dva vyhledávací algoritmy a vybere první algoritmus, který se má dokončit. Tento příklad definuje employee typ, který obsahuje číselný identifikátor a plat zaměstnance. Funkce find_employee najde prvního zaměstnance, který má zadaný identifikátor nebo zadaný plat. Funkce find_employee také zpracovává případ, kdy žádný zaměstnanec nemá zadaný identifikátor nebo plat. Funkce wmain vytvoří pole employee objektů a vyhledá několik identifikátorů a platových hodnot.

Příklad používá choice objekt k výběru z následujících případů:

  1. Zaměstnanec, který má zadaný identifikátor, existuje.

  2. Zaměstnanec, který má poskytnutý plat, existuje.

  3. Žádný zaměstnanec, který má zadaný identifikátor nebo plat, neexistuje.

V prvních dvou případech příklad používá souběžnost::single_assignment objekt k uložení identifikátoru a dalšího single_assignment objektu k uložení platu. Příklad používá join objekt pro třetí případ. Objekt join se skládá ze dvou dalších single_assignment objektů, jednoho pro případ, kdy neexistuje žádný zaměstnanec, který má zadaný identifikátor, a jeden pro případ, kdy neexistuje žádný zaměstnanec, který má poskytnutý plat. Objekt join odešle zprávu, když každý z jejích členů obdrží zprávu. V tomto příkladu objekt join odešle zprávu, pokud neexistuje žádný zaměstnanec, který má zadaný identifikátor nebo plat.

Příklad používá souběžnost::structured_task_group objekt ke spuštění obou vyhledávacích algoritmů paralelně. Každý vyhledávací úkol zapíše do jednoho z single_assignment objektů, aby bylo uvedeno, jestli daný zaměstnanec existuje. Příklad používá funkci concurrency::receive k získání indexu první vyrovnávací paměti, která obsahuje zprávu a switch blok k vytištění výsledku.

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

Tento příklad vytvoří následující výstup.

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.

Tento příklad používá pomocnou funkci concurrency::make_choice k vytváření choice objektů a pomocné funkce concurrency::make_join pomocné funkce k vytváření join objektů.

Probíhá kompilace kódu

Zkopírujte ukázkový kód a vložte ho do projektu sady Visual Studio nebo ho vložte do pojmenovaného find-employee.cpp souboru a potom v okně příkazového řádku sady Visual Studio spusťte následující příkaz.

cl.exe /EHsc find-employee.cpp

Viz také

Knihovna asynchronních agentů
Asynchronní bloky zpráv
Funkce pro předávání zpráv
choice – třída
join – třída