What's most likely to be happening is that your compiler is not aware that quit_thread
can be changed by another thread (because C doesn't know about threads). Because of that, it's optimising the while
loop to an infinite loop.
In other words, it looks at this code:
quit_thread = TRUE;
while(quit_thread);
and thinks to itself, "Hah, nothing in that loop can ever change quit_thread
to FALSE, so the coder obviously just meant to write while (TRUE);
".
When you add the call to usleep
, the compiler has another think about it and assumes that the function call may change the global, so it plays it safe and doesn't optimise it.
Normally you would mark the variable as volatile
to stop the compiler from optimising it but, in this case, you should use the facilities provided by pthreads and join to the thread after setting the flag to true (and don't have the sub-thread reset it, do that in the main thread after the join if it's necessary). The reason for that is that a join is likely to be more efficient than a continuous loop waiting for a variable change since the thread doing the join will most likely not be executed until the join needs to be done.
In your spinning solution, the joining thread will most likely continue to run and suck up CPU grunt.
In other words, do something like:
Main thread Child thread
------------------- -------------------
fStop = false
start Child Initialise
Do some other stuff while not fStop:
fStop = true Do what you have to do
Finish up and exit
join to Child
Do yet more stuff
And, as an aside, you should technically protect shared variables with mutexes but this is one of the few cases where it's okay, one-way communication where half-changed values of a variable don't matter (false/not-false).
The reason you normally mutex-protect a variable is to stop one thread seeing it in a half-changed state. Let's say you have a two-byte integer for a count of some objects, and it's set to 0x00ff
(255).
Let's further say that thread A tries to increment that count but it's not an atomic operation. It changes the top byte to 0x01
but, before it gets a chance to change the bottom byte to 0x00
, thread B swoops in and reads it as 0x01ff
.
Now that's not going to be very good if thread B want to do something with the last element counted by that value. It should be looking at 0x0100
but will instead try to look at 0x01ff
, the effect of which will be wrong, if not catastrophic.
If the count variable were protected by a mutex, thread B wouldn't be looking at it until thread A had finished updating it, hence no problem would occur.
The reason that doesn't matter with one-way booleans is because any half state will also be considered as true or false so, if thread A was halfway between turning 0x0000
into 0x0001
(just the top byte), thread B would still see that as 0x0000
(false) and keep going (until thread A finishes its update next time around).
And if thread A was turning the boolean into 0xffff
, the half state of 0xff00
would still be considered true by thread B so it would do its thing before thread A had finished updating the boolean.
Neither of those two possibilities is bad simply because, in both, thread A is in the process of changing the boolean and it will finish eventually. Whether thread B detects it a tiny bit earlier or a tiny bit later doesn't really matter.