// Worker thread static void networkThread(void) { HttpRequest *request = NULL; while (true) { if (s_need_quit) { break; } // step 1: send http request if the requestQueue isn't empty request = NULL; s_requestQueueMutex.lock(); //Get request task from queue if (0 != s_requestQueue->count()) { request = dynamic_cast<HttpRequest*>(s_requestQueue->objectAtIndex(0)); s_requestQueue->removeObjectAtIndex(0); } s_requestQueueMutex.unlock(); if (NULL == request) { // Wait for http request tasks from main thread std::unique_lock<std::mutex> lk(s_SleepMutex); s_SleepCondition.wait(lk); continue; } // step 2: libcurl sync access // Create a HttpResponse object, the default setting is http access failed HttpResponse *response = new HttpResponse(request); // request's refcount = 2 here, it's retained by HttpRespose constructor request->release(); // ok, refcount = 1 now, only HttpResponse hold it. int32_t responseCode = -1; int retValue = 0; // Process the request -> get response packet switch (request->getRequestType()) { case HttpRequest::kHttpGet: // HTTP GET retValue = processGetTask(request, writeData, response->getResponseData(), &responseCode, writeHeaderData, response->getResponseHeader()); break; case HttpRequest::kHttpPost: // HTTP POST retValue = processPostTask(request, writeData, response->getResponseData(), &responseCode, writeHeaderData, response->getResponseHeader()); break; case HttpRequest::kHttpPut: retValue = processPutTask(request, writeData, response->getResponseData(), &responseCode, writeHeaderData, response->getResponseHeader()); break; case HttpRequest::kHttpDelete: retValue = processDeleteTask(request, writeData, response->getResponseData(), &responseCode, writeHeaderData, response->getResponseHeader()); break; default: CCASSERT(true, "CCHttpClient: unkown request type, only GET and POSt are supported"); break; } // write data to HttpResponse response->setResponseCode(responseCode); if (retValue != 0) { response->setSucceed(false); response->setErrorBuffer(s_errorBuffer); } else { response->setSucceed(true); } // add response packet into queue s_responseQueueMutex.lock(); s_responseQueue->addObject(response); s_responseQueueMutex.unlock(); // resume dispatcher selector Director::getInstance()->getScheduler()->resumeTarget(HttpClient::getInstance()); } // cleanup: if worker thread received quit signal, clean up un-completed request queue s_requestQueueMutex.lock(); s_requestQueue->removeAllObjects(); s_requestQueueMutex.unlock(); s_asyncRequestCount -= s_requestQueue->count(); if (s_requestQueue != NULL) { s_requestQueue->release(); s_requestQueue = NULL; s_responseQueue->release(); s_responseQueue = NULL; } }
// Worker thread void HttpClient::networkThread() { HttpRequest *request = nullptr; auto scheduler = Director::getInstance()->getScheduler(); while (true) { if (s_need_quit) { break; } // step 1: send http request if the requestQueue isn't empty request = nullptr; s_requestQueueMutex.lock(); //Get request task from queue if (!s_requestQueue->empty()) { request = s_requestQueue->at(0); s_requestQueue->erase(0); } s_requestQueueMutex.unlock(); if (nullptr == request) { // Wait for http request tasks from main thread std::unique_lock<std::mutex> lk(s_SleepMutex); s_SleepCondition.wait(lk); continue; } // step 2: libcurl sync access // Create a HttpResponse object, the default setting is http access failed HttpResponse *response = new HttpResponse(request); // request's refcount = 2 here, it's retained by HttpRespose constructor request->release(); // ok, refcount = 1 now, only HttpResponse hold it. long responseCode = -1; int retValue = 0; // Process the request -> get response packet switch (request->getRequestType()) { case HttpRequest::Type::GET: // HTTP GET retValue = processGetTask(request, writeData, response->getResponseData(), &responseCode, writeHeaderData, response->getResponseHeader()); break; case HttpRequest::Type::POST: // HTTP POST retValue = processPostTask(request, writeData, response->getResponseData(), &responseCode, writeHeaderData, response->getResponseHeader()); break; case HttpRequest::Type::PUT: retValue = processPutTask(request, writeData, response->getResponseData(), &responseCode, writeHeaderData, response->getResponseHeader()); break; case HttpRequest::Type::DELETE: retValue = processDeleteTask(request, writeData, response->getResponseData(), &responseCode, writeHeaderData, response->getResponseHeader()); break; default: CCASSERT(true, "CCHttpClient: unkown request type, only GET and POSt are supported"); break; } // write data to HttpResponse response->setResponseCode(responseCode); if (retValue != 0) { response->setSucceed(false); response->setErrorBuffer(s_errorBuffer); } else { response->setSucceed(true); } // add response packet into queue s_responseQueueMutex.lock(); s_responseQueue->pushBack(response); s_responseQueueMutex.unlock(); if (nullptr != s_pHttpClient) { scheduler->performFunctionInCocosThread(CC_CALLBACK_0(HttpClient::dispatchResponseCallbacks, this)); } } // cleanup: if worker thread received quit signal, clean up un-completed request queue s_requestQueueMutex.lock(); s_requestQueue->clear(); s_requestQueueMutex.unlock(); if (s_requestQueue != nullptr) { delete s_requestQueue; s_requestQueue = nullptr; delete s_responseQueue; s_responseQueue = nullptr; } }