On Thursday, 18 October 2018 at 10:08:48 UTC, Stanislav Blinov
wrote:
Manu,
how is it that you can't see what *your own* proposal means???
Implicit casting from mutable to shared means that everything
is shared by default! Precisely the opposite of what D
proclaims.
Well, sorta. But that's not a problem, because you can't do
anything that's not threadsafe to something that's shared.
You also essentially forbid defining *any* functions that take
`shared T*` argument(s). You keep asking for concrete "holes".
Don't you see what the previous "atomicInc" example implies???
I certainly don't. Please do elucidate.
If *any* free function `foo(shared T* bar)`, per your
definition, is not threadsafe, then no other function with
shared argument(s) can be threadsafe at all. So how do you call
functions on shared data then? You keep saying "methods,
methods..."
struct Other { /* ... */ }
struct S {
void foo(shared Other*) shared;
}
Per your rules, there would be *nothing* in the language to
prevent calling S.foo with an unshared Other.
That's true. And you can't do anything to it, so that's fine.
So the only way to make your proposal work would be to forbid
all functions from taking `shared T*` or `ref shared T`
argument.
No. Please read this thread again. From the beginning, every
word. Actually, don't do that, because Manu's proposal is simple
and elegant:
1. the rule must be applied that shared object can not be read
or written
2. attributing a method shared is a statement and a promise
that the
method is threadsafe
The rest just follows naturally.
There's actually one more thing: The one and only thing you can
do (without unsafe casting) with a shared object, is call shared
methods and free functions on it.
To sum up, things you implied but never specified in your
proposal:
1. Primitive types can't be explicitly `shared`.
Sure they can, they just can't present a thread-safe interface,
so you can't do anything with a shared(int).
2. Free functions taking `shared` arguments are not allowed.
Yes, they are. They would be using other shared methods or free
functions on the shared argument, and would thus be thread-safe.
If defined in the same module as the type on which they operate,
they would have access to the internal state of the object, and
would have to be written in such a way as to not violate the
thread-safety of other methods and free functions that operate on
it.
3. Only `shared` methods can implement threadsafe operations on
`shared` data (which contradicts (2) already) <- this one you
did specify.
Non-shared methods are perfectly free to be thread-safe (and they
should be, in the sense that they shouldn't interfere with shared
methods). A better way to state this is that only shared methods
may be called on a shared object. A shared object may also be
passed to a function taking a shared parameter.
4. Every variable is implicitly shared, whether intended so or
not.
Well, yes, in the same sense that every variable is also
implicitly const, whether intended so or not.
--
Simen