Tarea empaquetada | C++ avanzado (multiproceso y multiprocesamiento)

La clase std:: packaged_task envuelve cualquier objeto invocable (función, expresión lambda, expresión de enlace u otro objeto de función) para que puedan invocarse de forma asincrónica. Una tarea empaquetada no se iniciará por sí sola, debe invocarla, ya que su valor de retorno se almacena en un estado compartido al que pueden llamar/acceder los objetos std::future.

Necesidad de packaged_task

La principal ventaja de una tarea empaquetada es que puede vincular un objeto invocable a un futuro y eso es muy importante en un entorno de inundación. Por ejemplo, si tenemos una función existente que obtiene los datos de la base de datos (DB) y los devuelve. Ahora es necesario ejecutar esta función en un hilo separado. Esto se puede hacer usando:

std::packaged_task<>

 De lo contrario, tendremos que usar:

std::promesa<>

y tengo que cambiar el código pero con la ayuda de std::packaged_task<> es simple y no necesitamos hacer eso.

Funciones de miembros

Algunas de las funciones miembro en packaged_task son:

  • Operador=- mueve tareas empaquetadas y es una función miembro pública.
  • Intercambiar: simplemente cambia a la tarea empaquetada o puede decir intercambiar dos tareas empaquetadas entre sí.
  • get_future- Devuelve un std::future asociado con el resultado prometido.
  • restablecer: esta función de miembro público solo restablece la tarea.
  • (constructor): como sugiere el nombre, esta función miembro pública construye la tarea empaquetada.
  • (destructor)- De manera similar, (destructor) destruye el objeto de la tarea.    

Funciones de no miembros

Una de las funciones no miembros es:

  • swap(packaged_task)- Se especializa en el algoritmo std::swap.

A continuación se muestra el programa C++ para implementar las funciones anteriores:

C++

// C++ program to implement
// the functions
#include<bits/stdc++.h>
  
using namespace std;
  
// Factorial function
int factorial(int N)
{
    int res = 1;
    for (int i = N; i > 1; i--) 
    {
        res *= i;
    }
    
    cout << "Result is = " << 
             res << "/n";
    return res;
}
  
// packaged task
std::deque<std::packaged_task<int(int)> > task_q;    
std::mutex mu;
std::condition_variable cond;
  
void thread1() 
{
  // packaged task
  std::packaged_task<int()> t;                       
  {
    std::unique_lock<std::mutex> locker(mu);
    cond.wait(locker, []() 
              { 
                return !task_q.empty();
              }); 
    t = std::move(task_q.front());
    task_q.pop_front();
  }  
  t();
}
  
// Driver Code
int main()
{
      std::thread t1(thread1);
      
    // Create a packaged_task<> that 
    // encapsulated the callback i.e. a function
    std::packaged_task<int()> t(bind(factorial,6));    
    
    // Fetch the associated future<> 
    // from packaged_task<>
      std::future<int> fu = t.get_future();              
  {
    std::lock_guard<std::mutex> locker(mu);
    task_q.push_back(std::move(t));
  }
    
      cond.notify_one();
    
    // Fetch the result of packaged_task<>
    cout<<fu.get();                                         
    
    // Join the thread. Its blocking and 
    // returns when thread is finished.
      t1.join();                                         
            
    return 0;
}

Producción:

packaged_task

Publicación traducida automáticamente

Artículo escrito por lost1903 y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *