Search code examples
c++memory-alignmentstdatomiccompare-and-swap

Partial-compare-and-full-swap for atomic values


The problem is as follows.

Given a POD object that has two parts: index and data. I want to perform an atomic conditional exchange operation over it with a condition that checks equality for the index only.

Something like this:

struct Data { size_t m_index; char m_data; };
std::atomic<Data> dd; // some initialization
Data zz; // some initialization

// so I want something like this
dd.exchange_if_equals<&Data::m_index>(10,zz);

So this is a sort of "partial-compare-and-full-swap" operation. Maybe this will require an appropriate alignment for Data::m_index.

Obviously std::atomic doesn't support this, but can one implement this by his own, or maybe there is another library that supports this?


Solution

  • I think you have to do a load, then your custom condition, then a compare-and-swap, where the comparison is that the current value is totally equal to the read value. If the last step fails, loop.

    template<class T, class F>
    bool swap_if(std::atomic<T>& atomic, T desired, F&& condition) {
        for (;;) {
            T data = atomic.load();
            if (!condition(data)) break;
            if (atomic.compare_exchange_weak(data, desired)) return true;
        }
        return false;
    }
    

    http://coliru.stacked-crooked.com/a/a394e336628246a9

    Due to the complexity, you should probably just use a mutex. Separately, std::atomic<Data> may already be using a mutex under the covers, since Data is so big.