Coco2d-x 内存管理笔记

Coco2d-x内存管理包括3个类,Ref(引用计数类)、AutoreleasePool(自动释放池)、PoolManager(自动释放池管理类)。

  • Ref:Ref是所有需要内存管理的类的基类,用于管理对象的引用计数。Ref中包含两种内存管理函数:手动管理函数retain()(引用计数加1)和release()(引用计数减1,当引用计数为0时,deleted this释放自身),自动管理类函数autorelease()(将对象自身交与PoolManager的栈顶AutoreleasePool管理,PoolManager会每帧都会release()一次所有autorelease对象)。
  • AutoreleasePool:AutoreleasePool是用于管理autorelease对象的管理类。本身是一个Vector,最少可以装150个对象(初始化reverse()了150个elements)。Ref中autorelease()调用的是PoolManager的栈顶的AutoreleasePool对象中的addObject()函数,将对象自身加入AutoreleasePool。PoolManager中每帧调用的是栈顶的AutoreleasePool对象的clear()函数release()一次全部autorelease对象(只是引用计数减1,不一定会delete)。
  • PoolManager:PoolManager是用于管理AutoreleasePool的一个管理类,它是一个单实例类,初始化可以包含10个池,其自身也是一个Vector,当作栈使用,一般来说PoolManager会用到的函数就只有getCurrentPool(),返回的是栈顶即Vector最后一个AutoreleasePool,因为一般来说只用一个AutoreleasePool就可以了,所以push(AutoreleasePool *pool)和pop()基本不会使用。


操作流程(以Scene为例子)

1.假设要新建一个场景:auto scene = Scene::create()

//--------------------------------------------------------------------
//
// Scene::create()
//
//--------------------------------------------------------------------
Scene* Scene::create()
{
    Scene *ret = new (std::nothrow) Scene();
    if (ret && ret->init())
    {
        ret->autorelease();
        return ret;
    }
    else
    {
        CC_SAFE_DELETE(ret);
        return nullptr;
    }
}

在new一个Scene之后,调用该Scene的autorelease()函数,将该对象加入到自动释放池中

2.ret->autorelease();

//--------------------------------------------------------------------
//
// Ref:::autorelease()
//
//--------------------------------------------------------------------
Ref* Ref::autorelease()
{
    PoolManager::getInstance()->getCurrentPool()->addObject(this);
    return this;
}

该Scene的autorelease()函数中,第一次调用PoolManager的getInstance(),需要进行PoolManager的初始化

3.PoolManager初始化:PoolManager::getInstance()

//--------------------------------------------------------------------
//
// PoolManager:::getInstance()
//
//--------------------------------------------------------------------
PoolManager* PoolManager::getInstance()
{
    if (s_singleInstance == nullptr)
    {
        s_singleInstance = new (std::nothrow) PoolManager();
        // Add the first auto release pool
        new AutoreleasePool("cocos2d autorelease pool");
    }
    return s_singleInstance;
}

初始化包括:new一个PoolManager和new一个名为cocos2d autorelease pool的默认AutoreleasePool。

//--------------------------------------------------------------------
//
// PoolManager:::PoolManager()
//
//--------------------------------------------------------------------
PoolManager::PoolManager()
{
    _releasePoolStack.reserve(10);
}

new一个PoolManager会申请一个至少可以保存10个AutoreleasePool的数组并当作栈来使用,其实一般只需要用到1个AutoreleasePool

//--------------------------------------------------------------------
//
// AutoreleasePool:::AutoreleasePool()
//
//--------------------------------------------------------------------
AutoreleasePool::AutoreleasePool(const std::string &name)
: _name(name)
{
    _managedObjectArray.reserve(150);
    PoolManager::getInstance()->push(this);
}
new一个AutoreleasePool会申请一个至少可以保存150个Ref类对象的数组,并把自身push到PoolManager的自动释放池栈的栈顶

//--------------------------------------------------------------------
//
// PoolManager:::push()
//
//--------------------------------------------------------------------
void PoolManager::push(AutoreleasePool *pool)
{
    _releasePoolStack.push_back(pool);
}

一般来说,PoolManager只会push一个默认的AutoreleasePool,不再需要其他的AutoreleasePool,所以PoolManager的自动释放池栈中一般只有一个elements

4.初始化PoolManager之后,获取栈顶的AutoreleasePool:PoolManager::getInstance()->getCurrentPool()

//--------------------------------------------------------------------
//
// AutoreleasePool:::getCurrentPool()
//
//--------------------------------------------------------------------
AutoreleasePool* PoolManager::getCurrentPool() const
{
    return _releasePoolStack.back();
}
因为Vector当作栈使用,所以_releasePoolStack的尾部就是栈顶,返回尾部_releasePoolStack.back()

5.获取当前AutoreleasePool后,把该Scene加入AutoreleasePool: PoolManager::getInstance()->getCurrentPool()->addObject(this);

//--------------------------------------------------------------------
//
// AutoreleasePool:::addObject()
//
//--------------------------------------------------------------------
void AutoreleasePool::addObject(Ref* object)
{
    _managedObjectArray.push_back(object);
}
把该Scene加入_managedObjectArray尾部

6.autorelease对象会在mainLoop()中调用PoolManager::getInstance()->getCurrentPool()->clear()进行内存清理

//--------------------------------------------------------------------
//
// DisplayLinkDirector:::mainLoop()
//
//--------------------------------------------------------------------
void DisplayLinkDirector::mainLoop()
{
    if (_purgeDirectorInNextLoop)
    {
        _purgeDirectorInNextLoop = false;
        purgeDirector();
    }
    else if (_restartDirectorInNextLoop)
    {
        _restartDirectorInNextLoop = false;
        restartDirector();
    }
    else if (! _invalid)
    {
        drawScene();
     
        // release the objects
        PoolManager::getInstance()->getCurrentPool()->clear();
    }
}
在draw所有的scene之后(一帧所有的rendering后),进行内存清理

//--------------------------------------------------------------------
//
// AutoreleasePool:::clear()
//
//--------------------------------------------------------------------
void AutoreleasePool::clear()
{
    std::vector<Ref*> releasings;
    releasings.swap(_managedObjectArray);
    for (const auto &obj : releasings)
    {
        obj->release();
    }
}

这里用到swap()函数releasings.swap(_managedObjectArray),大概就像交换两个vector的保存数据的内存首地址,然后AutoreleasePool中的_managedObjectArray的保存数据的内存首地址指向releasings的保存数据的内存首地址,两个vector中的内容交换后_managedObjectArray空了,releasings需要手动清空,即遍历releasings调用elements的release()进行内存清理。

7.swap()的使用方法

vector<int> vec(100000, 0);
cout << "vec[0] = " <<vec[0] << "        ";
cout << "vec[100000 - 1] = " << vec[100000 - 1] << endl;
for (int i = 0; i < 100000 - 2; ++i) vec.pop_back();
cout << "After pop_back() (100000 - 2) times , vec.capacity() = " << vec.capacity() << endl;
vector<int>(vec).swap(vec);//vector<int>(vec)是用vec作为形参新建一个vector,此时vec只剩两个elements了,所以新建的vector容量为2
cout << "After swap() with vector<int>(vec) (a new vector only have 2 elements), vec.capacity() = " << vec.capacity() << endl;



三个类的所有函数

//--------------------------------------------------------------------
//
// Ref
//
//--------------------------------------------------------------------

Ref::Ref()
: _referenceCount(1) // when the Ref is created, the reference count of it is 1
}

Ref::~Ref()
{
 }

void Ref::retain()
{
    CCASSERT(_referenceCount > 0, "reference count should be greater than 0");
    ++_referenceCount;
}

void Ref::release()
{
    CCASSERT(_referenceCount > 0, "reference count should be greater than 0");
    --_referenceCount;

    if (_referenceCount == 0)
    {
        delete this;
    }
}

Ref* Ref::autorelease()
{
    PoolManager::getInstance()->getCurrentPool()->addObject(this);
    return this;
}

unsigned int Ref::getReferenceCount() const
{
    return _referenceCount;
}

//--------------------------------------------------------------------
//
// AutoreleasePool
//
//--------------------------------------------------------------------
AutoreleasePool::AutoreleasePool()
: _name("")
{
    _managedObjectArray.reserve(150);
    PoolManager::getInstance()->push(this);
}
AutoreleasePool::AutoreleasePool(const std::string &name)
: _name(name)
{
    _managedObjectArray.reserve(150);
    PoolManager::getInstance()->push(this);
}
AutoreleasePool::~AutoreleasePool()
{
    CCLOGINFO("deallocing AutoreleasePool: %p", this);
    clear();
    PoolManager::getInstance()->pop();
}
void AutoreleasePool::addObject(Ref* object)
{
    _managedObjectArray.push_back(object);
}
void AutoreleasePool::clear()
{
    std::vector<Ref*> releasings;
    releasings.swap(_managedObjectArray);
    for (const auto &obj : releasings)
    {
        obj->release();
    }
}
bool AutoreleasePool::contains(Ref* object) const
{
    for (const auto& obj : _managedObjectArray)
    {
        if (obj == object)
            return true;
    }
    return false;
}
//--------------------------------------------------------------------
//
// PoolManager
//
//--------------------------------------------------------------------
PoolManager* PoolManager::s_singleInstance = nullptr;
PoolManager* PoolManager::getInstance()
{
    if (s_singleInstance == nullptr)
    {
        s_singleInstance = new (std::nothrow) PoolManager();
        // Add the first auto release pool
        new AutoreleasePool("cocos2d autorelease pool");
    }
    return s_singleInstance;
}
void PoolManager::destroyInstance()
{
    delete s_singleInstance;
    s_singleInstance = nullptr;
}
PoolManager::PoolManager()
{
    _releasePoolStack.reserve(10);
}
PoolManager::~PoolManager()
{
    CCLOGINFO("deallocing PoolManager: %p", this);
    while (!_releasePoolStack.empty())
    {
        AutoreleasePool* pool = _releasePoolStack.back();
        delete pool;
    }
}
AutoreleasePool* PoolManager::getCurrentPool() const
{
    return _releasePoolStack.back();
}
bool PoolManager::isObjectInPools(Ref* obj) const
{
    for (const auto& pool : _releasePoolStack)
    {
        if (pool->contains(obj))
            return true;
    }
    return false;
}
void PoolManager::push(AutoreleasePool *pool)
{
    _releasePoolStack.push_back(pool);
}
void PoolManager::pop()
{
    CC_ASSERT(!_releasePoolStack.empty());
    _releasePoolStack.pop_back();
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值