cocos2dx HttpRequest引用计数理解
来源:互联网 发布:李逵打鱼版本源码 编辑:程序博客网 时间:2024/06/15 13:02
HttpRequest* request = new (std::nothrow) HttpRequest(); request->setUrl("http://httpbin.org/post"); request->setRequestType(HttpRequest::Type::POST); std::vector<std::string> headers; headers.push_back("Content-Type: application/json; charset=utf-8"); request->setHeaders(headers); request->setResponseCallback(CC_CALLBACK_2(HttpClientTest::onHttpRequestCompleted, this)); // write the post data const char* postData = "visitor=cocos2d&TestSuite=Extensions Test/NetworkTest"; request->setRequestData(postData, strlen(postData)); if (isImmediate) { request->setTag("POST immediate test2"); HttpClient::getInstance()->sendImmediate(request); }else { request->setTag("POST test2"); HttpClient::getInstance()->send(request); } request->release();
new出来是1
send后是2,其次还有_requestQueue是一个大Vector pushBack加1 是3
void HttpClient::send(HttpRequest* request){ if (false == lazyInitThreadSemphore()) { return; } if (!request) { return; } request->retain();_requestQueueMutex.lock();_requestQueue.pushBack(request);_requestQueueMutex.unlock();// Notify thread start to work_sleepCondition.notify_one();}
网络线程处理一个个请求,在网络线程中,取出一个后,request = _requestQueue.at(0); 移除一个,再次变为2
void HttpClient::networkThread(){ increaseThreadCount(); while (true) { HttpRequest *request; // step 1: send http request if the requestQueue isn't empty { std::lock_guard<std::mutex> lock(_requestQueueMutex); while (_requestQueue.empty()){ _sleepCondition.wait(_requestQueueMutex); } request = _requestQueue.at(0); _requestQueue.erase(0); } if (request == _requestSentinel) { break; } // step 2: libcurl sync access // Create a HttpResponse object, the default setting is http access failed HttpResponse *response = new (std::nothrow) HttpResponse(request); processResponse(response, _responseMessage); // add response packet into queue _responseQueueMutex.lock(); _responseQueue.pushBack(response); _responseQueueMutex.unlock(); _schedulerMutex.lock();if (nullptr != _scheduler){_scheduler->performFunctionInCocosThread(CC_CALLBACK_0(HttpClient::dispatchResponseCallbacks, this));}_schedulerMutex.unlock(); } // cleanup: if worker thread received quit signal, clean up un-completed request queue _requestQueueMutex.lock(); _requestQueue.clear(); _requestQueueMutex.unlock(); _responseQueueMutex.lock();_responseQueue.clear();_responseQueueMutex.unlock();decreaseThreadCountAndMayDeleteThis(); }
内部调用curl库处理应该返回给客户端的响应
// Process Responsevoid HttpClient::processResponse(HttpResponse* response, char* responseMessage){auto request = response->getHttpRequest();long responseCode = -1;int retValue = 0;// Process the request -> get response packetswitch (request->getRequestType()){case HttpRequest::Type::GET: // HTTP GETretValue = processGetTask(this, request,writeData,response->getResponseData(),&responseCode,writeHeaderData,response->getResponseHeader(),responseMessage);break;case HttpRequest::Type::POST: // HTTP POSTretValue = processPostTask(this, request,writeData,response->getResponseData(),&responseCode,writeHeaderData,response->getResponseHeader(),responseMessage);break;case HttpRequest::Type::PUT:retValue = processPutTask(this, request,writeData,response->getResponseData(),&responseCode,writeHeaderData,response->getResponseHeader(),responseMessage);break;case HttpRequest::Type::DELETE:retValue = processDeleteTask(this, request,writeData,response->getResponseData(),&responseCode,writeHeaderData,response->getResponseHeader(),responseMessage);break;default:CCASSERT(true, "CCHttpClient: unknown request type, only GET and POSt are supported");break;}// write data to HttpResponseresponse->setResponseCode(responseCode);if (retValue != 0){response->setSucceed(false);response->setErrorBuffer(responseMessage);}else{response->setSucceed(true);}}
//Process Get Requeststatic int processGetTask(HttpClient* client, HttpRequest* request, write_callback callback, void* stream, long* responseCode, write_callback headerCallback, void* headerStream, char* errorBuffer){ CURLRaii curl;bool ok = curl.init(client, request, callback, stream, headerCallback, headerStream, errorBuffer) && curl.setOption(CURLOPT_FOLLOWLOCATION, true) && curl.perform(responseCode); return ok ? 0 : 1;}
获取结果后,在这里调用注册的回调函数。当分发完消息后,再次release,引用基数减1,变为1
void HttpClient::dispatchResponseCallbacks(){ // log("CCHttpClient::dispatchResponseCallbacks is running"); //occurs when cocos thread fires but the network thread has already quited HttpResponse* response = nullptr; _responseQueueMutex.lock(); if (!_responseQueue.empty()) { response = _responseQueue.at(0); _responseQueue.erase(0); } _responseQueueMutex.unlock(); if (response) { HttpRequest *request = response->getHttpRequest(); const ccHttpRequestCallback& callback = request->getCallback(); Ref* pTarget = request->getTarget(); SEL_HttpResponse pSelector = request->getSelector(); if (callback != nullptr) { callback(this, response); } else if (pTarget && pSelector) { (pTarget->*pSelector)(this, response); } response->release(); // do not release in other thread request->release(); }}
注意最后的,网络线程退出while循环时,调用clear函数。
void clear()
{
for( auto it =std::begin(_data); it !=std::end(_data); ++it ) {
(*it)->release();
}
_data.clear();
}
最终里面的搜游数据引用计数因为变为0,所有内存被释放。
一个有意思的地方是:
if (request == _requestSentinel) { break; }
退出while循环的条件是这个
void HttpClient::decreaseThreadCountAndMayDeleteThis(){bool needDeleteThis = false;_threadCountMutex.lock();--_threadCount;if (0 == _threadCount){needDeleteThis = true;}_threadCountMutex.unlock();if (needDeleteThis){delete this;}}
_requestSentinel(new HttpRequest())
void HttpClient::destroyInstance(){if (nullptr == _httpClient){CCLOG("HttpClient singleton is nullptr");return;}CCLOG("HttpClient::destroyInstance begin");auto thiz = _httpClient;_httpClient = nullptr;thiz->_scheduler->unscheduleAllForTarget(thiz);thiz->_schedulerMutex.lock();thiz->_scheduler = nullptr;thiz->_schedulerMutex.unlock();thiz->_requestQueueMutex.lock();thiz->_requestQueue.pushBack(thiz->_requestSentinel);thiz->_requestQueueMutex.unlock();thiz->_sleepCondition.notify_one();thiz->decreaseThreadCountAndMayDeleteThis();CCLOG("HttpClient::destroyInstance() finished!");}
这样,当消除单利的时候,将卫梢放进去,这样当检测出来是卫梢时,就退出网络线程。
0 0
- cocos2dx HttpRequest引用计数理解
- cocos2dx引用计数
- cocos2dx之 引用计数
- cocos2dx引用计数和autorelease
- 基于cocos2dx引用计数的事件机制
- Cocos2dx内存管理之引用计数分析
- Cocos2dx中的引用计数和自动回收池
- cocos2dx CCHttpRequest里面的内存引用计数的故事
- cocos2dx 3.x 源码阅读之一 引用计数原理
- cocos2dx CCObject引用计数,内存释放分析(1)
- cocos2dx源码之 引用计数及自动释放
- Cocos2dx中的引用计数和自动回收池
- 块设备驱动-模块引用计数理解
- cocos2dx v3.x之HttpRequest改动
- 引用计数
- 引用计数
- 引用计数
- 引用计数
- angular 广播实现实时刷新视图
- Activity启动模式intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
- 使用Foxmail邮箱客户端的方法。
- Android中获取应用程序(包)的信息-----PackageManager的使用(一)
- python调试器pdb
- cocos2dx HttpRequest引用计数理解
- 进阶1_MVC到MVP
- NumberUtils、ArrayUtils和RandomUtils工具类用法
- webdynpro for abap 随笔1
- PHP获取两个时间之间的年和月份及间隔天数 PHP两个日期之间的所有日期
- linux文件夹打包命令
- ACM-ICPC---Robot Roll Call – Cambot…Servo…Gypsy…Croooow
- 智能搜索
- Unity开发中的坑