Skip to content
Theory · Multithreading: An Overview · lesson 8 of 10

async, future and time: chrono

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:

C++
#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
}

std::async passes the argument 100 to sum_to. The angle brackets of std::future<int> hold the result type. The call result.get() waits until the function finishes and returns its result. You can call get() on one std::future only once, while wait() only waits, without taking the result.

Launch policy

The first argument of std::async is the launch policy. With std::launch::async, the function runs in a new thread. With std::launch::deferred, it does not start right away: the first call to get() or wait() runs it in the calling thread. If neither is called, the function never runs at all.

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.

Durations: chrono

A thread often needs to wait: std::this_thread::sleep_for pauses it for a given duration. Durations are expressed with the types std::chrono::seconds, std::chrono::minutes and std::chrono::milliseconds from the <chrono> header. The .count() method returns the number of units. The literals 2min, 30s and 500ms are available after the line using namespace std::chrono_literals;.

C++
#include <chrono>
#include <iostream>

using namespace std::chrono_literals;

int main() {
    std::chrono::seconds total = 2min + 30s;
    std::chrono::milliseconds ms = total;
    std::cout << total.count() << ' ' << ms.count() << '\n';  // 150 150000
}

The sum 2min + 30s gets the type of the finer of the two units, that is, seconds. A duration converts to finer units by itself, since no precision is lost. The opposite conversion can lose a fraction, so it is written explicitly, with std::chrono::duration_cast. It rounds toward zero: std::chrono::duration_cast<std::chrono::seconds>(1500ms) equals 1s.

Common mistake

Milliseconds are assigned to seconds:

C++
std::chrono::milliseconds ms{1500};
std::chrono::seconds s = ms;  // ✗
TEXT
error: no viable conversion from 'duration<[...], ratio<[...], 1000>>' to 'duration<[...], ratio<[...], 1>>'

This is a compiler error. The compiler checks the types, not the value: converting milliseconds to seconds can lose a fraction, even if ms held exactly 2000. If the loss is acceptable, convert with duration_cast.