Use std::async for Concurrency
Learn to use std::async for concurrency.
We'll cover the following...
std::async()
runs a target function asynchronously and returns a std::future
object to carry the target function's return value. In this way, async()
operates much like std::thread
but allows return values.
Let's consider the use of std::async()
with a few examples.
How to do it
In its simplest forms, the std::async()
function performs much the same task as std::thread
, without the need to call join()
or detach()
and while also allowing return values via a std::future
object.
In this recipe, we'll use a function that counts the number of primes in a range. We'll use chrono::steady_clock
to time the execution of each thread.
We'll start with a couple of convenience aliases:
using launch = std::launch;using secs = std::chorno::duration<double>;
std::launch
has launch policy constants, for use with the async()
call.
The secs
alias is a duration
class, for timing our prime number calculations.
Our target function counts prime numbers in a range. This is essentially a way to understand the execution policies by eating some clock cycles:
struct prime_time {secs dur{};uint64_t count{};};prime_time count_primes(const uint64_t& max) {prime_time ret{};constexpr auto isprime = [](const uint64_t& n) {for(uint64_t i{ 2 }; i < n / 2; ++i) {if(n % i == 0) return false;}return true;};uint64_t start{ 2 };uint64_t end{ max };auto t1 = steady_clock::now();for(uint64_t i{ start }; i <= end ; ++i) {if(isprime(i)) ++ret.count;}ret.dur = steady_clock::now() - t1;return ret;}
The prime_time
structure is for the return value, with elements for duration and count. This allows us to time the loop itself. The isprime
lambda returns true
if a value is prime. We use steady_clock
to calculate the duration of the loop that counts primes.
In
main()
, we call our function and report its timing:
int main() {constexpr uint64_t MAX_PRIME{ 0x1FFFF };auto pt = count_primes(MAX_PRIME);cout << format("primes: {} {:.3}\n", pt.count, pt.dur);}
Output:
primes: 12252 1.88008s
Now, we can run
count_primes()
asynchronously withstd::async()
:
int main() {constexpr uint64_t MAX_PRIME{ 0x1FFFF };auto primes1 = async(count_primes, MAX_PRIME);auto pt = primes1.get();cout << format("primes: {} {:.3}\n", pt.count, pt.dur);}
Here, we call async()
with ...