On Tuesday, 22 March 2016 at 21:32:24 UTC, Alex Parrill wrote:
As long as there's no race conditions in the initial creation
of the mutex, it shouldn't matter, even though it does
internally mutate the object, because it's transparent to
developers (unless you're going out of your way to access the
internal __monitor field).
Internally, the compiler breaks a language guarantee: it allows
passing an immutable Object to a function as mutable argument.
The synchronization object is passed to _d_monitorenter in
druntime.
An optimizer may use the immutability information, leading to
troubles.
```
import std.stdio : writeln;
interface Foo {}
void main() {
writeln(cast(size_t) typeid(Foo).__monitor);
synchronized(typeid(Foo)) { }
writeln(cast(size_t) typeid(Foo).__monitor);
}
```
This prints two zeros for `ldc2 -O3 -run`. (typeid(Foo) is
immutable in LDC)
So the optimizer deduces the __monitor pointer is still null,
even though it no longer is after the synchronized statement.
What exactly is bugged about the typeid example under LDC?
See https://github.com/ldc-developers/ldc/issues/1377
It is an example proving that synchronizing on an immutable
object is dangerous.