2017-04-22 28 views
11

Delphi 10.2 (z obsługą systemu Linux) ma funkcję platformy Cross AtomicExchange, która jest odpowiednikiem systemu Windows InterlocekdEchange. Do tej pory tak dobrze ...Równoważnik InterlockedExchangeAdd dla systemu Linux przy użyciu Delphi 10.2)

Mam do portu kodu Win32 za pomocą InterlockedExchangeAdd, który nie ma odpowiednika AtomicExchangeAdd.

Moje pytanie brzmi: co mogę użyć, aby zastąpić InterlockedExchangeAdd podczas kompilacji dla systemu Linux?

+0

http://stackoverflow.com/q/2287451/505088 –

Odpowiedz

10

InterlockedExchangeAdd() „wykonuje dodatkiem atomowy Wartość do wartości wskazywanej przez składnikiem sumy. Wynik jest przechowywany w adresie podanym przez składnikiem sumy”.

Jednostka System.SyncObjs ma TInterlocked klasę, która przeciążony Add() metod, aby zrobić to samo:

przyrostach wartość całkowitą z innym.

Istnieją dwie przeciążone metody Add. Obie metody Add zwiększają się o Target przez 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; 

Różnica polega na tym, że InterlockedExchangeAdd() „zwraca wartość początkową zmiennej wskazywanej przez składnikiem sumy”, natomiast TInterlocked.Add() „zwraca wartość zwiększany parametru” zamiast. Tak więc, jeśli używasz wartości zwracanej, trzeba będzie wyjaśnić tę różnicę, np:

function InterlockedExchangeAdd(var Addend: Integer; Value: Integer): Integer; 
begin 
    Result := TInterlocked.Add(Addend, Value) - Value; 
end; 
+0

Czy to naprawdę zablokowana (atomowych)? Nawiasem mówiąc, TInterlocked to po prostu wrapper wokół funkcji AtomicXYZ. – fpiette

+0

@fpiette tak, to jest wrapper, ale jest to również publiczny interfejs międzyplatformowy dla operacji atomowych. –

+1

'AtomicIncrement' itp. Są również publiczne między różnymi platformami. Możesz wybrać jedną. –

11

Jest ukryty implementacja tej funkcji w System.SysUtils.pas:

function AtomicExchangeAdd(var Addend: Integer; Value: Integer): Integer; 
begin 
    Result := AtomicIncrement(Addend, Value) - Value; 
end; 

To sprawia, że ​​korzystanie z tego, że AtomicIncrement zwraca nową wartość składnikiem sumy, natomiast InterlockedExchangeAdd zwraca starą wartość. Odejmowanie Wartość daje oczekiwany wynik i oczywiście jest wątkowo bezpieczne.