Re: Share .cpp and .h along projects
On Thu, 16 Aug 2007 08:41:35 -0500, "Ben Voigt [C++ MVP]"
<rbv@nospam.nospam> wrote:
That is exactly what "volatile" does. Even in old versions of the compiler,
when memory barriers are not used, volatile exactly prevents the
optimization you are speaking of, in a way that is not fragile to moving
source files between DLLs, changing optimization settings, etc.
Provided that "lock" and "unlock" trigger memory barriers, the code you show
will be correct on any version of the C++ compiler (even non-Microsoft
compilers), using any optimization settings, if you would only say "volatile
int x".
You can't require people to use volatile on top of synchronization.
Synchronization needs to be sufficient all by itself, and it is in any
compiler useful for multithreaded programming.
1. You're not thinking this through. Make x a vector<int>, and then what?
Cast volatile away so you can call its member functions? More generally,
how do you take existing code and use it in a thread-safe way?
2. Using volatile can be a huge performance killer, because it suppresses
optimization inside critical sections, where it's perfectly fine to use.
3. Reading and writing a volatile variable is ordered only WRT reading and
writing other volatile variables and other observable behavior, so what
you're proposing requires pretty much everything to be volatile.
All you need is synchronization.
In fact, if your "x" is in a anonymous namespace, which would be the
recommended practice, and you do not take its address, then the compiler
aliasing analysis can determine that it will not be touched by the "opaque"
DLL, and reorder or remove the access to x once again.
That optimization is not safe for a compiler useful for multithreaded
programming. Note that I didn't say "touched" by the DLL; I said
"reachable" from the DLL. The difference is, the compiler would have to
prove no potential code path in a MT program accesses the variable, which
is quite a tall order.
You *MUST* use "volatile" in this case to guarantee correct behavior, and
when you do, whether the lock and unlock functions are in a DLL is no longer
important.
You can't require people to use volatile on top of synchronization.
Synchronization needs to be sufficient all by itself, and it is in any
compiler useful for multithreaded programming. All you need is
synchronization.
BTW, whether or not lock/unlock are in a DLL is incidental. The important
thing is for the compiler not to perform unsafe optimizations around them,
and this could be specified by tagging them with a __declspec.
No. Unless you have a memory barrier, other threads could see the change to
the pointer before the change to the members of the object are visible.
I said, "it eliminates one of the problems in the DCLP", the key word being
"one". Memory barriers address another issue. The problem I described is
the one James Kanze brought to my attention in this discussion we were
having back in 1999, specifically his concern about inlining the ctor:
http://groups.google.com/group/comp.lang.c++.moderated/browse_frm/thread/13603168924676f5/956334d3a6e92e11?#956334d3a6e92e11
Looking at it now, he may have been overly pessimistic, since the compiler
may inhibit optimizing around the memory barrier instructions I used in my
example.
Your games with DLLs will not save you. "volatile" will save you in VC2005,
and "volatile" combined with InterlockedExchangePointer to update the
pointer is the correct, portable way of doing so.
Clearly, you think volatile is far more relevant than it is. You should
google this group as well as comp.programming.threads for past discussions
on "volatile".
--
Doug Harrison
Visual C++ MVP