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