Possible bug in atomicOp

Robert Jacques sandford at jhu.edu
Sun Oct 24 18:39:15 PDT 2010


On Sat, 23 Oct 2010 15:50:30 -0400, Sean Kelly <sean at invisibleduck.org>  
wrote:

> Benjamin Thaut <code at benjamin-thaut.de> wrote:
>> Am 23.10.2010 14:52, schrieb dsimcha:
>>> == Quote from Benjamin Thaut (code at benjamin-thaut.de)'s article
>>>> The following testcase (when executed on dual core at least) results
>> > > in
>>>> a endless loop inside atomicOp.
>>>> import std.stdio;
>>>> import std.concurrency;
>>>> enum Messages {
>>>> 	GO,
>>>> 	END
>>>> }
>>>> shared class Account {
>>>> 	private double amount = 0;
>>>> 	double getAmount() const {
>>>> 		return amount;
>>>> 	}
>>>> 	void change(double 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);
>>>> 	send(father,Messages.END);
>>>> }
>>>> void main(string[] args)
>>>> {
>>>> 	bank = new Account();
>>>> 	spawn(&otherThread,thisTid);
>>>> 	receiveOnly!(Messages)();
>>>> 	for(int i=0;i<1000;i++)
>>>> 		bank.change(+100);
>>>> 	receiveOnly!(Messages)();
>>>> 	writefln("Program finished. Amount is %s",bank.getAmount());
>>>> }
>>>> Is this a bug, or am I doing something wrong here?
>>>> If it is a bug it is kind of critical because people which are
>> > > reading
>>>> the "the D programming language" book won't be happy to find out
>> > > that
>>>> some of the given examples do not work yet.
>>>
>>> http://d.puremagic.com/issues/show_bug.cgi?id=4782
>>>
>>> Basically, atomicLoad (which atomicOp uses) always returns in ALU
>> > registers.
>>> Floating point numbers need to be returned in floating point
>> > registers.
>>> Therefore, a NaN always gets returned from atomicLoad!double, and a
>> > NaN isn't
>>> equal to anything.
>>
>> So shouldn't there be a static assert to prevent one from using
>> atomicOp with floats and doubles? Or should atomicLoad be implemented
>> to support floats and doubles?
>
> The former in the short term and the latter in the long term.

Well, here's the assembler to load a value onto the FP stack:
float  __int2float  (ref int  x) { asm { fld float  ptr [EAX]; } }
double __long2double(ref long x) { asm { fld double ptr [EAX]; } }

Unfortunately, direct loading from a register doesn't seem to be  
supported. So writing wrapper code which uses a union would be almost as  
fast. I know there is an SSE instruction to load directly from registers,  
but we can't assume SSE support.


More information about the Digitalmars-d mailing list