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 our count_primes function and the MAX_PRIME parameter. This runs ...