More Interlocked Functions
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.