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