On Mon, Oct 1, 2018 at 8:55 AM Timon Gehr via Digitalmars-d <digitalmars-d@puremagic.com> wrote: > > On 01.10.2018 04:29, Manu wrote: > > struct Bob > > { > > void setThing() shared; > > } > > > > As I understand, `shared` attribution intends to guarantee that I dun > > synchronisation internally. > > This method is declared shared, so if I have shared instances, I can > > call it... because it must handle thread-safety internally. > > > > void f(ref shared Bob a, ref Bob b) > > { > > a.setThing(); // I have a shared object, can call shared method > > > > b.setThing(); // ERROR > > } > > > > This is the bit of the design that doesn't make sense to me... > > The method is shared, which suggests that it must handle > > thread-safety. My instance `b` is NOT shared, that is, it is > > thread-local. > > So, I know that there's not a bunch of threads banging on this > > object... but the shared method should still work! A method that > > handles thread-safety doesn't suddenly not work when it's only > > accessed from a single thread. > > ... > > shared on a method does not mean "this function handles thread-safety". > It means "the `this` pointer of this function is not guaranteed to be > thread-local". You can't implicitly create an alias of a reference that > is supposed to be thread-local such that the resulting reference can be > freely shared among threads.
I don't understand. That's the point of `scope`... is that it won't escape the reference. 'freely shared' is the antithesis of `scope`. > > I feel like I don't understand the design... > > mutable -> shared should work the same as mutable -> const... because > > surely that's safe? > > No. The main point of shared (and the main thing you need to understand) > is that it guarantees that if something is _not_ `shared` is is not > shared among threads. Your analogy is not correct, going from > thread-local to shared is like going from mutable to immutable. We're talking about `mutable` -> `shared scope`. That's like going from mutable to const. `shared scope` doesn't say "I can share this", what it says is "this may be shared, but *I won't share it*", and that's the key. By passing a thread-local as `shared scope`, the receiver accepts that the argument _may_ be shared (it's not in this case), but it will not become shared in the call. That's the point of scope, no? > If the suggested typing rule was implemented, we would have the > following way to break the type system, allowing arbitrary aliasing > between mutable and shared references, completely defeating `shared`: > > class C{ /*...*/ } > > shared(C) sharedGlobal; > struct Bob{ > C unshared; > void setThing() shared{ > sharedGlobal=unshared; > } > } > > void main(){ > C c = new C(); // unshared! > Bob(c).setThing(); > shared(D) d = sharedGlobal; // shared! > assert(c !is d); // would fail (currently does not even compile) > // sendToOtherThread(d); > // c.someMethod(); // (potential) race condition on unshared data > } Your entire example depends on escaping references. I think you missed the point?