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








 
  
  
 
 "BCS" <anon anon.com>
 "BCS" <anon anon.com> 