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_;

 

 

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

 

 

 

 

 

 

 

 

 

 

 

posted @ 2016-01-31 13:15  luweimy  阅读(450)  评论(0编辑  收藏  举报