这只是一个push、一个pop的情况,其他待分析。
关于原子操作的几个参数,大概有自己的理解,如果发现有错误,欢迎指出。
code:
template
class lock_free_stack{
private:
struct node;
struct counted_node_ptr {
int external_count;
node* ptr;
};
struct node {
std::shared_ptr data;
std::atomic internal_count;
counted_node_ptr next;
node(T const &data_):
data(std::make_shared(data_)),
internal_count(0)
{}
};
std::atomic head;
void increase_head_count(counted_node_ptr &old_counter) {
counted_node_ptr new_counter;
do {
new_counter = old_counter;
++new_counter.external_count;
}
while(!head.compare_exchange_strong(old_counter, new_counter,
std::memory_order_acquire,
std::memory_order_relaxed)); //需要实时获取head的更新,这是使用memory_order_acquire
old_counter.external_count = new_counter.external_count;
}
public:
~lock_free_stack() {
while(pop());
}
void push(T const &data) {
counted_node_ptr new_node;
new_node.ptr = new node(data);
new_node.external_count = 1;
new_node.ptr->next = head.load(std::memory_order_relaxed);
while(!head.compare_exchange_weak(new_node.ptr->next, new_node,
std::memory_order_release,
std::memory_order_relaxed)); //更新后要及时更新到pop,这是使用memory_order_release
}
std::shared_ptr pop() {
counted_node_ptr old_head = head.load(std::memory_order_relaxed);
for(;;) {
increase_head_count(old_head);
node* const ptr = old_head.ptr;
if (!ptr) {
return std::shared_ptr();
}
if(head.compare_exchange_strong(old_head, ptr->next,
std::memory_order_relaxed)) { //前后没有需要同步的依赖操作,使用memory_order_relaxed
std::shared_ptr res;
res.swap(ptr->data);
int const count_increase = old_head.external_count - 2;
if (ptr->internal_count.fetch_add(count_increase,
std::memory_order_release) == -count_increase) { //修改数据需要及时更新,使用memory_order_release
delete ptr;
}
return res;
}
else if(ptr->internal_count.fetch_add(-1,
std::memory_order_relaxed) == 1) { //无依赖使用memory_order_relaxed
ptr->internal_count.load(std::memory_order_acquire);
delete ptr;
}
}
}
};
摘自《c++并发编程实战》