Windows System Programming Third Edition [Electronic resources]

Johnson M. Hart

نسخه متنی -صفحه : 291/ 133
نمايش فراداده

  • 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.