Re: Should I use mutex in this context?
Liviu wrote:
"Tommy" wrote...
Ben Voigt [C++ MVP] wrote:
There is no change in logic (as long as the compiler can prove that
someglobal isn't changed by the loop body or any function it calls --
it pays no attention to other threads). The compiler has preserved
the semantics of *sequential* execution as required.
Think about this one:
int a[1000]
for( int i = 0; i < x * y + z - 72; i++ ) {
a[i] = i;
}
The compiler changes this to:
int a[1000];
const int u = x * y + z - 72;
for( int i = 0; i < u; i++ )
a[i] = i;
saving a multiplication, addition, and subtraction on every iteration
of the loop. Of course if the body of the loop changes x, y, or z
then the compiler can't do this any more.
That makes sense because there is no change in flow and as long as the
end result is the same, no problem.
That is not the case in the stated claim:
while(X) { ...}
is fundamentally not the same as:
if (X) do { ....} while(TRUE);
It just isn't. I really, really, really hope this is not true.
It _is_ true if X is _not_ declared as "volatile" and if the compiler
can ascertain that it's non-0 at the beginning of the loop. For example,
given code like
int X;
void f()
{
int n = 0;
for(X = 1; X; )
n++;
printf("n = %d\n", n);
}
> [snip]
This is all understood. But who will do that? It doesn't make sense
to provide examples that are extreme and outside the scope of the
stated design question.
Remember the stated OP question/problem set:
My program has two threads; one main thread and other
working thread. My main thread asks the worker thread to
terminate if system is shutting down by making true a
boolean value which is a global shared resource. The main
thread only writes to the global value and the worker thread
only reads the same value. In this context, is mutex
use necessary?
- A global shared boolean flag
- one writer (main) thread,
- one worker reader thread,
- All he cares for is for a graceful shutdown.
In this case, you don't need a MUTEX or any other synchronization
kernel object, volatile or otherwise.
We are talking about a simple example:
bool stupidflag = 0;
void stupid_thread()
{
while(!stupidflag)
{
... stupid_flag is NOT referenced or visible ...
}
}
Now, Ben brought up a very excellent consideration WRT optimizing
compilers.
I have fail to see assembly in either the old and new Microsoft
compilers for non-optimizing OR full-optimize assembly code where it
fundamentally alters the logic so that it creates a BUG with effective
code that emulates the following flawed code:
if (!stupidflag) do {
... stupid_flag is NOT referenced or visible ...
} while (1)
What I am seeing instead in optimized compiled assembly code that
keeps the end result the same - an transparent optimization that does
not change the outcome using basically this flow:
if (!stupidflag) do {
... stupid_flag is NOT referenced or visible ...
} while (!stupidflag)
I'm sure we can the change scenarios around to prove a point and even
make the flawed do {... } while(1) loop, and I think that is good to
illustrate, but it doesn't answer the OP question.
All my point is that to answer this OP question by stating a MUTEX (or
some other sync object) is required - well, its not quite true.
--