async and future
You order soup in the kitchen and get a ticket with a number. While the soup cooks, you get on with your own things. When you need the soup, you bring the ticket to the pickup window. If the soup is ready, you get it right away; if not, you wait at the window. A ticket is exchanged for soup once.
A function started in a std::thread cannot return a result: the thread discards the returned value. To get a result, you have to set up a shared variable and call join(). The std::async function from the <future> header makes this simpler. It starts a function and returns a std::future, an object from which you collect the result later, that very ticket:
#include <future>
#include <iostream>
int sum_to(int n) {
int sum = 0;
for (int i = 1; i <= n; ++i) {
sum += i;
}
return sum;
}
int main() {
std::future<int> result = std::async(std::launch::async, sum_to, 100);
std::cout << result.get() << '\n'; // 5050
}The ticket and the result
Let's take main apart:
std::async(std::launch::async, sum_to, 100)startssum_toand passes it the argument100.std::future<int>is the ticket's type; the angle brackets hold the result type, hereint.result.get()waits until the function finishes and returns its result:5050.
std::future has two ways to wait for the function:
get()waits and takes the result; you can call it on onestd::futureonly once, as a ticket is exchanged once;wait()only waits, without taking the result.
This is where the ticket analogy ends: the pickup window turns down a used ticket, while a second get() is undefined behavior. The standard promises neither a refusal nor a result.
Launch policy
The first argument of std::async is the launch policy. It decides when and where the function runs.
std::launch::async
The function runs in a new thread and starts right away. This is a kitchen that starts on the soup as soon as it takes the order.
std::launch::deferred
The function does not start right away: the first call to get() or wait() runs it in the calling thread. This is a kitchen that starts cooking only when you come to the window with the ticket. If neither get() nor wait() is called, the function never runs at all.
No policy
You can leave the policy out: std::async(sum_to, 100). Then the standard library implementation chooses between async and deferred. If the task must run in parallel, pass std::launch::async explicitly. Interviewers like to ask whether the function runs at all without an explicit policy.
Key points
std::asyncstarts a function and returns astd::future, from which you collect the result later.get()waits and returns the result, and you can call it only once;wait()only waits.- With
std::launch::asyncthe function runs in a new thread, withstd::launch::deferredat the firstget()orwait(). - Without an explicit policy the library chooses; for parallel work, pass
std::launch::async.
Subscribe to take the course
The course is free. Sign in with Telegram and subscribe to the channel to open every lesson.