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: