标签:
template<typename T>
class LockFreeStack
{
private:
struct Node
{
std::shared_ptr<T> data;
Node* next;
Node(T const& value):
data(std::make_shared<T>(value))
{}
};
std::atomic<Node*> head;
std::atomic<size_t> threadsInPopCount;
std::atomic<Node*> toBeDeletedChainHead;
static void deleteNodes(Node* nodes)
{
while(nodes != nullptr){
auto const next = nodes->next;
delete nodes;
nodes = next;
}
}
void tryReclaim(Node* oldHead)
{
// If only this thread in the pop.
if (threadsInPopCount == 1) {
auto toBeDeletedList = toBeDeletedChainHead.exchange(nullptr);
// Now, if only this thread in the pop.
if (--threadsInPopCount == 0){
deleteNodes(toBeDeletedList);
}
// If some nodes to be deleted still waiting.
else if (toBeDeletedList != nullptr){
pushListToDelChain(toBeDeletedList);
}
delete oldHead;
}
else{
// If more than one thread in the pop.
pushNodeToDelChain(oldHead);
--threadsInPopCount;
}
}
void pushListToDelChain(Node* nodes)
{
auto last = nodes;
while (auto const next = last->next) {
last = next;
}
pushListToDelChain(nodes, last);
}
void pushListToDelChain(Node* first, Node* last)
{
last->next = toBeDeletedChainHead;
// Put current head of delete chain to the next of the last.
// Then let the first be the head.
while(!toBeDeletedChainHead.compare_exchange_weak(last->next, first));
}
void pushNodeToDelChain(Node* node)
{
pushListToDelChain(node, node);
}
public:
void push(T const& value)
{
auto const newNode = new Node(value);
newNode->next = head.load();
while (!head.compare_exchange_weak(newNode, newNode->next));
}
std::shared_ptr<T> pop()
{
++threadsInPopCount;
auto oldHead = head.load();
while(oldHead
&& !head.compare_exchange_weak(oldHead, oldHead->next));
std::shared_ptr<T> result;
if (oldHead){
result.swap(oldHead->data);
}
tryReclaim(oldHead);
return result;
}
};
标签:
原文地址:http://www.cnblogs.com/wuOverflow/p/4848436.html