Re: C++ Threads, what's the status quo?
Le Chaud Lapin wrote:
Mirek Fidler wrote:
Ahh... I guess you should seriously reconsider the issue.
Recommended reading is e.g. google: "why double checked guard does not
work".
Just for starters, if you have
Shared y;
Mutex y_lock;
void fn() {
y_lock.Lock();
y = 10;
y_lock.Unlock();
}
nothing in C++ standard prevents C++ compiler to generate machine code
equivalent to
void fn() {
y = 10;
y_lock.Lock();
y_lock.Unlock();
}
(and now I recommend you to get some C++ reeducation before your
threads start to fail with new compiler version ;)
First, I need to be really clear here. :) I did *NOT* write the code
above. You did. :D This could easily turn into a situation where people
start arguing that "my code does not work as expected." That is not my
code.
That's clear. But the question remains, what do you do to
guarantee that the compiler doesn't do something like this
behind your back?
And there is no place anywhere in any of my synchronization code
that uses double-checked locking. In fact, I did not even know what it
double-checked locking was (by name) until 15 minutes ago, after
finding a paper, per your suggestion. I did think about the concept
briefly, a few years ago, and soon realized that you get no free lunch
- that, if you want mutual exclusion, do not goof around. Ask for it,
have it, do your business, then let it go.
I don't think anyone was accusing you of using double checked
locking. Much discussion about what can and cannot happen,
however, has centered around this problem.
From this paper...
http://www.cs.wustl.edu/~schmidt/editorial-3.html
it should have been obvious that, barring the volatile keyword,
double-checked locking will not work, because the compiler could easily
out-wit the double-check lock programmer by not honouring the
"redundant" read of the "inexpensive" pseudo-semaphore (state
variable).
Using volatile doesn't change anything. And the problem
normally isn't that the compiler won't do the second read; if
the compiler is Posix conform, it knows that it will have to
resync its images of memory after a pthread_mutex_lock. (Of
course, since Posix doesn't define a C++ binding, strictly
speaking, there's no such thing as a Posix conform C++
compiler.) The immediate problem is that the compiler might
reorder the writes in the constructor with regards to the write
of the pointer. And making the pointer volatile doesn't change
that (except with the extension that Microsoft has proposed).
Even if one adds additional synchronization to guarantee the
order of the writes, it is still possible for the hardware to
reorder the reads in the branch which doesn't do any
synchronization; i.e. to read a non-null value for the pointer,
and then read older, uninitialized values in the object itself.
(I don't think the current Intel 32 bit architecture allows
this. Other architectures, including the IA-64 architecture and
Sparc, do.)
I did not look further, but it is my suspicion that, even
with volatile, it could still be circumvented.
Volatile doesn't change the problem an iota.
Again, I did *not* write the code above, nor does my code use
double-checked locking.
But of course, you count on the guarantee that the compiler and
the standard library doesn't do anything similar. From where do
you get that guarantee.
And if it is also true that sequence points are honored by the
C++ Standard after a semi-colon, then my multi-threading
framework still works, with the optimizer enabled, and is
portable.
Sequence points only define order between "observable behavior",
i.e. IO and accesses to volatile variables. A compiler can do
anything it wishes, as long as the observable behavior is
respected. And the observable behavior is not defined for
multi-threading.
--
James Kanze (GABI Software) email:james.kanze@gmail.com
Conseils en informatique orientie objet/
Beratung in objektorientierter Datenverarbeitung
9 place Simard, 78210 St.-Cyr-l'Icole, France, +33 (0)1 30 23 00 34
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]