Stdpackaged Task Class In C++

In this article, we will discuss the std::packaged_task class in C++ with its syntax, parameters, member functions, and example.

What is the std::packaged_task class in C++?

In C++ , callable objects, such as functions , lambda expressions, bind expressions, and any other function object can be wrapped and run asynchronously using the std::packagedtask class. In contrast to certain other asynchronous execution techniques like std::async, a std::packagedtask does not start executing automatically upon creation. Instead, it is pending unless it is explicitly invoked.<

After invoking a std::packaged_task, the corresponding callable object begins execution, and any result or exception from the computation is stored in a shared state. If an error arises during execution, it may be handled asynchronously by retrieving the result using a std::future object, which gives access to this shared state.

Syntax:

It has the following syntax:

Example

template< class R, class... Args >
class packaged_task<R(Args...)>;

Parameters:

  • Template: Two template parameters and a template class are declared in this way.
  • R: R is a representation of the function's return type related to the packed task.
  • Args..: The sorts of arguments that the Function associated with the packed task accepts are represented by the parameter pack called Args. Args can represent zero or more template arguments because it is a variadic template parameter, as indicated by the ellipsis (...).
  • Packagedtask class: This is the actual class declaration. It indicates that a function type R(Args...), where Args... is the parameter pack that represents the kinds of arguments and R is the return type, and defines the packagedtask class template.
  • Return Value:

The return value for std::packaged_task is an object that represents a task associated with a callable object of signature R(Args...). It allows for asynchronous execution of the task and retrieval of its result through an associated std::future.

Consider the following scenario:

Consider a scenario in which an existing function is responsible for retrieving and returning data from a Database (DB). Assume this function must be executed in a separate thread to prevent blocking the main thread of execution.

In these situations, the std::packaged_task is advantageous. By enclosing the database-fetching method in a packaged task, we can run it asynchronously on a different thread while guaranteeing that the related future object quickly handles the result and any potential exceptions.

Member Functions:

  • Operator=: This is the assignment operator(=) overloaded for std::packagedtask. It allows us to move one std::packagedtask object to another, transferring ownership of its state.
  • Swap: This member function swaps the contents of two std::packaged_task objects, which exchange their state. It can be useful for efficiently exchanging the state of two tasks.
  • Getfuture: This member function returns a std::future object associated with the promised result of the std::packagedtask. It allows us to asynchronously retrieve the result or handle exceptions.
  • Reset: This member function resets the std::packaged_task object. It clears any state associated with the task, which makes it ready for reuse.
  • Constructor: The constructor initializes a std::packaged_task object, which is usually takes a callable object as a parameter.
  • Destructor: The destructor deallocates resources associated with the std::packaged_task object when it goes out of scope.
  • Example:

Let us take an example to illustrate the std::packaged_task in C++.

Example

#include <iostream>
#include <future>
#include <thread>
#include <vector>
#include <numeric>
//Function to calculate the sum of elements in a vector
int SumVector(const std::vector<int>& vec) 
{
    return std::accumulate(vec.begin(), vec.end(), 0);
}
int main()
{
    // Creating a vector of integers.
    std::vector<int> nums = {18, 29, 32, 45, 60};
    // Creating a packaged_task to calculate the sum of the vector elements.
    std::packaged_task<int(const std::vector<int>&)> task(SumVector);
    // Get the associated future object.
    std::future<int> future = task.get_future();
    // Execute the task asynchronously.
    std::thread t(std::move(task), nums);
    t.join();
    // Get the result from the future.
    int result = future.get();
    // Displaying the result.
    std::cout << "The sum of the vector elements: " << result << std::endl;
    return 0;
}

Output:

Output

The sum of the vector elements: 184

Explanation:

  • This example demonstrates the use of std::packaged_task for asynchronous function execution. The SumVector function uses std::accumulate to determine the sum of the elements in a vector.
  • After creating and initializing a vector called nums, integers are used.
  • The SumVector method is used to create a std::packaged_task with the name task.
  • After that, the task produces the related std::future object future, which will store the result of the asynchronous computation.
  • Using std::move(task) function, the vector nums are passed in as a parameter, causing the task to be run asynchronously in a different thread, 't'.
  • Using t.join method, the main thread waits for the asynchronous task to be completed.
  • The get method is used to receive the result, which contains the sum of the vector elements from the future once the operation has been performed. The result is printed on the console.

Input Required

This code uses input(). Please provide values below: