Re: WaitForSingleObject() will not deadlock
- From: Joseph M. Newcomer <newcomer@xxxxxxxxxxxx>
- Date: Sun, 08 Jul 2007 23:32:31 -0400
See below...
On Sat, 07 Jul 2007 14:05:46 -0500, "Doug Harrison [MVP]" <dsh@xxxxxxxx> wrote:
On Sat, 07 Jul 2007 13:21:49 -0400, Joseph M. Newcomer*****
<newcomer@xxxxxxxxxxxx> wrote:
On Thu, 05 Jul 2007 22:20:56 -0500, "Doug Harrison [MVP]" <dsh@xxxxxxxx> wrote:
On Thu, 05 Jul 2007 17:02:44 -0400, Joseph M. Newcomer*****
<newcomer@xxxxxxxxxxxx> wrote:
So the question is, what compromises are made to allow C to work in a multithreaded
environment? One is to hijack the semantics of volatile to disable compiler optimizations
that would not be thread-safe, and otherwise let the compiler to agressive optimization.
That's an incredibly undesirable approach for a number of reasons. AFAIK,
no one approaches the problem in that way.
Did you see the C++ Standards Comittee discussion I pointed out?
No, I missed it. Please post it again, cite the relevant sections, and tell
me what you think they mean.
They are in fact considering that.
No, they are not, at least not in the way you think.
We were certainly doing this 35 years ago, so the technology is
well-understood. I worked with optimizing compilers between 1969 and 1983, and these were
issues we were constantly discussing and worrying about. We designed languages that had
explicit specifications of concurrency, and although the word 'volatile' was not one we
used, the issues raised by volatile seem indistinguishable from the issues we were
addressing.
Why is this undesirable?
It's undesirable to require volatile in addition to mutex lock/unlock,
which let's be clear, is what you're proposing, for at least the following
reasons:
1. The compiler would not be free to ignore volatile inside a critical
section; therefore, requiring volatile would slow down access inside the
critical section, but the vast majority of the time, there would be no
reason to respect volatile inside the critical section. Instead, the
compiler should recognize the operations that define the critical section,
e.g. mutex lock/unlock, and then you don't have to "hijack volatile". You
don't have to use it at all. That, in effect, is what POSIX did.
Good point. However, the issue has nothing to do with locking or unlocking, in effect,
you are looking for an explicit "commit" operation that defines a point in the code where
values need to be committed to memory, sort of a meta-volatile. However, coupling this to
locking or unlocking is not the right thing to do here. Locking is a separate operation
that sets and releases locks, and is quite independent of the concept of committing
values. As such, the notion of committing values is actually a compiler feature, not a
runtime or hardware feature, and therefore belongs as part of the formal language
semantics (such as volatile is). Which goes back to my point that defining correct
behavior in terms of low-level hardware operations or incidental features of current
compiler behavior is inappropriate. It is confusing a concept of comiiting values to
memory with a variety of other, largely irrelevant, pieces of behavior. volatile is a
formal requirement about value commitment. As you point out, it *is* overkill, but
coupling the commitment to unlocking does not solve the problem, For unlock to work
properly and do this, the compiler requires metadata about the semantics of that
particular function.
*****
*****
2. Classes such as std::vector are written to be used in a single-threaded
environment. We can use them in a thread-safe way without touching their
implementation by using mutexes to protect their operations that are not
thread-safe. If it were required to also declare vector objects volatile,
then:
But the mutexes only make sure that there is not concurrent access; they are not required
to guarantee that the compiler does not do optimizations.
*****
Joseph M. Newcomer [MVP]
2a. You could not call a member function without casting volatile away,
because none of the member functions are declared volatile. Besides being
ridiculous, this would be undefined for an object originally declared
volatile.
2b. Declaring an object x volatile doesn't make pointer and reference
members of x refer to volatile objects.
The net effect of 2a and 2b is to invalidate current practice and require
classes to come in two versions, one that uses volatile internally and one
that does not. Among other things, this is what one of the guys (Hans J.
Boehm) working on the multithreaded memory model for C++ says here:
A Memory Model for C++: FAQ
http://www.hpl.hp.com/personal/Hans_Boehm/c++mm/faq.html
<q>
Why cannot the compiler optimization issues just be side-stepped by
declaring the relevant shared variables volatile?
...
this turns out to be completely impractical. It is very common to "wrap"
single-threaded code in a lock to make it usable in a multithreaded
application. This would not be possible if all variables/fields in the
single-threaded code now had to be declared volatile. Thread-safe versions
of the C++ standard library, effectively rely on this approach, which we
believe to be the only viable one. It is also similar to the one adopted by
more recent Java container libraries, for example.
Requiring volatile declarations for lock-protected variables would
effectively require most libraries to come in two versions: A standard
version, and one in which all internal static variables were declared
volatile.
...
</q>
FWIW, this is stuff I was telling you years ago. If you just can't accept
it, I implore you, drop by comp.programming.threads,
comp.lang.c++.moderated, and comp.std.c++ and tell everyone how they should
be doing things. Maybe they can explain these things better than me.
I haven't read the remainder of your post, and after skimming it, I may or
may not get to it. I really think our time would be better spent if there
were a wider audience to respond to your viewpoints.
email: newcomer@xxxxxxxxxxxx
Web: http://www.flounder.com
MVP Tips: http://www.flounder.com/mvp_tips.htm
.
- References:
- Re: WaitForSingleObject() will not deadlock
- From: Joseph M . Newcomer
- Re: WaitForSingleObject() will not deadlock
- From: Doug Harrison [MVP]
- Re: WaitForSingleObject() will not deadlock
- From: Joseph M . Newcomer
- Re: WaitForSingleObject() will not deadlock
- From: Doug Harrison [MVP]
- Re: WaitForSingleObject() will not deadlock
- From: Joseph M . Newcomer
- Re: WaitForSingleObject() will not deadlock
- From: Doug Harrison [MVP]
- Re: WaitForSingleObject() will not deadlock
- From: Joseph M . Newcomer
- Re: WaitForSingleObject() will not deadlock
- From: Doug Harrison [MVP]
- Re: WaitForSingleObject() will not deadlock
- From: Joseph M . Newcomer
- Re: WaitForSingleObject() will not deadlock
- From: Doug Harrison [MVP]
- Re: WaitForSingleObject() will not deadlock
- Prev by Date: Re: WaitForSingleObject() will not deadlock
- Next by Date: Re: CProperty***
- Previous by thread: Re: WaitForSingleObject() will not deadlock
- Next by thread: Re: WaitForSingleObject() will not deadlock
- Index(es):