zoukankan      html  css  js  c++  java
  • C++模拟OC的多重自动释放池

    使用过OC的都知道,OC的引用计数机制用起来还比较方便。于是就仿照OC的形式搞了个C++引用计数。

    支持多重自动释放池,每次autorelease都会放到栈顶的自动释放池中。

    自动释放池也可以像变量一样有生命周期,在退出block时自动销毁池,并且对池中每个对象调用release.

    使用大概如下:

    int main(int argc, char * argv[])
    {
        USING_NAMESPACE_BASE
        using namespace std;
    
        Data *d = new Data(1);
        d->Autorelease();
    
        {
            autorelease_newpool
            Data *d = new Data(3);
            d->Autorelease();
            {
                autorelease_newpool
                Data *d = new Data(4);
                d->Autorelease();
            }
        }
    
        Data *d1 = new Data(2);
        d1->Autorelease();
    
        return 0;
    }

    Github:【点击】

    概述:

     *  - AutoreleasePool 自动释放池类

     *  - AutoreleasePoolLifecycleManager 池生命周期类,用于程序块内的池入栈和出栈控制

     *  - AutoreleasePoolMarager 池管理器,内部使用栈式结构管理池

     *  - RefObject 引用计数基类,提供引用计数的支持

    关系梳理:

     - 继承自RefObject的类具有,引用计数功能。当调用RefObject的autorelease时,其会通过AutoreleasePoolMarager获得栈顶的AutoreleasePool对象,然后将自己放入pool中。

     - AutoreleasePoolMarager是单例,其内部使用栈式结构保存了一个或多个AutoreleasePool对象,供其他对象调用入栈新pool或者出栈销毁pool

     - AutoreleasePool管理池中的对象,在pool销毁时会将所有池中RefObject对象release一遍

     - AutoreleasePoolLifecycleManager作用就是在构造函数中入栈新pool,在析构函数中出栈pool

    RefObject

    class RefObject{
    public:
        /*
         * 引用计数加一
         * 注意:
         *  - 只有对堆对象才能生效,栈对象不要使用
         */
        void Retain() { assert(m_refcount>0); ++m_refcount; }
        
        /*
         * 引用计数减一
         * 注意:
         *  - 只有对堆对象才能生效,栈对象不要使用
         */
        void Release() { if (--m_refcount<=0) delete this; }
        
        /*
         * 自动引用计数减一
         * 注意:
         *  - 只有对堆对象才能生效,栈对象不要使用
         */
        void Autorelease() { AutoreleasePoolMarager::GetInstance()->PeekTop()->AddRefObject(this); }
        
        /*
         * 获得引用计数
         * 注意:
         *  - 只有对堆对象才能生效,栈对象不要使用
         */
        int  GetRefCount() { return m_refcount; }
        
    protected:
        RefObject():m_refcount(1) { }
        virtual ~RefObject() { }
        
    private:
        int m_refcount;
    };

     AutoreleasePool

    class AutoreleasePool {
    public:
        AutoreleasePool();
        ~AutoreleasePool();
        
        /*
         * 添加对象到自动释放池中
         * 说明:
         *  - 此对象必须为RefObject的子类
         */
        void AddRefObject(RefObject *refobject);
        
        /*
         * 对池中所有对象调用一次Release方法
         * 说明:
         *  - 此方法一般不要手动调用,在析构中会自动调用
         *  - 调用顺序为,先进的先调用(类似队列结构)
         */
        void ReleaseAll();
        
    private:
        std::vector<RefObject*> m_refobjects;
    };

     AutoreleasePoolMarager

    class AutoreleasePoolMarager {
    public:
        static AutoreleasePoolMarager* GetInstance();
        static void DestroyInstance();
        
        /*
         * 创建一个新的自动释放池,并且入栈
         */
        void PushNew();
        
        /*
         * 将栈顶的自动释放池出栈,并删除
         */
        void PopTop();
        
        /*
         * 获取栈顶的自动释放池,并不会删除
         */
        AutoreleasePool* PeekTop();
        
    private:
        AutoreleasePoolMarager();
        ~AutoreleasePoolMarager();
        
    private:
        static AutoreleasePoolMarager* s_instance;
        std::stack<AutoreleasePool*>   m_poolstack;
    };

    AutoreleasePoolLifecycleManager

    这个类的作用就是利用其对象的生命周期,来入栈和出栈自动释放池

    class AutoreleasePoolLifecycleManager {
    public:
        /*
         * 构造函数中,入栈一个新的自动释放池(AutoreleasePool)
         */
        AutoreleasePoolLifecycleManager() { AutoreleasePoolMarager::GetInstance()->PushNew(); }
        
        /*
         * 析构函数中,出栈自动释放池
         */
        ~AutoreleasePoolLifecycleManager() { AutoreleasePoolMarager::GetInstance()->PopTop(); }
    };

     

    使用宏代替实例化AutoreleasePoolLifecycleManager对象

    #define autorelease_newpool 
        torch::AutoreleasePoolLifecycleManager __arplm_obj_;

     

    原理和代码都比较简单,只要把几个类得关系理清楚就明白了。

     

     

     

     

     

     

     

     

     

     

     

  • 相关阅读:
    高等软工第三次作业——设计也可以按图索骥
    高等软工第二次作业-从需求分析看软件开发的挑战
    高等软工第一次作业——期望与笃信
    【ACM-ICPC 2018 徐州赛区网络预赛】D.Easy Math 杜教筛
    【HDU 6428】Calculate 莫比乌斯反演+线性筛
    【BZOJ 4199】[Noi2015]品酒大会 后缀自动机+DP
    【BZOJ 3238】差异 后缀自动机+树形DP
    【Codeforces Round #466】E. Cashback DP+ST表
    【BZOJ 4709】柠檬 斜率优化dp+单调栈
    Hello Tornado
  • 原文地址:https://www.cnblogs.com/luweimy/p/5173028.html
Copyright © 2011-2022 走看看