На этом шаге мы рассмотрим функции, реализующие такой доступ.
Часто возникает необходимость совершения операций над разделяемыми между потоками 32-разрядными переменными. Для упрощения решения этой задачи Windows API предоставляет функции защищенного доступа к переменным (interlocked variable access), не требующие дополнительных (и более сложных) механизмов синхронизации. Переменные в этих функциях должны быть выровнены по границе 32-разрядного слова. Применительно к Delphi это означает, что если переменная объявлена внутри записи (record), то эта запись не должна быть упакованной (packed) и при ее объявлении должна быть активна директива компилятора {$А+}. Несоблюдение этого требования может привести к возникновению ошибок на многопроцессорных конфигурациях, что иллюстрируется приведенным ниже примером.
type TPackedRecord = packed record A: Byte; B: Integer; end; // TPackedRecord.B нельзя использовать в функциях InterlockedXXX TNotPackedRecord = record A: Byte; B: Integer; end; {$A-} var A1: TNotPackedRecord; // A1.B нельзя использовать в функциях InterlockedXXX I: Integer // I можно использовать в функциях InterlockedXXX, так как // переменные в Delphi всегда выравниваются по границе слова, // независимо от состояния директивы компилятора $A {$A+} var A2: TNotPackedRecord; // A2.B можно использовать в функциях InterlockedXXX
Далее мы рассмотрим функции для защищенного доступа к разделяемым между потоками 32-разрядным переменным, предоставляемые Windows API.
function InterlockedIncrement( var Addend: Integer ): Integer; stdcall;
Функция увеличивает переменную Addend на 1. Возвращаемое значение зависит от операционной системы.
function InterlockedDecrement( var Addend: Integer ): Integer; stdcall;
Функция уменьшает переменную Addend на 1. Возвращаемое значение аналогично возвращаемому значению функции InterlockedIncrement.
function InterlockedExchange( var Target: Integer; Value: Integer ): Integer; stdcall;
Функция записывает в переменную Target значение Value и возвращает предыдущее значение переменной Target.
Следующие функциидля выполнения требуют Windows 98 или Windows NT 4.0 и выше.
function InterlockedCompareExchange( var Destination: Pointer; Exchange: Pointer; Comperand: Pointer ): Pointer; stdcall;
Функция сравнивает значения Destination и Comperand. Если они совпадают, значение Exchange записывается в Destination. Функция возвращает начальное значение Destination.
function InterlockedExchangeAdd( Addend: PLongint; Value: Longint ): Longint; stdcall;
Функция добавляет к переменной, на которую указывает Addend, значение Value и возвращает начальное значение Addend.
На следующем шаге мы рассмотрим взаимную блокировку.