Другой важный аспект, связанный с Interlocked-функциями, состоит в том, что они выполняются чрезвычайно быстро. Вызов такой функции обычно требует не более 50 тактов процессора, и при этом не происходит перехода из пользовательского ре жима в режим ядра (а он отнимает не менее 1000 такюв).
Кстати, InterlockedExchangeAdd позволяет не только увеличить, но и уменьшить значение — просто передайте во втором параметре отрицательную величину. Interlo ckedExchangeAdd возвращает исходное значение в *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_fResour ceInUse присваивается значение TRUE и проверяется ее предыдущее значение. Если оно было равно FALSE, значит, ресурс не был занят, но вызывающий поток только что занял его, на этом цикл завершается. В ином случае (значение было равно TRUE) ре сурс занимал другой поток, и цикл повторяется
Если бы подобный код выполнялся и другим потоком, его цикл while работал бы до тех пор, пока значение переменной g_fResourceInUse вновь не изменилось бы на FALSE. Вызов InterlockedExchange в конце функции показывает, как вернуть перемен ной g_fResourceInUse значение FALSE.