InterlockedIncrement and InterlockedDecrement have already been shown to be useful when all you need to do is perform very simple operations on thread-shared variables. Several other functions allow you to perform atomic operations to compare and exchange variable pairs.
Interlocked functions are as useful as they are efficient; they are implemented in user space with a few machine instructions.
InterlockedExchange stores one variable into another, as follows:
LONG InterlockedExchange ( LPLONG Target, LONG Value)
The function returns the current value of *Target and sets *Target to Value.
InterlockedExchangeAdd adds the second value to the first.
LONG InterlockedExchangeAdd ( PLONG Addend, LONG Increment)
Increment is added to *Addend, and the original value of *Addend is returned. This function allows you to increment a variable by 2 (or more) atomically, which is not possible with successive calls to InterlockedIncrement.
The final function, InterlockedCompareExchange, is similar to InterlockedExchange except that the exchange is done only if a comparison is satisfied.
PVOID InterlockedCompareExchange ( PVOID *Destination, PVOID Exchange, PVOID Comparand)
This function atomically performs the following (the use of PVOID types for the last two parameters is confusing):
Temp = *Destination; if (*Destination == Comparand) *Destination = Exchange; return Temp;
One use of this function is as a lock to implement a code critical section. *Destination is the lock variable, with 1 indicating unlocked and 0 indicating locked. Exchange is 0 and Comparand is 1. A calling thread knows that it owns the critical section if the function returns 1. Otherwise, it should sleep or "spin"that is, execute a meaningless loop that consumes time for a short period and then try again. This spinning is essentially what EnterCriticalSection does when waiting for a CRITICAL_SECTION that has a nonzero spin count; see Chapter 9 for more information.