// Worker thread static void* networkThread(void *data) { CCHttpRequest *request = NULL; while (true) { // Wait for http request tasks from main thread int semWaitRet = sem_wait(s_pSem); if (semWaitRet < 0) { CCLog("HttpRequest async thread semaphore error: %s\n", strerror(errno)); break; } if (need_quit) { break; } // step 1: send http request if the requestQueue isn't empty request = NULL; pthread_mutex_lock(&s_requestQueueMutex); //Get request task from queue if (0 != s_requestQueue->count()) { request = dynamic_cast<CCHttpRequest*>(s_requestQueue->objectAtIndex(0)); s_requestQueue->removeObjectAtIndex(0); // request's refcount = 1 here } pthread_mutex_unlock(&s_requestQueueMutex); if (NULL == request) { continue; } // step 2: libcurl sync access // Create a HttpResponse object, the default setting is http access failed CCHttpResponse *response = new CCHttpResponse(request); // request's refcount = 2 here, it's retained by HttpRespose constructor request->release(); // ok, refcount = 1 now, only HttpResponse hold it. int responseCode = -1; int retValue = 0; // Process the request -> get response packet switch (request->getRequestType()) { case CCHttpRequest::kHttpGet: // HTTP GET retValue = processGetTask(request, writeData, response->getResponseData(), &responseCode); break; case CCHttpRequest::kHttpPost: // HTTP POST retValue = processPostTask(request, writeData, response->getResponseData(), &responseCode); 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 pthread_mutex_lock(&s_responseQueueMutex); s_responseQueue->addObject(response); pthread_mutex_unlock(&s_responseQueueMutex); // resume dispatcher selector CCDirector::sharedDirector()->getScheduler()->resumeTarget(CCHttpClient::getInstance()); } // cleanup: if worker thread received quit signal, clean up un-completed request queue pthread_mutex_lock(&s_requestQueueMutex); s_requestQueue->removeAllObjects(); pthread_mutex_unlock(&s_requestQueueMutex); s_asyncRequestCount -= s_requestQueue->count(); if (s_pSem != NULL) { #if CC_ASYNC_HTTPREQUEST_USE_NAMED_SEMAPHORE sem_unlink(CC_ASYNC_HTTPREQUEST_SEMAPHORE); sem_close(s_pSem); #else sem_destroy(s_pSem); #endif s_pSem = NULL; pthread_mutex_destroy(&s_requestQueueMutex); pthread_mutex_destroy(&s_responseQueueMutex); s_requestQueue->release(); s_responseQueue->release(); } pthread_exit(NULL); return 0; }
// Worker thread static void* networkThread(void *data) { CCHttpRequest *request = NULL; while (true) { if (need_quit) { break; } // step 1: send http request if the requestQueue isn't empty request = NULL; pthread_mutex_lock(&s_requestQueueMutex); //Get request task from queue if (0 != s_requestQueue->count()) { request = dynamic_cast<CCHttpRequest*>(s_requestQueue->objectAtIndex(0)); s_requestQueue->removeObjectAtIndex(0); // request's refcount = 1 here } pthread_mutex_unlock(&s_requestQueueMutex); if (NULL == request) { // Wait for http request tasks from main thread pthread_cond_wait(&s_SleepCondition, &s_SleepMutex); continue; } // step 2: libcurl sync access // Create a HttpResponse object, the default setting is http access failed CCHttpResponse *response = new CCHttpResponse(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 CCHttpRequest::kHttpGet: // HTTP GET retValue = processGetTask(request, writeData, response->getResponseData(), &responseCode, writeHeaderData, response->getResponseHeader()); break; case CCHttpRequest::kHttpPost: // HTTP POST retValue = processPostTask(request, writeData, response->getResponseData(), &responseCode, writeHeaderData, response->getResponseHeader()); break; case CCHttpRequest::kHttpPut: retValue = processPutTask(request, writeData, response->getResponseData(), &responseCode, writeHeaderData, response->getResponseHeader()); break; case CCHttpRequest::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 pthread_mutex_lock(&s_responseQueueMutex); s_responseQueue->addObject(response); pthread_mutex_unlock(&s_responseQueueMutex); // resume dispatcher selector CAScheduler::getScheduler()->resumeTarget(CCHttpClient::getInstance()); } // cleanup: if worker thread received quit signal, clean up un-completed request queue pthread_mutex_lock(&s_requestQueueMutex); s_requestQueue->removeAllObjects(); pthread_mutex_unlock(&s_requestQueueMutex); s_asyncRequestCount -= s_requestQueue->count(); if (s_requestQueue != NULL) { pthread_mutex_destroy(&s_requestQueueMutex); pthread_mutex_destroy(&s_responseQueueMutex); pthread_mutex_destroy(&s_SleepMutex); pthread_cond_destroy(&s_SleepCondition); s_requestQueue->release(); s_requestQueue = NULL; s_responseQueue->release(); s_responseQueue = NULL; } pthread_exit(NULL); return 0; }
// Worker thread static KDvoid* networkThread ( KDvoid* pData ) { CCHttpRequest* pRequest = KD_NULL; while ( 1 ) { if ( l_bNeedQuit ) { break; } // step 1: send http request if the requestQueue isn't empty pRequest = KD_NULL; kdThreadMutexLock ( l_pRequestQueueMutex ); // Get request task from queue if ( 0 != l_pRequestQueue->count ( ) ) { pRequest = dynamic_cast<CCHttpRequest*> ( l_pRequestQueue->objectAtIndex ( 0 ) ); l_pRequestQueue->removeObjectAtIndex ( 0 ); // request's refcount = 1 here } kdThreadMutexUnlock ( l_pRequestQueueMutex ); if ( KD_NULL == pRequest ) { // Wait for http request tasks from main thread kdThreadCondWait ( l_pSleepCondition, l_pSleepMutex ); continue; } // step 2: libcurl sync access // Create a HttpResponse object, the default setting is http access failed CCHttpResponse* pResponse = new CCHttpResponse ( pRequest ); // request's refcount = 2 here, it's retained by HttpRespose constructor pRequest->release ( ); // ok, refcount = 1 now, only HttpResponse hold it. KDint nResponseCode = -1; KDint nRetValue = 0; // Process the request -> get response packet switch ( pRequest->getRequestType ( ) ) { case CCHttpRequest::kCCHttpGet : // HTTP GET nRetValue = processGetTask ( pRequest, writeData, pResponse->getResponseData ( ), &nResponseCode ); break; case CCHttpRequest::kCCHttpPost : // HTTP POST nRetValue = processPostTask ( pRequest, writeData, pResponse->getResponseData ( ), &nResponseCode ); break; default : CCAssert ( KD_TRUE, "CCHttpClient: unkown request type, only GET and POSt are supported" ); break; } // write data to HttpResponse pResponse->setResponseCode ( nResponseCode ); if ( nRetValue != 0 ) { pResponse->setSucceed ( KD_FALSE ); pResponse->setErrorBuffer ( l_szErrorBuffer ); } else { pResponse->setSucceed ( KD_TRUE ); } // add response packet into queue kdThreadMutexLock ( l_pResponseQueueMutex ); l_pResponseQueue->addObject ( pResponse ); kdThreadMutexUnlock ( l_pResponseQueueMutex ); // resume dispatcher selector CCDirector::sharedDirector ( )->getScheduler ( )->resumeTarget ( CCHttpClient::getInstance ( ) ); } // cleanup: if worker thread received quit signal, clean up un-completed request queue kdThreadMutexLock ( l_pRequestQueueMutex ); l_pRequestQueue->removeAllObjects ( ); kdThreadMutexUnlock ( l_pRequestQueueMutex ); l_uAsyncRequestCount -= l_pRequestQueue->count ( ); if ( l_pRequestQueue != KD_NULL ) { kdThreadMutexFree ( l_pRequestQueueMutex ); kdThreadMutexFree ( l_pResponseQueueMutex ); kdThreadMutexFree ( l_pSleepMutex ); kdThreadCondFree ( l_pSleepCondition ); l_pRequestQueue->release ( ); l_pRequestQueue = KD_NULL; l_pResponseQueue->release ( ); l_pResponseQueue = KD_NULL; } kdThreadExit ( KD_NULL ); return 0; }