[dmd-concurrency] draft 8: the final countdown

Andrei Alexandrescu andrei at erdani.com
Wed Feb 10 12:29:27 PST 2010


Michel Fortin wrote:
> Le 2010-02-10 à 14:08, Andrei Alexandrescu a écrit :
> 
>> Nonono. What should happen is no escape of *field* addresses
>> because those are exposed to races when accessed naively.
>> Synchronized methods do NOT assumes that the *indirections*
>> starting from fields are locked/protected/non-shared.
>> 
>> If I have a pointer to int as a field:
>> 
>> - inside the sychronized method, the pointer itself is protected by
>> the lock and can be considered not shared. Escaping THE ADDRESS OF
>> that pointer would create races because it breaks the assumption
>> that only the method messes with it
>> 
>> - the int pointed to by that field is STILL considered shared by
>> the method AND by the rest of the world so there's never the risk
>> of an undue race. The method can escape it all it wants.
> 
> I understand quite well your intent. I just disagree with it.
> 
> My point is that it will happen quite often that the compiler's
> assumption (that synchronization does not apply beyond indirections)
> isn't adequate: when you need to use an internal array as a buffer,
> or when you need some other hidden data structure. I understand that
> in those cases you need to cast your way around, fine. It looks
> crippled, but let's say that's okay.
> 
> What is much less shiny is that in those cases where you need a cast
> to do the right thing, the compiler will also let you do the wrong
> thing (let a value escape) without a cast. For instance, in your
> example of "casting away shared" with a 'List!double' member, nothing
> prevents a function from escaping a reference to the list as a
> shared(List!double), but doing so will lead to races.

There are no races because the List!double type is either thread-unaware 
in which case there is next to nothing you can do with, or is 
thread-aware in which case it knows how to fend for itself.

> Instead of having T* members implicitly converted to shared(T)*, the
> compiler could just prevent any access to non-shared data through an
> indirection. So you'd still need a cast to do the right thing, but
> the compiler won't let you do the wrong thing by accident.

With the no escape rule you cripple people who rent; without it I 
cripple people who own. Most importantly, I allow escaping of members of 
class type which I think is an important case.


Andrei


More information about the dmd-concurrency mailing list