Dela via


Anvisningar: Välj bland slutförda uppgifter

Det här exemplet visar hur du använder samtidighet::val och samtidighet::koppla klasser för att välja den första uppgiften för att slutföra en sökalgoritm.

Exempel

I följande exempel utförs två sökalgoritmer parallellt och den första algoritmen som ska slutföras väljs. I det employee här exemplet definieras typen, som innehåller en numerisk identifierare och en lön för en anställd. Funktionen find_employee hittar den första medarbetaren som har den angivna identifieraren eller den angivna lönen. Funktionen find_employee hanterar även det fall där ingen anställd har den angivna identifieraren eller lönen. Funktionen wmain skapar en matris med employee objekt och söker efter flera identifierare och lönevärden.

I exemplet används ett choice objekt för att välja bland följande fall:

  1. Det finns en medarbetare som har den angivna identifieraren.

  2. Det finns en anställd som har den angivna lönen.

  3. Det finns ingen anställd som har den angivna identifieraren eller lönen.

I de första två fallen använder exemplet ett samtidighet::single_assignment-objekt för att lagra identifieraren och ett annat single_assignment-objekt för att lagra lönen. I exemplet används ett join objekt för det tredje fallet. Objektet join består av två ytterligare single_assignment objekt, ett för det fall där det inte finns någon anställd som har den angivna identifieraren, och ett för det fall där det inte finns någon anställd som har den angivna lönen. Objektet join skickar ett meddelande när var och en av dess medlemmar får ett meddelande. I det här exemplet join skickar objektet ett meddelande när det inte finns någon anställd som har den angivna identifieraren eller lönen.

I exemplet används ett samtidighetsobjekt::structured_task_group för att köra båda sökalgoritmerna parallellt. Varje sökaktivitet skriver till ett av objekten single_assignment för att ange om den angivna medarbetaren finns. I exemplet används funktionen concurrency::receive för att hämta indexet för den första bufferten som innehåller ett meddelande och ett switch block för att skriva ut resultatet.

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

Det här exemplet genererar följande utdata.

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.

I det här exemplet används hjälpfunktionen concurrency::make_choice för att skapa choice objekt och hjälpfunktionen concurrency::make_join för att skapa join objekt.

Kompilera koden

Kopiera exempelkoden och klistra in den i ett Visual Studio-projekt, eller klistra in den i en fil med namnet find-employee.cpp och kör sedan följande kommando i ett Visual Studio-kommandotolkfönster.

cl.exe /EHsc find-employee.cpp

Se även

Asynkront agentbibliotek
Asynkrona meddelandeblock
Funktioner för meddelandeöverföring
choice Class
gå med i klass