On Mon, Oct 22, 2018 at 6:00 AM Timon Gehr via Digitalmars-d <digitalmars-d@puremagic.com> wrote: > > On 22.10.18 12:26, Timon Gehr wrote: > > --- > > module borked; > > > > void atomicIncrement(int* p)@system{ > > import core.atomic; > > atomicOp!("+=",int,int)(*cast(shared(int)*)p,1); > > } > > > > struct Atomic(T){ > > private T val; > > void opUnary(string op : "++")() shared @trusted { > > atomicIncrement(cast(T*)&val); > > } > > } > > void main()@safe{ > > Atomic!int i; > > auto a=&[i][0];// was: Atomic!int* a = &i; > > import std.concurrency; > > spawn((shared(Atomic!int)* a){ ++*a; }, a); > > ++i.val; // race > > } > > --- > > Obviously, this should have been: > > --- > module borked; > > void atomicIncrement(int*p)@system{ > import core.atomic; > atomicOp!"+="(*cast(shared(int)*)p,1); > } > struct Atomic(T){ > private T val; > void opUnary(string op:"++")()shared @trusted{ > atomicIncrement(cast(T*)&val); > } > } > void main()@safe{ > auto a=new Atomic!int; > import std.concurrency; > spawn((shared(Atomic!int)* a){ ++*a; }, a); > ++a.val; // race > } > --- > > (I was short on time and had to fix Manu's code because it was not > actually compilable.)
Nitpick; atomicOp does not receive a shared arg under my proposal, it's not a threadsafe function by definition as discussed a few times.