Shared

Radu void at null.pt
Wed May 15 09:09:36 UTC 2019


On Wednesday, 15 May 2019 at 08:52:23 UTC, Jonathan M Davis wrote:
> On Wednesday, May 15, 2019 1:56:12 AM MDT Radu via 
> Digitalmars-d wrote:
>> On Tuesday, 14 May 2019 at 21:02:10 UTC, Jonathan M Davis 
>> wrote:
>> > On Tuesday, May 14, 2019 8:32:45 AM MDT Radu via 
>> > Digitalmars-d
>> >
>> > wrote:
>> >> [...]
>> >
>> > Sure, it can guarantee that no reference will escape that 
>> > function, but all that's required is that another reference 
>> > to the same data exist elsewhere, and another thread could 
>> > muck with the object while the mutex was locked. There's no 
>> > question that helpers could be created which would help 
>> > users avoid mistakes when casting when casting away shared, 
>> > but the compiler can't actually make the guarantee that 
>> > casting away shared is thread-safe.
>> >
>> > - Jonathan M Davis
>>
>> My view is that the compiler could automatically insert 
>> locking logic (ala synchronized) when the shared parameters 
>> gets references inside the function, and also automatically 
>> cast away shared so for the function internals it would be 
>> like working with local non-shared data.
>>
>> Given that compiler inferes lifetime, it could safely elide 
>> locking if the parameter is passed to other functions that 
>> have the same signature (scope is explicit or inferred).
>>
>> The idea is to provide the tools that simplify concurrent 
>> programming, the compiler will need to insert all the checks 
>> automatically using the lifetime tracking.
>
> The compiler does not have enough information to know which 
> mutexes to use when even if we wanted it to insert locks. TDPL 
> synchronized classes are a special case in that they would 
> provide a way in the language to associate a specific lock with 
> a specific set of variables in a way that the compiler could 
> then guarantee that it's safe to remove the outer layer of 
> shared within a synchronized function. Without a similar 
> mechanism to associate a mutex with one or more variables and 
> guarantee that that mutex is always locked when they're 
> accessed, the compiler won't be able to even know what to lock, 
> let alone that it's safe to remove shared within a particular 
> section of code.
>
> And the issue with what you're proposing with scope is that 
> unless the compiler can actually guarantee that no other 
> references to the shared object exist which could be used to 
> access the object at the same time, then the compiler cannot 
> safely remove shared even temporarily. scope is just enough to 
> guarantee that that particular function can't escape any 
> references, not enough to guarantee that they don't exist. So, 
> while features like scope can be used to make it easier to 
> reason about the code and cast away shared in a way that your 
> code is thread-safe, I fully expect that it's going to have to 
> be up to the programmer to know when it's safe to remove 
> shared, thus requiring a cast or some other @trusted mechanism 
> to temporarily remove shared. TDPL synchronized classes are the 
> only proposal I've seen that would be able to guarantee 
> thread-safety, and it can only do it for what's directly in the 
> class, making TDPL synchronized classes arguably pretty useless 
> (on top of the fact that it means requiring classes when most D 
> code wouldn't normally use classes for something like this).
>
> - Jonathan M Davis

Locks for classes can be done using the class monitor field (like 
synchronized works today). For other types the compiler could 
probably use the typeinfo class for locking, that might be to 
much for some cases. But there may be optimization opportunities, 
like for example use atomics when the target supports it and the 
type is a primitive, or assignment for the reference/pointer, 
same for binary ops when dereferencing a pointer to a primitive.

scope role is to ensure lock/unlock semantics and to help ellide 
superfluous locking when chaining the calls. I'm not proposing a 
ownership system here.
The shared castaway should be performed only inside the locked 
scope, the difference is that the compiler will automatically do 
that for you.

I think this should be enabled only for @safe functions, and not 
for @system.


More information about the Digitalmars-d mailing list