In many cases, the second memory ordering parameter is not compare_exchangeset to memory_order_relaxed. In such cases, as a rule, this is not the case to omit it, but is potentially less effective.
, , /, , compare_exchange_weak, .
push , ,
, push; .. .
template<typename T>
class mystack {
struct node {
node *next = nullptr;
T data;
int id;
node(int id) : id{id} { }
};
std::atomic<node *> head{nullptr};
public:
void push(T data, int id);
bool pop(T &data);
};
template<typename T>
void mystack<T>::push(T data, int id)
{
node *newnode = new node{id};
newnode->data = std::move(data);
node *current_head = head.load(std::memory_order_relaxed);
for (;;)
{
newnode->next = current_head;
if (head.compare_exchange_weak(current_head, newnode,
std::memory_order_release,
std::memory_order_acquire))
{
std::cout << "Insertion successful\n";
break;
} else
{
std::cout << "Insertion failed after head changed to id: " <<
current_head->id << std::endl;
}
}
}
push load ( A) , , , head ,
, , , .
, compare_exchange_weak , newnode , ( B).
, ( pop), .
, compare_exchange_weak ( ), node current_head head.
current_head , , , , current_head .
, cout current_head->id.
, load, ,
memory_order_relaxed, current_head->id.