{ TInterlockedEx }
class function TInterlockedEx.CAS(var aTarget: integer; aCurrentVal, aNewVal: integer): boolean;
begin
{
//Compare, if equal then set and return TRUE
if aTarget = aCurrentVal then
begin
aTarget := aNewVal;
result := true;
else
result := false;
}
result := InterlockedCompareExchange(aTarget, aNewVal, aCurrentVal) = aCurrentVal;
end;
class procedure TInterlockedEx.Add(var aValue: integer; aCounter: integer);
//EDX,ECX
{$IFDEF WIN32}
ASM
LOCK XADD [EDX], ECX
MOV EAX, [EDX]
END;
{$ELSE}
begin
_Lock.Lock;
try
System.Inc(aValue, aCounter);
finally
_Lock.Unlock;
end;
end;
{$ENDIF}
{$IFDEF WIN32}
class function TInterlockedEx.CAS(var aTarget: pointer; aCurrentVal, aNewVal: pointer): boolean;
begin
result := CAS(integer(aTarget), integer(aCurrentVal), integer(aNewVal));
end;
class function TInterlockedEx.CAS(var aTarget: TObject; aCurrentVal, aNewVal: TObject): boolean;
begin
result := CAS(integer(aTarget), integer(aCurrentVal), integer(aNewVal));
end;
{$ENDIF}
class function TInterlockedEx.Dec(var aValue: integer): integer;
begin
result := InterlockedDecrement(aValue);
end;
class function TInterlockedEx.Inc(var aValue: int64): integer;
begin
if _Lock <> nil then //This is also call by _Lock.Create(), that's why we check first
_Lock.Lock;
try
System.Inc(aValue);
result := aValue;
finally
if _Lock <> nil then
_Lock.Unlock;
end;
end;
class function TInterlockedEx.Exchange(var aValA, aValB: integer): integer;
begin
result := InterlockedExchange(aValA, aValB);
end;
class procedure TInterlockedEx.Sub(var aValue: integer; aCounter: integer);
//EDX,ECX
{$IFDEF WIN32}
ASM
NEG ECX //1-3 = 1+(-3)
LOCK XADD [EDX], ECX
MOV EAX, [EDX]
END;
{$ELSE}
begin
_Lock.Lock;
try
System.Dec(aValue, aCounter);
finally
_Lock.Unlock;
end;
end;
{$ENDIF}
class function TInterlockedEx.Inc(var aValue: integer): integer;
begin
result := InterlockedIncrement(aValue);
end;
class function TInterlockedEx.CAS(var aTarget: LongBool; aCurrentVal, aNewVal: LongBool): boolean;
begin
result := CAS(integer(aTarget), integer(aCurrentVal), integer(aNewVal));
end;
class function TInterlockedEx.CAS(var aTarget: cardinal; aCurrentVal, aNewVal: cardinal): boolean;
begin
result := CAS(integer(aTarget), integer(aCurrentVal), integer(aNewVal));
end;
class function TInterlockedEx.Dec(var aValue: int64): integer;
begin
_Lock.Lock;
try
System.Dec(aValue);
result := aValue;
finally
_Lock.Unlock;
end;
end;
It works for 32 bits (with optimized assembler) and also for 64 bits (not so optimized yet...)
No comments:
Post a Comment