This is the mail archive of the gcc-bugs@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[Bug c++/20099] -pthreads should imply -fno-threadsafe-statics


------- 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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]