On Thursday, 18 October 2018 at 21:51:52 UTC, aliak wrote:
On Thursday, 18 October 2018 at 18:12:03 UTC, Stanislav Blinov wrote:
On Thursday, 18 October 2018 at 18:05:51 UTC, aliak wrote:

Right, but the argument is a shared int*, so from what I've understood... you can't do anything with it since it has no shared members. i.e. you can't read or write to it. No?

Obviously the implementation would cast `shared` away, just like it would if it were Atomic!int. But for some reason, Manu thinks that latter is OK doing that, but former is voodoo. Go figure.

Sounds like one is encapsulated within a box that carefully

Unit of "encapsulation" in D is either a module or a package, not a struct. Free functions are a very valid way of accessing "encapsulated" data.

handles thread safety and makes promises with the API and the other is not.

Nope.

void foo(const T* x);

makes a promise to not write through x. It assumes '*x' itself may not be const.

void foo(shared T* x);

makes a promise to threat '*x' in a thread-safe manner. But per MP, it *assumes* that '*x' is shared. And if it isn't, good luck finding that spot in your code.

I don't think you can apply shared on a free function, i.e.:

void increment(shared int*) shared;

in which case increment would not, and cannot be a threadsafe api in Manu's world.

Wrong. In Manu's "world", this is somehow considered "safe":

void T_method_increment(ref shared T);

...because that is what a method is, while this:

void increment(shared T*);
void increment(ref shared T);

...is considered "unsafe" because reasons. Do you see the difference in signatures? I sure don't.

So once you throw an Object in to shared land all you could do is call shared methods on it, and since they'd have been carefully written with sharing in mind... it does seem a lot more usable.

Same goes with free functions.

On these two cases:

increment(shared int* p1) {
// I have no guarantees that protecting and accessing p1 will not cause problems
 //
// but you don't have this guarantee in any world (current nor MP) because you can
 // never be sure that p1 was not cast from a mutable.
}

Except that you *have to* *explicitly* cast it, which is:
a) documentation
b) greppable
c) easily fails review for people not authorized to do so

int* p2;
increment(p2);
// I have no guarantee that accessing p2 is safe anymore.
// But that would apply only if the author of increment was being unsafe.
// and "increment" cannot be marked as shared.

No. *You*, the caller of an API (the "increment"), do not necessarily control that API. By allowing implicit conversion you waive all claims on your own data. In Manu's world, "increment" *assumes* you're doing the right thing. Yet at the same time, Manu happily talks about how only "experts" can do the right thing. How these two things co-exist in his world, I have no idea.

The "have no guarantee" holds in both cases. Except case (1) would require actually checking what the hell you're doing before making a cast, while in case (2) you just blindly write unsafe code.

Reply via email to