Wednesday, February 20, 2019

c++11 - Is it safe to remove the c++ volatile here?



Is it safe to remove volatile from the definition of m_flag here?
If m_flag is not volatile, what would stop compilers from optimizing away this loop's condition: while (!m_flag) m_cv.wait(lock); ?
Does the standard (post-C++11) specify explictly that such optimizations are prohibited in such cases?




#include 
#include
#include
#include
using namespace std;

class foofoo
{
volatile bool m_flag;

mutex m_mutex;
condition_variable m_cv;

public:
void DoWork()
{
m_flag = false;
unique_lock lock(m_mutex);
auto junk = async(std::launch::async, [this]()
{

{
unique_lock lock(m_mutex);
m_flag = true;
}
m_cv.notify_one();
});
while (!m_flag) m_cv.wait(lock);
cout << "ququ" << endl;
}
};


int main()
{
foofoo f;
f.DoWork();
}

Answer



In general, volatile and multithreading are orthogonal in C++11. Using volatile neither adds nor removes data races.




In this case, m_flag = true; is sequenced before the release of the mutex in the thread launched by async ([intro.execution]/p14), which in turn synchronizes with the subsequent acquire of the mutex in m_cv.wait(lock) ([thread.mutex.requirements.mutex]/p11,25), which in turn is sequenced before a subsequent read of m_flag. m_flag = true; therefore inter-thread happens before, and hence happens before, the subsequent read. ([intro.multithread]/p13-14)



Since there are no other side effects on m_flag, m_flag = true; is the visible side effect with respect to that read ([intro.multithread]/p15), and that read must therefore read what was stored by the visible side effect, i.e., true.



A compiler that "optimizes" away that condition, regardless of whether volatile is used, would be non-conforming.


No comments:

Post a Comment

plot explanation - Why did Peaches&#39; mom hang on the tree? - Movies &amp; TV

In the middle of the movie Ice Age: Continental Drift Peaches' mom asked Peaches to go to sleep. Then, she hung on the tree. This parti...