D const enables multi-reader synchronization
Tomek Sowiński
just at ask.me
Tue Jun 15 13:38:58 PDT 2010
Brad Roberts wrote:
> On Mon, 14 Jun 2010, Tomek Sowi?ski wrote:
>
>> Dnia 14-06-2010 o 21:27:24 Brad Roberts <braddr at slice-2.puremagic.com>
>> napisa?(a):
>>
>> > Const methods only prevent mutating 'this'. You can still call
>> > functions that mutate other state (via globals or passed in arguments).
>>
>> But synchronized on a method also protects only 'this', no?. Currently
>> you can have:
>>
>> class A { ... }
>>
>> shared class K {
>> synchronized void fun(A a) const {
>> // mutate a
>> }
>> }
>>
>> If you call fun on two instances of K, each in a different thread, but
>> pass them the same instance of A, you'll get a data race anyway. You
>> could make fun's arguments const, but still there's shared globals.
>
> The lock is per-object but the lock protects all of the code inside the
> block, not just the parts that hang off the this reference.
>
> You're code describes the case I'm talking about. If the mutations to A
> are all inside the K::fun code, and your proposal happens, then code that
> runs safely changes to code that runs unsafely.
>
> I'm not saying it's a good idea to structure code that way, but the
> language rules need to consider all angles, not just the used correctly or
> best practices uses.
Hm, not sure if we understand each other. Perhaps a full example:
import std.stdio;
import core.thread;
class A { int a; }
shared class K {
A a;
synchronized void fun(A a) const {
foreach (i; 0..3) {
writeln(Thread.getThis().name, ": I saw ", a.a, ", changed to ",
++a.a);
Thread.sleep(1_000_000);
}
}
}
class Thr : Thread {
A a;
this(A a, string name) {
super(&run);
this.a = a;
this.name = name;
}
void run() {
auto k = new K;
k.fun(a);
}
}
void main() {
A a = new A;
(new Thr(a, "T1")).start();
(new Thr(a, "T2")).start();
}
Compiled with DMD 2.045 it outputs:
T2: I saw 0, changed to 1
T1: I saw 1, changed to 2
T2: I saw 2, changed to 3
T1: I saw 3, changed to 4
T2: I saw 4, changed to 5
T1: I saw 5, changed to 6
So the 2 sync'ed calls are mutating its parameter at the same time, already
without my proposal.
Anyway, language-level implementation probably doesn't make sense. As Sean
said, it's too much machinery and too many options to devise a standard that
would make everybody happy.
Tomek
More information about the Digitalmars-d
mailing list