Windows для профессионалов


Атомарный доступ: семейство Inferlockect-функций - часть 4


Другой важный аспект, связанный с Interlocked-функциями, состоит в том, что они выполняются чрезвычайно быстро. Вызов такой функции обычно требует не более 50 тактов процессора, и при этом не происходит перехода из пользовательского режима в режим ядра (а он отнимает не менее 1000 тактов).

Кстати, InterlockedExchangeAdd позволяет не только увеличить, но и уменьшить значение — просто передайте во втором параметре отрицательную величину. InterlockedExchangeAdd возвращает исходное значение в *plAddend

Вот еще две функции из этого семейства:

LONG InterlockedExchange( PLONG plTarget, LONG IValue);

PVOTD InterlockedExchangePointer( PVOID* ppvTarget, PVOID* pvValue);

InterlockedExchange и InterlockedExchangePointer монопольно заменяют текущее значение переменной типа LONG, адрес которой передается в первом параметре, на значение, передаваемое во втором параметре. В 32-разрядпом приложении обе функции работают с 32-разрядными значениями, но в 64-разрядной программе первая оперирует с 32-разрядными значениями, а вторая — с 64-разрядными. Все функции возвращают исходное значение переменной InterlockedExchange чрезвычайно полезна при реализации спин-блокировки (spinlock):

// глобальная переменная, используемая как индикатор того, занят ли разделяемый ресурс
BOOL g_fResourceInUse = FALSE ;

...

void Func1() {

// ожидаем доступа к ресурсу

while (InterlockedExchange(&g_fResourceInUse, TRUE) = TRUE)
Sleep(0);

// получаем ресурс в свое распоряжение

// доступ к ресурсу больше не нужен
InterlockedFxchange(&g_fResourceInUse, FALSE); }

В этой функции постоянно "крутится" цикл while, в котором переменной g_fResourceInUse присваивается значение TRUE и проверяется ее предыдущее значение. Если оно было равно FALSE, значит, ресурс не был занят, но вызывающий поток только что занял его, на этом цикл завершается. В ином случае (значение было равно TRUE) ре сурс занимал другой поток, и цикл повторяется.

Если бы подобный код выполнялся и другим потоком, его цикл while работал бы до тех пор, пока значение переменной g_fResourceInUse вновь не изменилось бы на FALSE.


Начало  Назад  Вперед



Книжный магазин