Эквивалент InterlockedExchangeAdd для Linux с использованием Delphi 10.2)
Delphi 10.2 (с поддержкой Linux) имеет кроссплатформенную функцию AtomicExchange, которая эквивалентна Windows InterlocekdEchange. Все идет нормально...
Я должен портировать код Win32, используя InterlockedExchangeAdd, который не имеет эквивалента AtomicExchangeAdd.
Мой вопрос: что я могу использовать для замены InterlockedExchangeAdd при компиляции для Linux?
2 ответа
InterlockedExchangeAdd()
"выполняет атомарное добавление значения к значению, указанному в Addend. Результат сохраняется по адресу, указанному в Addend."
System.SyncObjs
блок имеет TInterlocked
класс, который перегружен Add()
способы сделать то же самое:
Увеличивает целочисленное значение с другим.
Есть два перегруженных
Add
методы. И то и другоеAdd
методы увеличиваютTarget
от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;
Разница в том, что InterlockedExchangeAdd()
"возвращает начальное значение переменной, на которую указывает Addend ", тогда как TInterlocked.Add()
msgstr "возвращает значение увеличенного параметра ". Итак, если вы используете возвращаемое значение, вам придется учитывать эту разницу, например:
function InterlockedExchangeAdd(var Addend: Integer; Value: Integer): Integer;
begin
Result := TInterlocked.Add(Addend, Value) - Value;
end;
В System.SysUtils.pas есть скрытая реализация этой функции:
function AtomicExchangeAdd(var Addend: Integer; Value: Integer): Integer;
begin
Result := AtomicIncrement(Addend, Value) - Value;
end;
Он использует тот факт, что AtomicIncrement возвращает новое значение Addend, а InterlockedExchangeAdd возвращает старое значение. Вычитание значения дает ожидаемый результат и, очевидно, является поточно-ориентированным.