Consider the following C+11 code:
#include <chrono>
#include <future>
#include <iostream>
#include <thread>
using namespace std;
int main() {
auto start = chrono::steady_clock::now();
auto elapsed = [start](string s) {
cout << s << (chrono::steady_clock::now() - start).count() << endl;
};
elapsed("A ");
auto fut (async([]() { this_thread::sleep_for(chrono::seconds(2)); }));
elapsed("B ");
this_thread::sleep_for(chrono::seconds(1));
elapsed("C ");
fut.wait();
elapsed("D ");
return 0;
}
Compiling said code on macOS Sierra with the command c++ -std=c++11 -stdlib=libc++ -Wall question.cc -o question
and running, I get the output:
A 27186
B 86970
C 1001961755
D 2001585903
which is expected. It took minimal time to get to A
and B
, waited 1 second and then got to C
, and waiting the remaining of the 2 seconds (1 already elapsed) to get to D
.
The Mac compiler is:
$ c++ --version
Apple LLVM version 8.0.0 (clang-800.0.38)
Target: x86_64-apple-darwin16.0.0
Thread model: posix
On Linux, I compiled the same code with c++ -std=c++11 -pthread question.cc -o question
and ran, and got the result:
A 32423
B 444340
C 1003635793
D 3006121895
The Linux compiler is:
$ c++ --version
c++ (Debian 4.9.2-10) 4.9.2
Copyright (C) 2014 Free Software Foundation, Inc.
I also tried clang++
on Linux, the LLVM C++ compiler. Same result.
Why is there the fully 2 second lag between C
and D
on Linux? Wasn't the async task supposed to run in the background? Am I using the wrong compile options?
async
takes as an optional parameter if you want to start it in a different thread, or just wait until the .wait
is called to run the code.
You chose "I do not care" by omitting it.
If you care, state you want it in a different thread. If not, you should not be surprised if they waited until you .wait
ed to run it, or alternatively started a new thread and ran it there. In your case, one compiler made it lazy, the other put it in its own thread. Both are permitted by the standard.
To get the behavior you expect, pass std::launch::async
as the first argument to std::async
.
Now, in theory async
without being told how to run it is supposed to do something smart. But some compilers punted and said "always doing it lazy is less work for us" (or always async), so did always-lazy whenever you let it.
This is a quality of implementation issue. At this point, you cannot trust async
to be smart on all C++11 compilers you are working with. Come back in a decade.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With