On Thursday, 9 July 2015 at 14:03:18 UTC, Jonathan M Davis wrote:
Well, the compiler is free to assume that a variable that is not marked as shared is thread-local. So, it's free to make optimizations based on that. So, for instance, it can know for a fact that

auto foo = getFoo();
auto result1 = foo.constPureFunction(); // This function _cannot_ mutate foo auto result2 = foo.constPureFunction(); // This function _cannot_ mutate foo
auto bar = foo;

So, it knows that the value of bar is identical to the value of foo and that result1 and result2 are guaranteed to be the same,

Pretty sure that's the same as in C++. Unless there was an acquire operation/barrier in there, the compiler is free to assume that two sequential reads to a memory location, without an intervening write (only considering the same thread), will return the same result. The optimisations that are forbidden in C++ are more subtle.

Really, we can't tell what subtle behavioral problems you're risking with __gshared, because that depends on what the compiler is currently able to do with the assumption that a variable is in TLS. You run into all of the problems that you risk with sharing variables in threads in C++ only worse, because the D compiler is free to assume that an object is thread-local unless it's marked as shared and thus can make optimizations based on that, whereas the C++ compiler can't. And you've thrown away all of the compiler's help by using __gshared. __gshared is intended specifically for use with interacting with C code where we don't really have a choice, and you have to be careful with it.

Basically, __gshared pretends to compatible with C(++) globals, but in actual fact it doesn't share the same memory model so who knows what might happen... It's not just dangerous-so-be-very-careful, it's fundamentally broken and we're currently just getting away with it by relying on C(++) optimisers.

Reply via email to