shared - i need it to be useful

Nicholas Wilson iamthewilsonator at hotmail.com
Tue Oct 16 00:08:11 UTC 2018


On Monday, 15 October 2018 at 23:30:43 UTC, Stanislav Blinov 
wrote:
> On Monday, 15 October 2018 at 21:51:43 UTC, Manu wrote:
>
>> If a shared method is incompatible with an unshared method, 
>> your class is broken.
>
> What?!? So... my unshared methods should also perform all 
> that's necessary for `shared` methods?

No, its the other way around: a shared method that does extra 
synchronisation should work irrespective of wether or not the 
object needs that synchronisation. e.g. atomic loading a TLS 
variable is fine.

>> Explicit casting doesn't magically implement thread-safety, it
>> basically just guarantees failure.
>
> It doesn't indeed. It does, however, at least help prevent 
> silent bugs. Via that same guaranteed failure. That failure is 
> about all the help we can get from the compiler anyway.
>
>> What I suggest are rules that lead to proper behaviour with 
>> respect to writing a thread-safe API.
>> You can write bad code with any feature in any number of ways.
>
> Yup. For example, passing an int* to a function expecting 
> shared int*.

That is a reasonable thing to do if shared is const + no 
unsynched reads.

>> I see it this way:
>> If your object has shared methods, then it is distinctly and
>> *deliberately* involved in thread-safety. You have deliberately
>> opted-in to writing a thread-safe object, and you must deliver 
>> on your promise.
>>
>> The un-shared API of an object that supports `shared` are not 
>> exempt from the thread-safety commitment, they are simply the 
>> subset of the API that may not be called from a shared context.
>
> And therefore they lack any synchronization. So I don't see how 
> they *can* be "compatible" with `shared` methods.
>

I think Manu means you have a shared object with some shared 
methods and some unshared methods. The shared methods deal with 
synchronisation and can therefore be call from anywhere by 
anyone, whereas the unshared methods must be called on a locked 
object.

> snip
>> Nobody writes methods of an object such that they don't work 
>> with each other... methods are part of a deliberately crafted 
>> and packaged
>> entity. If you write a shared object, you do so deliberately, 
>> and you buy responsibility of making sure your objects API is 
>> thread-safe.
>> If your object is not thread-safe, don't write shared methods.
>
> Ahem... Okay...
>
> import std.concurrency;
> import core.atomic;
>
> void thread(shared int* x) {
>     (*x).atomicOp!"+="(1);
> }
>
> shared int c;
>
> void main() {
>     int x;
>     auto tid = spawn(&thread, &x); // "just" a typo
> }
>
> You're saying that's ok, it should "just" compile. It 
> shouldn't. It should produce an error and a mild electric 
> discharge into the developer's chair.

Indeed that is just a typo, just as that is a contrived example. 
You'd notice that pretty quick in a debugger.



More information about the Digitalmars-d mailing list