In this example we will discuss c++11 std::packaged_task feature and its uses.

std::packaged_task<>

std::packaged_task<> is a class template and represents a asynchronous task. It encapsulates,

  1. A callable entity i.e either function, lambda function or function object.
  2. A shared state that stores the value returned or thrown exception by associated callback.

Need of std::packaged_task<>

Suppose we have an existing function that fetches the data from DB and return i.e.

Now we want to execute this function in a separate thread. But how we will fetch the result or exception back in main thread after other thread is finished ?

One way is to change the declaration of function and pass a std::promise<> in the function. Before passing the std::promise<> object in thread function, fetch the associated std::future<> out of it and keep that in main thread. Now, before thread function returns its value, it should set that in passed std::promise<> argument, so that it can be available in associated std::future<> object in main thread. Check below tutorial for this approach i.e,

C++11 Multithreading – Part 8: std::future , std::promise and Returning values from Thread

But creating this std::promise<> and changing function code can be prevented if we use std::packaged_task<>.

Using packaged_task<> with function to create Asynchronous tasks

std::packaged_task<> can wrap around a normal function and make it applicable to run as asynchronous function.

When std::packaged_task<> is called in a separate thread, it calls the associated callback and stores the return  value/exception in its internal shared state. This value can be accessed in other thread or main function through std::future<> object.

Let’s create a std::packaged_task<> from above mentioned function, execute in separate thread and fetch result from its future<> object.

Creating std::packaged_task<> object

std::package_task<> is a class template, therefore we need to pass template parameter to packaged_task<> i.e. type of callable function

Fetch the future object from it,

Passing packaged_task<> to a thread,

std::packaged_task<> is movable but not copy-able, so we need to move it to thread i.e.

As packaged_task was only movable and not copy-able, therefore we fetched the std::future<> object from it before moving it to thread.

Thread will execute this task, which internally calls associated callable entity i.e. our function getDataFromDB().

Now when this function returns the value, std::packaged_task<> sets it to associated shared state and result or exception returned by getDataFromDB() will eventually be available in associated future object.

In main function, fetch result from future<> object i.e.

get() function will block the calling thread until the callable entity returns and std::packaged_task<> set the data in its shareable state.

Complete example is as follows,

Output:

On similar lines we can create a packaged_task with lambda function and function objects too i.e.

Creating packaged_task with Lambda Function

Output:

 Creating packaged_task with Function Object

 

Output:

Click Here to Subscribe for more Articles / Tutorials like this.