When it comes to implementing CAS Loop using std::atmoic, cppreference in this link gives the following demonstration for push:
template<typename T>
class stack
{
std::atomic<node<T>*> head;
public:
void push(const T& data)
{
node<T>* new_node = new node<T>(data);
new_node->next = head.load(std::memory_order_relaxed);
while(!head.compare_exchange_weak(new_node->next, new_node,
std::memory_order_release,
std::memory_order_relaxed /* Eh? */));
}
};
Now, I don't understand how come std::memory_order_relaxed is used for the failure case, because as far as I understand, compare_exchange_weak (same for -strong but I'll just use the weak version for convenience) is a load operation at failure, which means it loads from a successful CAS operation in another thread with std::memory_order_release, and thus it should use std::memory_order_acquire instead to be synchronized-with...?
What if, hypothetically, the 'relaxed load' gets one of the old values, ending up failing again and again, staying in the loop for extra time?
The following scratchy picture is where my brain is stuck at.
So to sum up my question,
- Why not
std::memory_order_acquire, instead ofstd::memory_order_relaxedat failure? - What makes
std::memory_order_relaxedsufficient? - Does
std::memory_order_relaxedon failure mean (potentially) more looping? - Likewise, does
std::memory_order_acquireon failure mean (potentially) less looping? (beside the downside of the performance)

Aucun commentaire:
Enregistrer un commentaire