Let's say I have this application:
#include <atomic>
#include <thread>
#include <iostream>
#include <chrono>
void do_something(const std::atomic<bool>& stop) {
while (!stop) {
std::cout << "Doing stuff..." << std::endl;
std::this_thread::sleep_for(std::chrono::seconds(1));
}
}
int main() {
std::atomic<bool> stop { false };
std::thread wait([&stop] {
std::this_thread::sleep_for(std::chrono::seconds(10));
stop = true;
});
do_something(stop);
wait.join();
}
This works as expected. The main thread loops until the wait
thread sets stop
. As far as I know, there's no real issues with this application since it's using an std::atomic<bool>
for synchronization between the threads.
However, I can break the application by changing the signature of do_something
to this:
void do_something(const bool& stop);
This still compiles without any warnings, but the loop in do_something
never exits. Conceptually, I understand why this happens. do_something
is accepting a const reference to a non-atomic value, so it would be reasonable to optimize the function to something like:
void do_something(const bool& stop) {
if (!stop) {
while(true) {
std::cout << "Doing stuff..." << std::endl;
std::this_thread::sleep_for(std::chrono::seconds(1));
}
}
}
What's confusing to me is why the modified application compiles at all. I wouldn't expect to be able to pass an std::atomic
value into a function expecting a const reference to a non-atomic type. I haven't looked at the standard, but I don't see anything on cppreference that suggests this conversion is allowed.
Am I misunderstanding something here? Is this just some quirk of std::atomic
that's not obvious to me from the documentation?
CodePudding user response:
This is because there is an implicit conversion when you call
do_something(const bool &stop)
while passing an std::atomic<bool>
It translates to:
do_something(static_cast<bool>(stop.operator bool()));
As you can see here : https://en.cppreference.com/w/cpp/atomic/atomic/operator_T
You actually tell the compiler to load the value once, right at the time of the call.