<bump/>
I would have thought our resident language lawyers and experienced OS devers would have had fun with this one. It seems that "volatile" is like the elephant in the room... no one can ignore it, but everyone wants to pretend that it isn't there.
Doesn't anyone else want to try and understand volatile better to avoid "debugging sessions darker than night"?
Ok, maybe I'll help by providing an example that isn't completely off-base, like my last one was.
Code: Select all
class GimmeStatus
{
public:
GimmeStatus()
{
this->status = 0;
}
int getStatus() const
{
// Hmmm... unsynchronized read. Could there be problems?
return this->status;
}
void setStatus( int newStatus )
{
// Use this as an atomic write, throw away the return value.
::InterlockedExchange( &(this->status), newStatus );
}
private:
int status;
};
Ok, according to what I know about ::InterlockedExchange() and x86, this code should be fine as long as the "status" field is aligned on a 4-byte boundary. By "fine", I mean multiple threads can access the status of a GimmeStatus simultaneously and get the same answer, and if one of the threads sets the status, the other threads will at some point see the new status, and not some messed up half-and-half (which might happen if the reads and writes were to unaligned memory).
With me so far?
Here's where things get scary IMO:
Code: Select all
static GimmeStatus globalStatus;
void thread1()
{
// Wait for the status to change.
while (globalStatus.getStatus() == 0)
{
do_something_else();
}
do_something_important();
}
void thread2()
{
do_something_time_consuming();
globalStatus.setStatus( 1 );
do_something_else();
}
Would this work? What happens if the compiler inlines the call to getStatus() and the optimizer puts the status field in a register? Could this happen?
This is why volatile worries me -- I don't understand enough about the situations where it's necessary.