Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Doing more than one atomic operations on shared variable

I want to do two operations on a shared variable. I need to guarantee that it can be done atomically. Can some one help me clarify if the following approach is correct:

#include <atomic>
std::atomic<int> index;

void function()
{
     // I need the variable index to be incremented but bound in the 
     // range of [0,9].
     int loc_indx = index.load(std::memory_order_acquire);
     index.store( (loc_indx+1)%10  , std::memory_order_release);
}

Based on my understanding, the index store operation and index load operation have to happen together. Can some of the experts here clarify if the above code will be equivalent to the following pseudo-code:

ATOMIC
{
   index = (index+1)%10;
}

I have been working with atomic package in c++ part of Visual Studio 2012 or/and boost::atomic part of 1.53.

like image 477
Goutham Avatar asked Jun 16 '26 03:06

Goutham


1 Answers

The whole purpose of atomics is to improve performance compared to locks.

There are no locks in your code. The memory_order enum is just to make sure that the compiler does not reorder the code (nor let the CPU reorder it). This means there is a small chance that some other thread modifies the value between load and store. If the stored value must depend on the previous value, then the calculations done in between are wasted and need to be redone. Doing this can be considerably more efficient than locks since the chance that the concurrent modification does actually occur is low, and the calculations are cheap and simple.

Store when you know the previous value, otherwise recalculate and retry. Something like:

 int loc_index = index.load(std::memory_order_acquire);
 int desired = (loc_index+1)%10;

 while ( !index.compare_exchange_strong( loc_index, desired ) )
 {
     desired = (loc_index+1)%10;
 }

compare_exchange_strong is atomic operation that compares the value stored in index to loc_index; if they are equal, it stores desired into index; if they are not equal, it copies the value of index into loc_index. That helps you to make sure that the next value stored in index is correct one.

like image 175
Öö Tiib Avatar answered Jun 18 '26 18:06

Öö Tiib