cocos2dx CCHttpRequest裏面的內存引用計數的故事

CCHttpRequest 自己是一個CCObject 對象, 用於lua的create函數 默認會retain request對象一次,所以須要在lua的callback函數裏面處理結束request以後,須要release對象不然會內存泄露。 函數

實際的引用計數變化的過程以下: this

new  引用計數 = 1 lua

autorelease 引用計數先變成2 再變成1 , 將對象加入自動釋放池子裏面以後,對象引用計數會+1, 接着會調用對象的release方法,對象引用計數又減去1 url

retain 引用計數變成 2 spa

start 開始http請求,對象加入schedule 的列表裏面 引用計數+1 引用計數變成3 code

update 過程當中,到下一個update循環的時候,對象的引用計數會減去1,由於自動釋放池子release了這個對象,這時候引用計數變成2 對象

http請求處理結束,update函數裏面檢測結束,取消schedule 更新,可是由於當前在函數體內,因此不會當即release掉request對象,而是等待本次回合結束的時候再release對象 內存

http請求結束,在callback函數裏面release 掉對象,引用計數-1  變成 1 get

在本次更新回合結束,schedule模塊,將標記刪除的對象的引用計數-1, 引用計數 = 0 對象被刪除掉。 string



#include "network/CCHttpRequest.h"
#include "network/CCHttpRequest_impl.h"
#include "cocos2d.h"

#include "CCLuaEngine.h"

using namespace cocos2d;

NS_CC_EXT_BEGIN

CCHttpRequest* CCHttpRequest::createWithUrl(CCHttpRequestDelegate* delegate,
                                            const char* url,
                                            CCHttpRequestMethod method,
                                            bool isAutoReleaseOnFinish)
{
    CCHttpRequest* request = new CCHttpRequest(delegate, url, method, isAutoReleaseOnFinish);
    request->initHttpRequest();
    request->autorelease();
    if (isAutoReleaseOnFinish)
    {
        request->retain();
    }
    return request;
}

CCHttpRequest* CCHttpRequest::createWithUrlLua(int nHandler, const char* url, bool isGet)
{
    CCHttpRequest* request = new CCHttpRequest(NULL, url, isGet?CCHttpRequestMethodGET:CCHttpRequestMethodPOST, true);
    request->m_luaHandler = nHandler;
    request->initHttpRequest();
    request->autorelease();
    request->retain();
    CCLog("request count is? %d", request->retainCount());
    return request;
}

bool CCHttpRequest::initHttpRequest(void)
{
    m_request = new CCHttpRequest_impl(m_url.c_str(), m_method);
    return true;
}

CCHttpRequest::~CCHttpRequest(void)
{
    delete (CCHttpRequest_impl*)m_request;
}

void CCHttpRequest::addRequestHeader(const char* key, const char* value)
{
    if (key && value)
    {
        ((CCHttpRequest_impl*)m_request)->addRequestHeader(key, value);
    }
}

void CCHttpRequest::addPostValue(const char* key, const char* value)
{
    if (key && value)
    {
        ((CCHttpRequest_impl*)m_request)->addPostValue(key, value);
    }
}

void CCHttpRequest::setPostData(const char* data)
{
    if (data)
    {
        ((CCHttpRequest_impl*)m_request)->setPostData(data);
    }
}

void CCHttpRequest::setTimeout(float timeout)
{
    ((CCHttpRequest_impl*)m_request)->setTimeout(timeout);
}

bool CCHttpRequest::getIsInProgress(void)
{
    return ((CCHttpRequest_impl*)m_request)->getIsInProgress();
}

void CCHttpRequest::start(bool isCached)
{
    CCDirector::sharedDirector()->getScheduler()->unscheduleUpdateForTarget(this);
    if (((CCHttpRequest_impl*)m_request)->start())
    {
        CCDirector::sharedDirector()->getScheduler()->scheduleUpdateForTarget(this, 0, false);
    }
}

void CCHttpRequest::cancel(void)
{
    CCDirector::sharedDirector()->getScheduler()->unscheduleUpdateForTarget(this);
    ((CCHttpRequest_impl*)m_request)->cancel();
}

void CCHttpRequest::clearDelegatesAndCancel(void)
{
    m_delegate = NULL;
    cancel();
}

int CCHttpRequest::getResponseStatusCode(void) {
    return ((CCHttpRequest_impl*)m_request)->getResponseStatusCode();
}

const char* CCHttpRequest::getResponseString(void)
{
    return ((CCHttpRequest_impl*)m_request)->getResposeString().c_str();
}

const void* CCHttpRequest::getResponseData(int* dataLength)
{
    return ((CCHttpRequest_impl*)m_request)->getResponseData();
}

int CCHttpRequest::getResponseDataLength()
{
    return ((CCHttpRequest_impl*)m_request)->getResponseDataLength();
}

CCHttpRequestError  CCHttpRequest::getErrorCode(void)
{
    return ((CCHttpRequest_impl*)m_request)->getErrorCode();
}

const char* CCHttpRequest::getErrorMessage(void)
{
    return ((CCHttpRequest_impl*)m_request)->getErrorMessage();
}

void CCHttpRequest::update(float dt)
{
    CCLog("update Request state %d", retainCount());
    CCHttpRequest_impl* request = (CCHttpRequest_impl*)m_request;
    if (!request || !request->getIsInProgress())
    {
        CCDirector::sharedDirector()->getScheduler()->unscheduleUpdateForTarget(this);
    }
    
    if (request->getIsCompleted())
    {
        if (m_delegate) m_delegate->requestFinished(this);
        
        if (m_luaHandler)
        {
			bool isSuc = (request->getErrorCode()==CCHttpRequestErrorNone);
			CCLuaEngine* engine = CCLuaEngine::defaultEngine();

			engine->getLuaStack()->clean();
			engine->getLuaStack()->pushBoolean(isSuc);
			engine->getLuaStack()->executeFunctionByHandler(m_luaHandler, 1);
            CCLog("afterHandler retainCount %d", retainCount());
			/*
            cocos2d::CCLuaValueDict dict;
            dict["name"] = cocos2d::CCLuaValue::stringValue("completed");
            dict["request"] = cocos2d::CCLuaValue::ccobjectValue(this, "CCHttpRequest");
            cocos2d::CCLuaEngine* engine = cocos2d::CCLuaEngine::defaultEngine();
            engine->cleanStack();
            engine->pushCCLuaValueDict(dict);
            engine->executeFunctionByHandler(m_luaHandler, 1);
			*/
        }
        
    }
    else if (request->getIsCancelled())
    {
        if (m_delegate) m_delegate->requestFailed(this);
        
        if (m_luaHandler)
        {
			CCLuaEngine* engine = CCLuaEngine::defaultEngine();

			engine->getLuaStack()->clean();
			engine->getLuaStack()->pushBoolean(false);
			engine->getLuaStack()->executeFunctionByHandler(m_luaHandler, 1);
			/*
            cocos2d::CCLuaValueDict dict;
            dict["name"] = cocos2d::CCLuaValue::stringValue("failed");
            dict["request"] = cocos2d::CCLuaValue::ccobjectValue(this, "CCHttpRequest");
            cocos2d::CCLuaEngine* engine = cocos2d::CCLuaEngine::defaultEngine();
            engine->cleanStack();
            engine->pushCCLuaValueDict(dict);
            engine->executeFunctionByHandler(m_luaHandler, 1);
			*/
        }
    }
}

NS_CC_EXT_END
相關文章
相關標籤/搜索