Comment : effectuer une sélection parmi les tâches terminées

Cet exemple montre comment utiliser les classes concurrency ::choice et concurrency ::join pour sélectionner la première tâche pour terminer un algorithme de recherche.

Exemple

L’exemple suivant effectue deux algorithmes de recherche en parallèle et sélectionne le premier algorithme à terminer. Cet exemple définit le employee type, qui contient un identificateur numérique et un salaire pour un employé. La find_employee fonction recherche le premier employé qui a l’identificateur fourni ou le salaire fourni. La find_employee fonction gère également le cas où aucun employé n’a fourni l’identificateur ou le salaire fourni. La wmain fonction crée un tableau d’objets et recherche plusieurs valeurs d’identificateur et de employee salaire.

L’exemple utilise un choice objet pour sélectionner parmi les cas suivants :

  1. Un employé qui a l’identificateur fourni existe.

  2. Un employé qui a le salaire fourni existe.

  3. Aucun employé qui a fourni l’identificateur ou le salaire n’existe.

Pour les deux premiers cas, l’exemple utilise un objet concurrency ::single_assignment pour contenir l’identificateur et un autre single_assignment objet pour contenir le salaire. L’exemple utilise un join objet pour le troisième cas. L’objet join est composé de deux objets supplémentaires single_assignment , un pour le cas où aucun employé qui n’a l’identificateur fourni existe, et un pour le cas où aucun employé n’a le salaire fourni. L’objet join envoie un message lorsque chacun de ses membres reçoit un message. Dans cet exemple, l’objet join envoie un message lorsqu’aucun employé n’a l’identificateur ou le salaire fourni.

L’exemple utilise un objet concurrency ::structured_task_group pour exécuter les deux algorithmes de recherche en parallèle. Chaque tâche de recherche écrit dans l’un des single_assignment objets pour indiquer si l’employé donné existe. L’exemple utilise la fonction concurrency ::receive pour obtenir l’index du premier tampon qui contient un message et un switch bloc pour imprimer le résultat.

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

Cet exemple produit la sortie suivante.

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.

Cet exemple utilise la fonction d’assistance concurrency ::make_choice pour créer des choice objets et la fonction d’assistance concurrency ::make_join pour créer des join objets.

Compilation du code

Copiez l’exemple de code et collez-le dans un projet Visual Studio, ou collez-le dans un fichier nommé find-employee.cpp , puis exécutez la commande suivante dans une fenêtre d’invite de commandes Visual Studio.

cl.exe /EHsc find-employee.cpp

Voir aussi

Bibliothèque d’agents asynchrones
Blocs de messages asynchrones
Fonctions de passage de messages
choice, classe
join, classe