A breach of immutability due to memory implicit conversions to immutable without synchronisation, maybe??
Steven Schveighoffer
schveiguy at gmail.com
Sun Nov 11 20:47:16 UTC 2018
On 11/11/18 2:21 PM, John Colvin wrote:
> Take a look at this (I think?) supposed-to-be-thread-safe code according
> to the rules of D:
>
> import std.stdio;
> import core.thread;
> import core.atomic;
>
> int* foo() pure
> {
> auto ret = new int;
> *ret = 3; // MODIFY
> return ret;
> }
>
> shared immutable(int)* g;
>
> void bar()
> {
> immutable(int)* d = null;
> while (d is null)
> d = g.atomicLoad;
> assert(*d == 3); // READ
> assert(*d == 3); // READ AGAIN
> }
>
> void main()
> {
> auto t = new Thread(&bar).start();
> immutable(int)* a = foo();
> g.atomicStore(a);
> t.join;
> }
>
> What stops the CPU executing this such that MODIFY happens between READ
> and READ AGAIN ?
>
> To aid in the thought experiment, imagine if we replace `*ret = 3` with
> `*ret = longComputation()`? It might help your reasoning about
> re-ordering if you consider `foo` inlined.
Hm... I wouldn't expect the compiler would allow reordering across a
return boundary. Even if the inlining occurs. Implicit conversion of
pure return values depends on that.
I don't know all the rules of reordering, but this would definitely
cause races if it was allowed to reorder the storage of data in *d, and
the storage of d into g.
>
> Is implicit conversion to the shared part of immutable actually safe, or
> does it secretly hide data races?
>
> Another way of putting this:
> Is `ret` secretly shared due to implicit conversion to immutable?
If it is, we need to make it so it's not.
-Steve
More information about the Digitalmars-d
mailing list