samedi 28 novembre 2015

std::atomic.compare_and_exchange_strong() fails

I am pretty new to C++ and have to do some exercises on atomic operations. I am implementing a AtomicHashSet - but I get confused by compare_and_exchange_strong()behaving different than I would expect it.

As internal data structure I use an array of std::atomic-instances:

std::atomic<Item<T>> data[N] = {};

The essential part observing the problems is the following:

bool insert(const T &key) {
    if (keysStored.load() == N) {
        return false;
    }

    size_t h = this->hash(key);



    for (size_t i = 0; i < N; i++) {
        size_t pos = (h + i) % N;
        data[pos].load(); //No idea why that is needed...
        Item<T> atPos = data[pos].load();

        if (atPos.dataRef == &key) {
            return false;
        }
        if (atPos.dataRef == nullptr && atPos.state == BucketState::Empty) {
            Item<T> atomDesired(&key, BucketState::Occupied);

            if (data[pos].compare_exchange_strong(atPos, atomDesired)) {
                keysStored++;
                return true;
            }
        }
    }

    return false;
}

Item is defined like this:

enum class BucketState { Empty, Occupied, Deleted };

template<typename T>
struct Item {
Item(): dataRef(nullptr), state(BucketState::Empty) {}
Item(const T* dataRef, BucketState state) : dataRef(dataRef), state(state) {}

const T* dataRef;
BucketState state;
};

I do some assertion tests (inserting an element twice, checking keyStoredetc.). With this code they succeed - but if I remove the nonsense data[pos].load(); call they fail due to compare_exchange_strong() returning false. This strange failing behavior occurs only the first time the function is called...

I also checked with a debugger - the value of atPos is the same as in data[pos] - so in my understanding ces should do the exchange and returjn true.

Another question: Do I have to use a special memory order to ensure atomic (and therefore threadsafe) behaviour?

Aucun commentaire:

Enregistrer un commentaire