Promise
The promise is the last synchronization mechanism. We already wrote about the
others, namely std::async
,
std::packaged_task
and
std::condition_variable
.
Similar as with other synchronization techniques, the promise is associated
with a std::future
. std::async
and
std::packaged_task
set a value to the future by returning from a
callable object. But the promise can explicitly set the value to the future. Let’s explain how this works.
Promise
We would like to set a value, of the type int
, to the
future.
Creation
First, the default constructor of the std::promise
creates a promise.
std::promise<int> promise;
The promise has a template parameter int
, because we would
like to set a value of the type int
to the future.
The future
The .get_future()
member function of the
std::promise
creates a future.
std::future<int> future = promise.get_future();
The template parameter of the future is the same as the template parameter of the promise.
Setting the value
The .set_value(...)
member function of the
std::promise
sets the value to the future.
promise.set_value(42);
We already know how to obtain the value from the future:
int answer = future.get();
In our example, the answer
is 42
, because
the promise sets the value 42
to the future.
Typical usage
The typical usage of the promise is:
-
creating a promise,
-
retrieving the future from the promise,
-
passing the promise to some other thread,
-
setting a value to the future via the promise,
-
obtaining the value from the future.
Temperature tomorrow re-revisited
We will use the following, already well known, story:
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.
We modeled this story with the
std::async
and the
std::packaged_task
. But
in this example, we will use the std::promise
for the
synchronization.
#include <iostream>
#include <string>
#include <chrono>
#include <thread>
#include <future>
#include <utility>
void make_break(int millisec)
{
std::this_thread::sleep_for(std::chrono::milliseconds(millisec));
}
The beginning is the same as in previous examples: the include statements and
make_break
function.
void temperature(std::promise<int> answer)
{
std::cout << "Husband: Hm, is the weather "
<< "forecast in the newspaper?\n"
<< " Eh, we don't "
<< "have a newspaper at home..." << std::endl;
make_break(2);
std::cout << "Husband: I will look it up on the internet!" << std::endl;
make_break(2);
std::cout << "Husband: Here it is, "
<< "it says tomorrow will be 40." << std::endl;
answer.set_value(40);
}
The argument of the temperature(...)
is the
std::promise<int>
. At the end, the function sets the value to
the associated future via .set_value(...)
member function of
the promise.
int main()
{
std::cout << "Wife: Tomorrow, we are going on a picnic.\n"
<< " What will be the weather...\n"
<< " \"What will be the "
<< "temperature tomorrow?\"" << std::endl;
std::promise<int> promise;
std::future<int> answer = promise.get_future();
std::thread thread(temperature, std::move(promise));
thread.detach();
make_break(2);
std::cout << "Wife: I should pack for tomorrow." << std::endl;
make_break(2);
std::cout << "Wife: Hopefully my husband can figure out the weather soon."
<< std::endl;
int temp = answer.get();
std::cout << "Wife: Finally, tomorrow will be " << temp << "... Em...\n"
<< " \"In which units is the answer?\""
<< std::endl;
return 0;
}
The main function creates a promise and retrieves the future from the
promise. Then, we pass the promise to the temperature(...)
function which is executed in another thread. The
std::promise
is not copyable, therefore
std::move
moves it to the function.
At the end, the .get()
member function of the future
retrieves the value.
The entire source code is available here. The output of the program is:
$ ./promise
Wife: Tomorrow, we are going on a picnic.
What will be the weather...
"What will be the temperature tomorrow?"
Husband: Hm, is the weather forecast in the newspaper?
Eh, we don't have a newspaper at home...
Wife: I should pack for tomorrow.
Husband: I will look it up on the internet!
Wife: Hopefully my husband can figure out the weather soon.
Husband: Here it is, it says tomorrow will be 40.
Wife: Finally, tomorrow will be 40... Em...
"In which units is the answer?"
This is the third solution of this problem. First one used
std::async
and second one used
std::packaged_task
. Now, we can compare the solutions between
each other and see the semantic differences between them.
Summary
The std::promise
can directly set a value to the associated
std::future
with .set_value()
member
function.
In this article, we learned how to use the std::promise
.
Links: