| Thread overview | ||||||||
|---|---|---|---|---|---|---|---|---|
|
March 22, 2016 Synchronization on immutable object | ||||
|---|---|---|---|---|
| ||||
Quiz: does this compile or not?
```
class Klass {}
void main() {
immutable Klass klass = new Klass;
synchronized (klass)
{
// do smth
}
}
```
A D object contains two (!) hidden pointers. Two? Yes: the vtable pointer __vptr, and a pointer to a Monitor struct which contains a synchronization mutex.
The synchronized statement is lowered into druntime calls that *write* to __monitor.
Quiz answer: yes it compiles. Oops?
This is related to an earlier discussion on whether TypeInfo objects should be immutable or not [1]. Should one be able to synchronize on typeid(...) or not?
```
interface Foo {}
void main() {
synchronized(typeid(Foo)) {
// do smth
}
}
```
Because LDC treats the result of typeid as immutable, the code is bugged depending on the optimization level.
[1] http://forum.dlang.org/post/entjlarqzpfqohvnnwjb@forum.dlang.org
| ||||
March 22, 2016 Re: Synchronization on immutable object | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Johan Engelen | Related bug report: https://issues.dlang.org/show_bug.cgi?id=14251 | |||
March 22, 2016 Re: Synchronization on immutable object | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Johan Engelen | On Tuesday, 22 March 2016 at 10:49:01 UTC, Johan Engelen wrote:
> Quiz: does this compile or not?
> ```
> class Klass {}
> void main() {
> immutable Klass klass = new Klass;
> synchronized (klass)
> {
> // do smth
> }
> }
> ```
>
> A D object contains two (!) hidden pointers. Two? Yes: the vtable pointer __vptr, and a pointer to a Monitor struct which contains a synchronization mutex.
> The synchronized statement is lowered into druntime calls that *write* to __monitor.
> Quiz answer: yes it compiles. Oops?
>
> This is related to an earlier discussion on whether TypeInfo objects should be immutable or not [1]. Should one be able to synchronize on typeid(...) or not?
> ```
> interface Foo {}
> void main() {
> synchronized(typeid(Foo)) {
> // do smth
> }
> }
> ```
> Because LDC treats the result of typeid as immutable, the code is bugged depending on the optimization level.
>
> [1] http://forum.dlang.org/post/entjlarqzpfqohvnnwjb@forum.dlang.org
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).
What exactly is bugged about the typeid example under LDC?
| |||
March 22, 2016 Re: Synchronization on immutable object | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Alex Parrill | 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. | |||
March 23, 2016 Re: Synchronization on immutable object | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Johan Engelen | On 03/22/2016 12:49 PM, Johan Engelen wrote:
> Quiz: does this compile or not?
tl; dr: most of druntime internal functions bypass qualifiers and are constant source of type system violation bugs. There is a similar violation with `try { throw new immutable Exception; } catch(Exception) { }` and plenty of array appending bugs have been fixed in the past.
| |||
March 23, 2016 Re: Synchronization on immutable object | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Dicebot | On Wednesday, 23 March 2016 at 00:11:32 UTC, Dicebot wrote: > On 03/22/2016 12:49 PM, Johan Engelen wrote: >> Quiz: does this compile or not? > > tl; dr: most of druntime internal functions bypass qualifiers and are constant source of type system violation bugs. There is a similar violation with `try { throw new immutable Exception; } catch(Exception) { }` and plenty of array appending bugs have been fixed in the past. Thanks. Gives some confidence in the correctness of https://github.com/D-Programming-Language/dmd/pull/5564 | |||
Copyright © 1999-2021 by the D Language Foundation
Permalink
Reply