使用引用计数方法管理内存的无锁栈 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;
    }

};
时间: 2024-10-26 15:30:31

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

无锁栈的实现

template<typename T> class LockFreeStack { private: struct Node; struct CountedNode { int externalCount = 0; Node* ptr = nullptr; }; struct Node { std::shared_ptr<T> data; std::atomic<int> internalCount; CountedNode next; Node(T const&am

使用风险指针(hazard pointer) 处理无锁栈的 push 与 pop

constexpr size_t maxHazardPointers = 100; struct HazardPointer { std::atomic<std::thread::id> id; std::atomic<void*> pointer; }; array<HazardPointer, maxHazardPointers> hazardPointers; class HazardPointerOwner { HazardPointer* hazardPoin

iOS中引用计数内存管理机制分析总结(NSString引用计数为-1的情况)

在 iOS 中引用计数是内存的管理方式,虽然在 iOS5 版本中,已经支持了自动引用计数管理模式,但理解它的运行方式有助于我们了解程序的运行原理,有助于 debug 程序.   操作系统的内存管理分成堆和栈. 在堆中分配的内存,都适用引用计数模式:在栈中则不是. NSString 定义的对象是保存在栈中,所以它没有引用计数,不是通过引用计数对内存进行管理的.之前我在一篇博客上看,说常量的引用计数会是一个很大的整数,测试的结果显示它是-1. 对该对象进行 retain 操作,不好改变它的 reta

Objective-C中的引用计数

导言 Objective-C语言使用引用计数来管理内存,也就是说,每个对象都有个可以递增或递减的计数器.如果想使某个对象继续存活,那就递增其引用计数:用完了之后,就递减其计数.计数为0,就表示没人关注此对象了,于是,就可以把它销毁. 从Mac OS X 10.8开始,“垃圾收集器”(garbage collector)已经正式废弃了,以Objective-C代码编写Mac OS X程序时不应再使用它,而iOS则从未支持过垃圾收集.因此,掌握引用计数机制对于学好Objective-C来说十分重要.

iOS 理解引用计数

一 简介     OC 语言使用引用计数来管理内存每个对象都有个可以递增或递减的计数器,如果想某个对象继续存活,那就递增其引用计数,用完之后,就递减其计数,计数变为0,就销毁. 二 引用计数工作原理 NSObject 协议声明了下面三个方法用于操作计数器,以递增或递减其值 retain 递增引用计数 release 递减引用计数 autorelease 稍后清理"自动释放池"时,在递减引用计数 为避免在不经意间使用了无效对象,一般调用完release 之后都会清空指针.这就能保证不会出

第29条:理解引用计数

第5章 内存管理 在 Objective-C 这种面向对象语言里,内存管理是个重要概念.要想一门语言写出内存使用效率高而且又没有 bug 的代码,就得掌握其内存管理模型的种种细节. 一旦理解了这些规则,你就会发现,其实 Objective-C 的内存管理没那么复杂,而且有了 "自动引用计数"(Automatic Reference Counting, ARC)之后,就变得更为简单了.ARC 几乎把所有内存管理事宜都交由编译器来决定,开发者只需专注于业务逻辑. 本条要点:(作者总结) O

Objective-C内存管理之引用计数

初学者在学习Objective-c的时候,很容易在内存管理这一部分陷入混乱状态,很大一部分原因是没有弄清楚引用计数的原理,搞不明白对象的引用数量,这样就当然无法彻底释放对象的内存了,苹果官方文档在内存管理这一部分说的非常简单,只有三条准则: 当你使用new.alloc或copy方法创建一个对象时,该对象的保留指针为1,当不再使用该对象的时候,你应该想该对象发送一条release或autorelease消息,这样,该对象在其寿命结束时将被销毁. 当你通过其他方法获得一个对象时,假设该对象的保留计数

iOS中引用计数内存管理机制分析

在 iOS 中引用计数是内存的管理方式,尽管在 iOS5 版本号中.已经支持了自己主动引用计数管理模式.但理解它的执行方式有助于我们了解程序的执行原理.有助于 debug 程序. 操作系统的内存管理分成堆和栈. 在堆中分配的内存,都试用引用计数模式:在栈中则不是. NSString 定义的对象是保存在栈中,所以它没有引用计算.看一些书上说它的引用计算会是 fffffffff 最大整数.測试的结果显示它是- 1. 对该对象进行 retain 操作.不好改变它的 retainCount 值. Mut

OC基础15:内存管理和自动引用计数

1.什么是ARC? (1).ARC全名为Automatic Reference Counting,即是自动引用计数,会自动统计内存中对象的引用数,并在适当时候自动释放对象: (2).在工程中使用ARC非常简单:只需要像往常那样编写代码,只不过永远不用写retain. release和autorelease三个关键字: (3).在使用ARC之前,需要手动管理内存计数,这种机制称为MRC,即是手动引用计数 (Manual Referecen Counting): (4).ARC是Objective-