std::async is not the only way to associate a
std::future with a task. Using the
std::packaged_task is also a possible solution.
We would like to represent the result of the function
with a future using a packaged task. This is done in three steps.
First, we create a packaged task:
The constructor of the
std::packaged_task requires a function
(callable target) as an argument. The template parameter is the signature of the
function. The signature is
int(double, bool) because
takes arguments of types
The packaged task has a member function
.get_future() which returns a future.
The template parameter of the
std::future must be the same as
the return type of the function which was the argument for the packaged task
constructor. In our example, the template parameter must be
int) was the argument for the
The packaged task is a callable object. The
task forwards the
arguments to the supplied function.
The upper call runs the
(2.5, true) and stores the result of the function
in the future.
We can pass the packaged task around and call it at a different place than where it was created. This is the benefit of packaged tasks: decoupling the creation of the future with the execution of the task.
The typical usage of a packaged task is:
creating the packaged task with a function,
retrieving the future from the packaged task,
passing the packaged task elsewhere,
invoking the packaged task.
Temperature tomorrow revisited
We will use a packaged task on the example from the previous article.
The story was: A couple, wife and husband, are going on a picnic tomorrow. The wife would like to know what will be the temperature of the weather. Therefore, she asks her husband to look it up.
The two functions from the last example
stay the same. The
make_break() stops current thread for
given amount of milliseconds and the
temperature() returns the
temperature, which the husband looked up. The
The interesting part is where the constructor of
creates a packaged task with the
temperature(). Then, the future
retrieved from the
task. Afterwards, we pass the task to a
separate thread. The packaged task is not copyable, therefore
std::move moves it to the thread. The thread is detached and
computes the result asynchronously.
temperature would have additional input arguments,
they would be listed in the
The entire source code is available here. The output of the program is:
This is a possible usage of a packaged task but it is not a common one. Using
std::async is a lot easier in this case. But it is useful to
start exploring packaged tasks with a familiar example.
std::packaged_task is another way to associate a task
std::future – the future representation of the result
of the task.
In the next article, we will give another example of usage of packaged
tasks. It will take advantage of the fact that the execution of the task and the
retrieval of the future from the packaged task is not so tightly connected as in