why can't I call const methods on shared objects?

Vlad Levenfeld via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Fri May 9 15:55:56 PDT 2014


Let me see if I understand this right... let's say I have some 
(unshared) class that launches threads to do its real work in.

class Foo {
   this () {thread = spawn (&work);}
   shared void work () {...};
   void send_message (T) (T msg) {thread.send (msg);}
   Tid thread;
}

It has an unshared method to pass messages to the worker thread, 
and everything is copacetic, but what is the best practice for 
when I want another thread to interact with one of these 
instances?

class Bar {
   this () {thread = spawn (&pass);}
   shared void pass () {
     receive (
        (shared Foo F) {this.F = F;}                  // (1)
        (T msg) {(cast(Foo)F).send_message (msg);},   // (2)
     );
   void send_message (T) (T msg) {thread.send (msg);}
   Tid thread;
   Foo F;
}

void main () {
   auto F = new Foo;
   auto B = new Bar;
   B.send_message (cast(shared)F);                    // (3)
   // sleep
}

When I interact with F from at (1), this.F is automatically 
shared (because Bar is shared) so this compiles. Here, this.F 
refers to the same F I would refer to if I accessed this.F from 
the main method, it just gets automatically shared whenever Bar 
is shared. So when I spawn a worker thread, the worker thread 
sees a shared Bar (and shared F), while the main thread sees a 
Bar that it owns, but they are both looking at the same Bar (just 
with different access rules, like a const and non-const reference 
to the same object).
At (2), I have to cast F to unshared in order to send it a 
message. But this is ok, because I am only sending messages, and 
am not risking a race condition. Basically I am announcing "I 
know that multiple threads can see this, but I am taking 
ownership of it and taking responsiblity for preventing races."
And when I cast to shared at (3), I am announcing "I am 
explicitly recognizing that multiple threads may now access this, 
and that there is a potential for races."

Is this the right way to handle this situation?

And on a more general note, the shared keyword, as I understand 
it, is intended to be a sort of compiler-reinforced tag that I 
can use to prevent races the same way const helps prevent 
unintended side-effects, and  to aid my reasoning when I do need 
to debug a race?


More information about the Digitalmars-d-learn mailing list