On 10/17/18 12:27 PM, Nicholas Wilson wrote:
On Wednesday, 17 October 2018 at 15:51:04 UTC, Steven Schveighoffer wrote:
On 10/17/18 9:58 AM, Nicholas Wilson wrote:
On Wednesday, 17 October 2018 at 13:25:28 UTC, Steven Schveighoffer wrote:
It's identical to the top one. You now have a new unshared reference to shared data. This is done WITHOUT any agreed-upon synchronization.

It isn't, you typo'd it (I originally missed it too).
int *p3 = cast(int*)p2;

vs

int *p3 = p;

It wasn't a typo.

The first example assigns p2, the second assigns p (which is thread local) _not_ p2 (which is shared), I'm confused.


Here they are again:

int *p;
shared int *p2 = p;
int *p3 = cast(int*)p2;

int *p;
shared int *p2 = p;
int *p3 = p;


I'll put some asserts in that show they accomplish the same thing:

assert(p3 is p2);
assert(p3 is p);
assert(p2 is p);

What the example demonstrates is that while you are trying to disallow implicit casting of a shared pointer to an unshared pointer, you have inadvertently allowed it by leaving behind an unshared pointer that is the same thing.

While we do implicitly allow mutable to cast to const, it's because const is a weak guarantee. It's a guarantee that the data may not change via *this* reference, but could change via other references.

Shared doesn't have the same characteristics. In order for a datum to be safely shared, it must be accessed with synchronization or atomics by ALL parties. If you have one party that can simply change it without those, you will get races.

That's why shared/unshared is more akin to mutable/immutable than mutable/const.

It's true that only one thread will have thread-local access. It's not valid any more than having one mutable alias to immutable data.

-Steve

Reply via email to