Chapter: Multicore Application Programming For Windows, Linux, and Oracle Solaris - Windows Threading

| Study Material, Lecturing Notes, Assignment, Reference, Wiki description explanation, brief detail |

Atomic Updates of Variables

The Windows API provides a large number of atomic operations, which are referred to in Windows terminology as interlocked functions.

Atomic Updates of Variables

 

The Windows API provides a large number of atomic operations, which are referred to in Windows terminology as interlocked functions. For the full list of functions, refer to the Windows documentation. An example of one such function is InterlockedExchangeAdd(), which atomically adds a value to a variable of type LONG (in Windows a long variable is 32 bits in size, and a LONGLONG is 64 bits in size; the size does not change depending on whether the application is 32-bit or 64-bit). Listing 6.36 shows an example of using InterlockedExchangeAdd() to atomically increment a variable by ten.

 

Listing 6.36   Example of Using InterlockedAdd()

#include <windows.h>

 

void update( LONG* value )

 

{

 

InterlockedExchangeAdd( value, 10 );

 

}

 

The range of atomic operations available encompasses and, or, xor, add, increment, and decrement. All the functions are available for long and longlong data types; some of them are also available for smaller data types like char.

 

There are also some functions that modify the variable and return the old value. InterlockedCompareExchange() performs a compare and swap operation where if the value of the variable matches the expected value, the value of the variable is exchanged with a new value. InterlockedBitTestAndSet() returns the value of a specified bit in the variable and sets its new value to one. Similarly, InterlockedBitTestAndReset() provides the same return value but sets the new value to zero.

 

The code in Listing 6.37 creates two threads and uses InterlockedIncrement() to increment the variable counter shared between the two threads. This approach is lower latency than using a mutex or some other synchronization mechanism.

 

Listing 6.37   Using Atomic Operations to Protect a Shared Variable

#include <math.h> #include <stdio.h> #include <windows.h> #include <process.h>

 

int isprime( int number )

 

{

 

int i;

 

for (i = 2; i < (int)( sqrt( (float)number )+1.0 ); i++ )

 

{

 

if ( number%i == 0) { return 0; }

 

}

 

return 1;

 

}

 

volatile long counter = 0;

 

unsigned int __stdcall test( void * )

 

{

 

while ( counter<100 )

 

{

 

int number = InterlockedIncrement( &counter );

 

printf( "ThreadID %i; value = %i, is prime = %i\n", GetCurrentThreadId(), number, isprime(number) );

}

 

return 0;

 

}

 

int _tmain( int argc, _TCHAR* argv[] )

 

{

 

HANDLE h1, h2;

 

h1 = (HANDLE)_beginthreadex( 0, 0, &test, (void*)0, 0, 0); h2 = (HANDLE)_beginthreadex( 0, 0, &test, (void*)0, 0, 0); WaitForSingleObject( h1, INFINITE );

WaitForSingleObject( h2, INFINITE );

 

CloseHandle( h1 );

 

CloseHandle( h2 ); getchar();

return 0;

 

}

 

Most of these functions enforce full memory ordering, so all memory operations prior to the call become visible to other processors before the atomic operation com-pletes and any operations performed after the atomic operation becomes visible to other processors as happening after the atomic operation.


Study Material, Lecturing Notes, Assignment, Reference, Wiki description explanation, brief detail


Copyright © 2018-2020 BrainKart.com; All Rights Reserved. Developed by Therithal info, Chennai.