InterlockedExchangeAdd() "performs an atomic addition of Value to the value pointed to by Addend. The result is stored in the address specified by Addend."
The System.SyncObjs unit has a TInterlocked class, which has overloaded Add() methods to do the same thing:
Increments an integer value with another.
There are two overloaded Add methods. Both Add methods increment a Target by Increment.
class function Add(var Target: Integer; Increment: Integer): Integer; overload; static; inline;
class function Add(var Target: Int64; Increment: Int64): Int64; overload; static; inline;
The difference is that InterlockedExchangeAdd() "returns the initial value of the variable pointed to by Addend", whereas TInterlocked.Add() "returns the value of the incremented parameter" instead. So, if you use the return value, you will have to account for that difference, eg:
function InterlockedExchangeAdd(var Addend: Integer; Value: Integer): Integer;
begin
Result := TInterlocked.Add(Addend, Value) - Value;
end;