Introduction
In this blog, Thread and Process in C++ – My sky (freewindcode.com), I mentioned that an operation on a thread could return results and have it captured by another thread. In this post, I will explain the concept and how to do that.
Concepts
Promise: class template provides a facility to store a value or an exception that is later acquired asynchronously via a std::future
object. The future object must be associated with a the promise via promise::get_future()
function.
- The promise is created in caller thread.
- The promise should be passed as reference to a function that the called thread runs.
- The promise acquires the values of the thread operation from inside the function that the called thread runs. The promise uses
set_value
to the data.
Future: class template std::future
provides a mechanism to access the result of asynchronous operations.
- Futures can use
get
function to get the result or exception that was set in the promise. - Futures stay in the calling thread.
The relationship between the {Caller, future} and {Called, promise} is illustrated as below:

Simply speaking: a future is one end of a communications channel through which a callee transmits a result to a caller.
Implementation
Getting future via associated promise
The following steps are to be done:
- Create a promise object
- Create and associate a future with the promise.
- Create a thread object, pass a function to be done the thread to its constructor. Pass the promise as the reference argument to the function.
- Note that the function returns result. The result must be
set_value
in the promise.
- Note that the function returns result. The result must be
- terminate thread
- get the result in the calling thread.
#include <iostream>
#include <thread>
#include <future>
int main()
{
// 1. Create a promise object
std::promise<int> p;
// 2. Associate a future with the promise
std::future<int> ft = p.get_future();
// 3. Start a sub-thread, pass the promise to the thread's operation
// and set return result to promise
std::thread t([&p]() {
std::cout << "ThreadID: " << std::this_thread::get_id() << std::endl;
p.set_value(5); // Set a value in the promise
});
// 4. Block main thread, wail till sub-thread finishes.
t.join();
// 5. Main thread gets the result via future
int result = ft.get();
std::cout << "result " << result << std::endl;
return 0;
}
Note that the above program uses lamda function where the promise
is captured. We could also define a function where promise is passed in as a reference; then we invoke the thread.
void doSomething(std::promise<int> &p;
// in main:
std::thread t(doSomething, ref(p));
Getting future from a task-based thread operation
It is advisable to implement task-based programming.
With the task-based approach, the future
returned from std::async
offers the std::fucture::get
function. The get
function is even more important if thread operation emits an exception, get
provides access to that, too. [1]
The following program uses std::async
to run an anonymous function that returns 5. The std::assync
will run the function in async mode and directly returns the future
object.
#include <iostream>
#include <thread>
#include <future>
int main()
{
std::future<int> ft = std::async(std::launch::async, []{ return 5;})
int result = ft.get();
std::cout << "result " << result << std::endl;
return 0;
}
Reference:
[1] Effective Modern C++. Item 35.