On 10/01/2018 04:29 AM, Manu wrote:
struct Bob
{
   void setThing() shared;
}
[...]
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.
[...]
I feel like I don't understand the design...
mutable -> shared should work the same as mutable -> const... because
surely that's safe?

`shared` isn't analogous to `const`. It's analogous to `immutable`. Functions dealing with `shared` data can assume that other threads also see the data as `shared`. If you allow calling `shared` methods on non-`shared` objects, you're breaking that.

Example:

----
struct Bob
{
  int* p;
  void doThing() shared
  {
    p = &s;
  }
}

shared int s;

void main()
{
  Bob bob;
  (cast(shared Bob)bob).doThing();/* You'd make the cast implicit. */

  import core.thread;
  import core.atomic;
  enum n = 1_000_000;
  auto t = new Thread(() { foreach (i; 0 .. n) atomicOp!"+="(s, 1); });
  t.start();
  foreach (i; 0 .. n) ++*bob.p;
  thread_joinAll();

  import std.stdio;
  writeln(s); /* usually not "2000000", because of race */
}
----

Reply via email to