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.

Reply via email to