template
classLockFreeStack
{private:structNode;structCountedNode
{int externalCount = 0;
Node* ptr =nullptr;
};structNode
{
std::shared_ptrdata;
std::atomicinternalCount;
CountedNode next;
Node(Tconst&data_):
data(std::make_shared(data_)),
internalCount(0)
{}
};
std::atomichead;void increaseHeadCount(CountedNode&oldCounter)
{
CountedNode newCounter;do{
newCounter=oldCounter;++newCounter.externalCount;
}while (!head.compare_exchange_strong(oldCounter, newCounter,
std::memory_order_acquire,
std::memory_order_relaxed));
oldCounter.externalCount=newCounter.externalCount;
}public:~LockFreeStack()
{while(pop() !=nullptr);
}void push(T const&data)
{
CountedNode newNode;
newNode.ptr= newNode(data);
newNode.externalCount= 1;
newNode.ptr->next =head.load(std::memory_order_relaxed);while(!head.compare_exchange_weak(newNode.ptr->next, newNode,
std::memory_order_release,
std::memory_order_relaxed));
}
std::shared_ptrpop()
{
auto oldHead=head.load(std::memory_order_relaxed);for(;;){
increaseHeadCount(oldHead);
autoconst nodePtr =oldHead.ptr;if (nodePtr ==nullptr){return shared_ptr();
}if (head.compare_exchange_strong(oldHead, nodePtr->next,
std::memory_order_relaxed)){
std::shared_ptrresult;
result.swap(nodePtr->data);int const increaseCount = oldHead.externalCount - 2;if (nodePtr->internalCount.fetch_add(increaseCount,
std::memory_order_release)== -increaseCount){deletenodePtr;
}returnresult;
}else if (nodePtr->internalCount.fetch_add(-1,
std::memory_order_acquire)== 1){
nodePtr->internalCount.load(std::memory_order_acquire);deletenodePtr;
}
}
}
};