Search code examples
c++race-conditionicc

How do I prevent race condition WITHOUT using locks in C++?


How do I prevent a race condition WITHOUT locking or using mutexes/semaphors in C++? I'm dealing with a nested for loop in which I will be setting a value in an array:

for (int i = 0; i < m; ++i)
  for (int j = 0; j < n; ++j)
    for (int k = 0; k < o; ++k)
      array[k] += foo(...);

More or less, I want to deal with this so that I can ensure different threads running at the same time don't write to array[k] at the same time. Any suggestions on how to approach this?

Edit: I am running on a Linux machine and I also have to use the Intel compiler. I will be using "icc" instead of "gcc" to compile the code.


Solution

  • Assuming windows and that array contains elements of type LONG you could do something like:

    for (int i = 0; i < m; ++i) 
       for (int j = 0; j < n; ++j) 
          for (int k = 0; k < o; ++k)  {
              LONG val = foo(...);
              InterlockedAdd( &array[k], val);
          }
    

    If you're not working in Windows your platform may have a similar set of APIs. As long as your platform has an InterlockedCompareExchange() type of API you can write your own version of InterlockedAdd().

    Something like the following (disclaimer - untested):

     int InterlockedAdd( int volatile* pDest, int operand)
     {
          int curval = *pDest;
          int oldval;
    
          do {
               oldval = curval;
               curval = InterlockedCompareExchange( pDest, oldval + operand, oldval);
          } while (curval != oldval);
    
          return oldval+operand;
     }
    

    As far as I know, Boost only has limited support for atomic/interlocked operations, apparently only enough to support atomic manipulation of reference counts. I don't think that the support for interlocked operations in Boost is more than implementation detail (I'm currently dealing with an somewhat older version of Boost, so it's possible that this isn't the case anymore).

    There are some portable libraries that support atomic compare and exchange and other atomic operations as documented parts of the interface:

    Also note that C++0x will have support for atomic operations like compare/exchange - I'm not sure what the level of support is in current C++ compilers (it doesn't appear to being VS 2010).