I have a function that accesses(reads and writes to) a std::atomic<bool>
variable. I'm trying to understand the order of execution of instructions so as to decide whether atomic will suffice or if I've got to use mutexes here. The function is given below -
// somewhere member var 'executing' is defined as std::atomic<bool>`
int A::something(){
int result = 0;
// my intention is only one thread should enter next block
// others should just return 0
if(!executing){
executing = true;
...
// do some really long processing
...
result = processed;
executing = false;
}
return result;
}
I've read this page on cppreference which mentions -
Each instantiation and full specialization of the std::atomic template defines an atomic type. If one thread writes to an atomic object while another thread reads from it, the behavior is well-defined (see memory model for details on data races)
and on Memory model page the following is mentioned -
When an evaluation of an expression writes to a memory location and another evaluation reads or modifies the same memory location, the expressions are said to conflict. A program that has two conflicting evaluations has a data race unless either
both conflicting evaluations are atomic operations (see std::atomic)
one of the conflicting evaluations happens-before another (see std::memory_order)
If a data race occurs, the behavior of the program is undefined.
and slight below it reads -
When a thread reads a value from a memory location, it may see the initial value, the value written in the same thread, or the value written in another thread. See std::memory_order for details on the order in which writes made from threads become visible to other threads.
This is slightly confusing to me, which one of above 3 statements are actually happening here?
When I perform if(!executing){
is this instruction an atomic instruction here? and more important - is it guaranteed that no other thread will enter that if loop if one two threads will enter that if body since first one will set executing
to true
?
And if something's wrong with the mentioned code, how should I rewrite it so that it reflects original intention..
if(!executing){ executing = true;
another thread can get in between these 2 statements. Have a look atstd::atomic<>.compare_exchange_XXX
– Disturbancedo some really long processing
at a time? – Brief// my intention is only one thread should enter next block
// others should just return 0
. I apologize if it wasn't clear, I just want other incoming functions to just return 0 without doing that computation part, otherwise they'd be all doing same thing and return multiple times. And I'm the one who has recieved this code from someone else to maintain, the tests are passing but I somehow caught it and was suspicious that this might be wrong. – Netherlands