#include #include 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)); 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)); } 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)) { 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) { delete ptr; } return res; } else if(ptr->internal_count.fetch_add( -1,std::memory_order_relaxed)==1) { ptr->internal_count.load(std::memory_order_acquire); delete ptr; } } } };