------- Additional Comments From davids at webmaster dot com 2005-02-23 02:19 -------
> It's not the question of optimization but correctness. Exactly, and not locking objects that may be modified from another thread is not correct. Only the programmer knows whether an object may be modified from another thread. > Having an "initialize on first use" semantics which breaks when > multiple threads use it is as wrong as using global variables > for passing data between functions and forcing clients to > introduce locks to make them reentrant. It doesn't break when multiple threads use it, it breaks when multiple threads use it in a way where one thread might modify an object while another thread access it without locking. POSIX specifies that everything breaks when misused this way. You seem to have an attitude that it's difficult to track data dependencies and ensure correct locking. You talk about "unfortunate timing". What you're missing is that this is what people who write multithreaded programs do all day long. Those who are good at writing multithreaded programs are good at doing exactly this. And this change does not remove any of the burden -- it simply removes a choice (one can trivially add these locks when one knows they're needed or doesn't know they're not needed). > It is usable when > clients are careful, but it's a bad default when we can't > expect all calls to be done from a single thread. Any function that might be called from multiple threads concurrently will require special coding to deal with this situation. You would have to go out of your way to create a situation where just protecting the initialization is sufficient. You have to be careful when you write multithreaded code, period. Functions may require you to hold certain locks when you call them, prohibit you from holding other locks, or require the callers to impose synchronization. This is not some obscure detail unique to COFU, it's the bread and butter of multithreaded programming. POSIX puts the responsibility fully on the application programmer to place locks where there might be concurrent access. In exchange for this effort, the programmer gets the performance benefit of there not being locks when they are not needed. Some hypothetical multithreaded C++ standard might choose a different route. But it would not be POSIX. Again, it is this simple: POSIX prohibits an object from being modified in one thread and accessed in another. C++ specifies initialization on first use. Initialization is modification. Thus first use requires a lock if there can be a concurrent access. The language cannot tell when there can and cannot be a concurrent access, the language cannot tell when a call cannot possibly be first use. I could perhaps ignore all of this if the behavior discussed made a reasonably significant category of code "just work" or removed some of the work involved in getting synchronized code correct, but it does not. In the vast majority of cases, the static object may be modified and locks will be needed anyway. In many cases, it will be known that the static object has already been intialized and will not be modified, and the locks added will be wasted. -- http://gcc.gnu.org/bugzilla/show_bug.cgi?id=20099