Is the code example for atomic_compare_exchange_weak in cppreference correct?

The following code example is given at http://en.cppreference.com/w/cpp/atomic/atomic_compare_exchange as an example of using std::atomic_compare_exchange_weak :

 void append(list* s, node* n) { node* head; do { head = s->head; n->next = head; } while(! std::atomic_compare_exchange_weak(s->head, head, n)); } 

My understanding is that this has the effect of comparing *(s->head) with head , when it seems to me desirable to compare s->head with head . If the first argument std::atomic_compare_exchange_weak in this example should be &(s->head) , or am I missing something?

UPDATE: specification for std::atomic_compare_exchange_weak says:

 bool atomic_compare_exchange_weak(volatile A* object, C * expected, C desired) noexcept; bool atomic_compare_exchange_weak(A* object, C * expected, C desired) noexcept; 

Effects: Atomic, compares the contents of the memory pointed to by the object ... for equality with the expected ...

I believed that *object compared to expected , but further research shows that the actual value is that *object compared to *expected (that is, in expected "means" which the expected points to "). That would mean that the answer to my original question is β€œno, there is no need to take the address s->head in the example code in cppreference.” But the fact that object must point to std::atomic<T> , and the expected one must point to a T , makes it difficult for me to figure out how to fix the code in cppreference so that it compiles, we want to compare the list heading with a copy of the head of the list, but whether the head of the list is of type std::atomic<T>* , the copy must be of type T* , if the call to std::atomic_compare_exchange_weak is to compile, and I cannot find a way to assign std::atomic<T>* T* without reinterpret_cast Even then, the third parameter std::atomic_compare_exchange_weak must be of type T , but the cppreference example shows both the second and third parameters of the same type, which indicates that the cppreference example is broken. I tried to fix it, but I was stymied by the need to use reinterpret_cast , which just feels wrong.

Interestingly, in my attempts to figure this out, I checked the msdn page for std::atomic_compare_exchange_weak , and I was alarmed to see prototypes for std::atomic_compare_exchange_*strong* !

Can someone post plausible code that uses std::atomic_compare_exchange_weak to insert a node at the beginning of a singly linked list? There is no need to worry about the ABA problem or do something unusual. I would just like to compile skeletal code.

+7
source share
1 answer

The correct example is:

 struct list { std::atomic<node*> head; }; ... void append(list* s, node* n) { node* head; do { head = s->head; n->next = head; } while (!std::atomic_compare_exchange_weak(&(s->head), &head, n)); // or while (!s->head.compare_exchange_weak(head, n)); } 

list::head should be a std::atomic object if you don't want to deal with undefined. On the platform in question, you may need some or all of the material std::atomic , which will be implemented using locks. Therefore, std::atomic<T*> may include additional elements, and reinterpret_cast<std::atomic<T*>*> is the case when UB means that your program will work.

+1
source

All Articles