使用引用计数方法管理内存的无锁栈 I

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;
    }
    
};
原文地址:https://www.cnblogs.com/wuOverflow/p/4848436.html