7

I want to know how to implement compare_and_swap in c++11. Here's what I tried:

template<typename T>
T compare_and_swap(atomic<T>& reg,T newVal )
{
    bool success = false;
    T oldVal;
    do
    {
        oldVal = reg.load();
        success = reg.compare_exchange_weak(oldVal,newVal);
    }while(!success);
    return oldVal;
}

Is there a better way to implement this?

nkorth
  • 1,684
  • 1
  • 12
  • 28
AntiMoron
  • 1,286
  • 1
  • 11
  • 29
  • You should try to ask in http://codereview.stackexchange.com/ – Jose Palma Apr 11 '15 at 09:17
  • 4
    compare_exchange already does the swap, you don't need your wrapper at all. – Mat Apr 11 '15 at 09:32
  • @Mat negative, compare_exchange would certainly add code lines in some situation.situation that need semantics of compare_and_swap many times – AntiMoron Apr 11 '15 at 09:40
  • I don't understand what you're saying. compare_exchange *is* compare_and_swap, just a different name. If you don't want the loop, use the strong variant. – Mat Apr 11 '15 at 09:43
  • @Mat tks dude. I didn't understant compare_exchange clearly. – AntiMoron Apr 11 '15 at 09:54
  • 2
    This `compare_and_swap` isn't an equivalent of standard `compare_exchange_strong`. The later one can fail and return false, while the former loops until it succeeds. This is an equivalent of `exchange`. In fact it's a valid implementation of `exchange` for a CPU without atomic exchange instruction. But it's slightly inefficient: you shouldn't `load()` inside the loop because you get the updated value from the previous iteration. – Constantin Baranov Apr 11 '15 at 17:27

1 Answers1

0

This is how I would do it:

//untested code
template<typename T>
T compare_and_swap(atomic<T>& reg,T newVal )
{
     oldVal = atomic_load(reg);
     while(!atomic_compare_exchange_weak(&reg, &oldVal, newVal));
     return oldVal;
}

The compare exchange function will update the oldval value if it fails. Therefore there is no need repeating this.

As you can see I prefer to use the explicit atomic operations. This is because the full one's aren't always implemented. As is explained by Herb Sutter here(the rest of the video might also interest you:) ).

As a posibbly unnecessary afterthought I would like to warn against using this function with non trivially copyable types. Or 'normal' pointers. Shared pointers are in general okay:).

laurisvr
  • 2,724
  • 6
  • 25
  • 44