digitalmars.D.learn - atomicOp problem
- Benjamin Thaut (45/45) Oct 21 2010 I recently read the book "the D programming language" and wanted to try
- BCS (5/17) Oct 21 2010 Are you sure it's endless? IIRC atomic increment on x86 has some fairly ...
- Heywood Floyd (21/73) Oct 21 2010 Interesting!
I recently read the book "the D programming language" and wanted to try out a few of the multithreaded examples pointed out in this book. I tried to write a version of the bank account example using the atomicOp from core.atomic. But when I compile it, it never finishes, it just gets stuck in a endless loop inside atomic.d I think. Here is the code: import std.stdio; import std.concurrency; enum Messages { GO } shared class Account { private float amount = 0; float getAmount() const { return amount; } void change(float change){ atomicOp!"+="(amount,change); } } shared Account bank = null; void otherThread(Tid father){ send(father,Messages.GO); for(int i=0;i<1000;i++) bank.change(-100); } void main(string[] args) { bank = new Account(); spawn(&otherThread,thisTid); receiveOnly!(Messages)(); for(int i=0;i<1000;i++) bank.change(+100); writefln("Program finished. Amount is %s",bank.getAmount()); } If you could please point out what I did wrong I would be very glad. If I did not do anything wrong, I don't quite understand whats the exact problem because the code inside atomic.d looks good (at least at my level of understanding) -- Kind Regards Benjamin Thaut
Oct 21 2010
Benjamin Thaut <code benjamin-thaut.de> wrote:I recently read the book "the D programming language" and wanted to try out a few of the multithreaded examples pointed out in this book. I tried to write a version of the bank account example using the atomicOp from core.atomic. But when I compile it, it never finishes, it just gets stuck in a endless loop inside atomic.d I think.[...]If you could please point out what I did wrong I would be very glad. If I did not do anything wrong, I don't quite understand whats the exact problem because the code inside atomic.d looks good (at least at my level of understanding)Are you sure it's endless? IIRC atomic increment on x86 has some fairly severe performance considerations and you are setting it ip for maximal contention. Try running it for 100 cycles and see if that works. OTOH I'm no expert so I could be totally off base.-- Kind Regards Benjamin Thaut
Oct 21 2010
Interesting! I get the same result, ie an infinite loop, with the CPU at 100% Some things I noticed: - Changing the for-loops to 100 or 10 doesn't help. - Changing the atomicOp from "+=" to just "+" makes it work (although the account doesn't get changed) - Adding a Thread.sleep(1000) in one of the for-loops, before the call to atomic-op, makes it all work with "+=" as well By looking at the code in atomic.d it looks the "+="-operator ends up here: T get, set; do { get = set = atomicLoad!(msync.raw)( val ); mixin( "set " ~ op ~ " mod;" ); } while( !cas( &val, get, set ) ); return set; And I suppose the cas()-function never returns true? I don't know how atomic is supposed to work, so I'm not sure if it's a bug or not. I'm no expert with D, or threading for that matter, so I don't know. (I'm just an expert guesser : ) I guess bug! BR /HF Benjamin Thaut Wrote:I recently read the book "the D programming language" and wanted to try out a few of the multithreaded examples pointed out in this book. I tried to write a version of the bank account example using the atomicOp from core.atomic. But when I compile it, it never finishes, it just gets stuck in a endless loop inside atomic.d I think. Here is the code: import std.stdio; import std.concurrency; enum Messages { GO } shared class Account { private float amount = 0; float getAmount() const { return amount; } void change(float change){ atomicOp!"+="(amount,change); } } shared Account bank = null; void otherThread(Tid father){ send(father,Messages.GO); for(int i=0;i<1000;i++) bank.change(-100); } void main(string[] args) { bank = new Account(); spawn(&otherThread,thisTid); receiveOnly!(Messages)(); for(int i=0;i<1000;i++) bank.change(+100); writefln("Program finished. Amount is %s",bank.getAmount()); } If you could please point out what I did wrong I would be very glad. If I did not do anything wrong, I don't quite understand whats the exact problem because the code inside atomic.d looks good (at least at my level of understanding) -- Kind Regards Benjamin Thaut
Oct 21 2010