Re: Will Modern C++ Design ever get fixed? Organization: unknown
On Oct 20, 8:49 pm, Charles Bryant <n871108125...@chch.demon.co.uk>
wrote:
In article <ZZOdnY5hF_pwUjHRnZ2dnUVZ8uCdn...@giganews.com>,
Leigh Johnston <le...@i42.co.uk> wrote:
}My reply was slightly unclear, the following code snippet clarifies it I hope:
}
}static DWORD WINAPI thread_proc(LPVOID aThreadableObject)
}{
} ::Sleep(1000); // wait for a second
} bool* p = (bool*)aThreadableObject;
} if (p)
} *p = false;
} return 0;
}}
}
}int main()
}{
} bool gotOne = false;
} bool b = false; // not volatile
} HANDLE thread = ::CreateThread(NULL, 0, thread_proc, &b, 0, NULL);
} b = true;
} while(b)
} {
} gotOne = true;
} rand(); /* any (library) function which the optimizer cannot analyze seems to
}work,
} a wait on the thread or some mutex locking would be less contrived */
} }
} if (gotOne)
} std::cout << "volatile not needed";
}}
In case anyone is wondering, no compiler can optimise the test of b.
If the compiler does not know what ::CreateThread() does, then it must
allow for the possibility that it saves the address of b that was
passed in. If it does not know what rand() does, then it must allow
for the possibility that it uses the pointer saved by ::CreateThread()
to change b. Hence it cannot optimise away the repeated test of b.
Of course a compiler might be smart enough to know what those function
do, but in that case it would know that the address of b was likely to
be used by another thread and also could not optimise away the test of
b.
If a compiler was smart enough to know that rand() couldn't modify b
but not smart enough to know that ::CreateThread() created a thread,
which could modify b then it is an excellent example of the proverb that
"A little knowledge is a dangerous thing." because such a compiler is
useless for multithreaded code.
What? No. That is a perfectly legitimate compiler transformation. You
have a formal race condition, so all bets are off. If you want
communication between threads, that communication /must/ be with
proper synchronization primitives. Otherwise you're in undefined
behavior land.
I don't recall what the win32 spec says on the matter, but I suspect
it's undefined behavior. IIRC POSIX says this program (with the
pthreads primitives) has a race condition, and race conditions are
undefined behavior. Finally, C++0x definitely says that this program
(with the C++0x primitives) would have a race condition, and race
conditions are undefined behavior.
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]