// Worker thread void HttpClient::networkThreadAlone(HttpRequest* request) { // Create a HttpResponse object, the default setting is http access failed HttpResponse *response = new (std::nothrow) HttpResponse(request); char errorBuffer[CURL_ERROR_SIZE] = { 0 }; processResponse(response, errorBuffer); auto scheduler = Director::getInstance()->getScheduler(); scheduler->performFunctionInCocosThread([response, request]{ const ccHttpRequestCallback& callback = request->getCallback(); Ref* pTarget = request->getTarget(); SEL_HttpResponse pSelector = request->getSelector(); if (callback != nullptr) { callback(s_pHttpClient, response); } else if (pTarget && pSelector) { (pTarget->*pSelector)(s_pHttpClient, response); } response->release(); // do not release in other thread request->release(); }); }
void ReserveRetunrHomeController::showSPrite() { char message[100]; NativeLauncher::launchLocationController(0); reserveEquipment(message); // 別スレッドを生成して引数を渡して実行する auto t = std::thread([this] (int n) { for (int i = 0; i < 100; i++) { mtx.lock(); log("%d", n + i); mtx.unlock(); } // 処理が一通り終わったのでメインスレッドに戻してメソッドを呼ぶ auto scheduler = Director::getInstance()->getScheduler(); scheduler->performFunctionInCocosThread(CC_CALLBACK_0(ReserveRetunrHomeController::dispatchThreadCallbacks, this)); }, 1000); // スレッドの管理を手放す // スレッドの処理を待つ場合はt.join()かstd::asyncを使う t.detach(); }
void HttpDownload::onSuccess(string filefullPath){ _isStop = true; if(_isAutoUncompress) { if(uncompress()) { this->deleteFile(_filePath + _url.substr(_url.rfind('/') + 1)); //进入Cocos主线程然后分发 auto scheduler = Director::getInstance()->getScheduler(); scheduler->performFunctionInCocosThread([this,filefullPath] { //TODO:分发给LUA CURLDOWNLOG("%s Download Success",filefullPath.c_str()); if (_delegate) { _delegate->onSuccess(filefullPath); } }); } else { this->deleteFile(_filePath + _url.substr(_url.rfind('/') + 1)); this->onError(CurlDown::ErrorCode::kUncompress);//解压失败 } } else { //进入Cocos主线程然后分发 auto scheduler = Director::getInstance()->getScheduler(); scheduler->performFunctionInCocosThread([this,filefullPath] { //TODO:分发给LUA CURLDOWNLOG("%s Download Success",filefullPath.c_str()); if (_delegate) { _delegate->onSuccess(filefullPath); } }); } }
// Worker thread void HttpClient::networkThread() { auto scheduler = Director::getInstance()->getScheduler(); while (true) { HttpRequest *request; // step 1: send http request if the requestQueue isn't empty { std::lock_guard<std::mutex> lock(s_requestQueueMutex); while (s_requestQueue->empty()) { s_SleepCondition.wait(s_requestQueueMutex); } request = s_requestQueue->at(0); s_requestQueue->erase(0); } if (request == s_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, s_errorBuffer); // 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; } }
void OutgoingController::showSPrite() { char message[100]; lockAllEquipment(message); auto s = Director::getInstance()->getWinSize(); auto action = Sequence::createWithTwoActions(ProgressTo::create(2, 100), ProgressTo::create(0, 0)); /** * Our image on the left should be a radial progress indicator, clockwise */ auto left = ProgressTimer::create(Sprite::create("seaside-955948_640.png")); left->setType(ProgressTimer::Type::RADIAL); addChild(left); left->setMidpoint(Vec2(0.25f, 0.75f)); left->setPosition(100, s.height/2); left->runAction(RepeatForever::create(action->clone())); /** * Our image on the left should be a radial progress indicator, counter clockwise */ auto right = ProgressTimer::create(Sprite::create("seaside-955948_640.png")); right->setType(ProgressTimer::Type::RADIAL); right->setMidpoint(Vec2(0.75f, 0.25f)); /** * Note the reverse property (default=NO) is only added to the right image. That's how * we get a counter clockwise progress. */ addChild(right); right->setPosition(s.width-100, s.height/2); right->runAction(RepeatForever::create(action->clone())); // 別スレッドを生成して引数を渡して実行する auto t = std::thread([this] (int n) { for (int i = 0; i < 100; i++) { mtx.lock(); log("%d", n + i); mtx.unlock(); } // 処理が一通り終わったのでメインスレッドに戻してメソッドを呼ぶ auto scheduler = Director::getInstance()->getScheduler(); scheduler->performFunctionInCocosThread(CC_CALLBACK_0(OutgoingController::dispatchThreadCallbacks, this)); }, 10000); // スレッドの管理を手放す // スレッドの処理を待つ場合はt.join()かstd::asyncを使う t.detach(); }
void HttpDownload::onStop(string filefullPath) { _isStop = true; //进入Cocos主线程然后分发 auto scheduler = Director::getInstance()->getScheduler(); scheduler->performFunctionInCocosThread([this,filefullPath] { //TODO:分发给LUA CURLDOWNLOG("%s Download Stop",filefullPath.c_str()); if (_delegate) { _delegate->onStop(filefullPath); } }); }
void HttpDownload::onError(CurlDown::ErrorCode errorCode){ _isStop = true; //进入Cocos主线程然后分发 auto scheduler = Director::getInstance()->getScheduler(); scheduler->performFunctionInCocosThread([this,errorCode] { //TODO:分发给LUA CURLDOWNLOG("Download Error ErrorCode:%d",(int)errorCode);//CurlDown::ErrorCode::kUncompress是停止 if (_delegate) { _delegate->onError(errorCode); } }); }
/** * Callback Methods */ void TestGeoService::onGeoRequestCompleted( void *response) { App42GeoResponse *geoResponse = (App42GeoResponse*)response; printf("\ncode=%d...=%d",geoResponse->getCode(),geoResponse->isSuccess); printf("\nResponse Body=%s",geoResponse->getBody().c_str()); string code = StringUtils::format("Code = %d",geoResponse->getCode()); responseArray.push_back(code); if (geoResponse->isSuccess) { printf("\nTotalRecords=%d",geoResponse->getTotalRecords()); for(std::vector<App42Geo>::iterator it = geoResponse->geoList.begin(); it != geoResponse->geoList.end(); ++it) { printf("\n StorageName=%s",it->storageName.c_str()); printf("\n SourceLat=%lf",it->sourceLat); printf("\n SourceLng=%lf",it->sourceLng); vector<App42GeoPoint>app42GeoPointList = it->pointList; for(std::vector<App42GeoPoint>::iterator geoPoint = app42GeoPointList.begin(); geoPoint != app42GeoPointList.end(); ++geoPoint) { printf("\n Latitude=%lf",geoPoint->latitude); printf("\n Longitude=%lf",geoPoint->longitude); printf("\n MarkerName = %s",geoPoint->markerName.c_str()); } } } else { printf("\nerrordetails:%s",geoResponse->errorDetails.c_str()); printf("\nerrorMessage:%s",geoResponse->errorMessage.c_str()); printf("\nappErrorCode:%d",geoResponse->appErrorCode); printf("\nhttpErrorCode:%d",geoResponse->httpErrorCode); string error = StringUtils::format("Error = %s",geoResponse->errorDetails.c_str()); responseArray.push_back(error); string errorMsg = StringUtils::format("ErrorMessage = %s",geoResponse->errorMessage.c_str()); responseArray.push_back(errorMsg); } auto scheduler = Director::getInstance()->getScheduler(); scheduler->performFunctionInCocosThread(CC_CALLBACK_0(TestGeoService::loadResponseScene, this)); }
/** * Callback Methods */ void TestSessionService::onSessionServiceRequestCompleted( void *response) { App42SessionResponse *app42SessionResponse = (App42SessionResponse*)response; string code = StringUtils::format("Code = %d",app42SessionResponse->getCode()); responseArray.push_back(code); if(app42SessionResponse->isSuccess) { printf("\ncode=%d",app42SessionResponse->getCode()); printf("\nisSuccess=%d",app42SessionResponse->isSuccess); printf("\nResponse Body=%s",app42SessionResponse->getBody().c_str()); printf("\nUserName=%s",app42SessionResponse->app42Session.userName.c_str()); printf("\nSessionId=%s",app42SessionResponse->app42Session.sessionId.c_str()); printf("\nCreatedOn=%s",app42SessionResponse->app42Session.createdOn.c_str()); printf("\nInvalidatedOn=%s",app42SessionResponse->app42Session.invalidatedOn.c_str()); //sessionId = app42SessionResponse->app42Session.sessionId; vector<App42Attribute> attributesArray = app42SessionResponse->app42Session.attributeArray; for(std::vector<App42Attribute>::iterator attribute = attributesArray.begin(); attribute != attributesArray.end(); ++attribute) { printf("\n Name=%s",attribute->name.c_str()); printf("\n Value=%s\n",attribute->value.c_str()); } } else { printf("\nerrordetails:%s",app42SessionResponse->errorDetails.c_str()); printf("\nerrorMessage:%s",app42SessionResponse->errorMessage.c_str()); printf("\nappErrorCode:%d",app42SessionResponse->appErrorCode); printf("\nhttpErrorCode:%d",app42SessionResponse->httpErrorCode); string error = StringUtils::format("Error = %s",app42SessionResponse->errorDetails.c_str()); responseArray.push_back(error); string errorMsg = StringUtils::format("ErrorMessage = %s",app42SessionResponse->errorMessage.c_str()); responseArray.push_back(errorMsg); } auto scheduler = Director::getInstance()->getScheduler(); scheduler->performFunctionInCocosThread(CC_CALLBACK_0(TestSessionService::loadResponseScene, this)); }
void _asyncLoadThreadFunc(struct __Args* args) { std::mutex mt; std::unique_lock<std::mutex> lock(mt); args->cv.wait(lock); #if COCOS2D_DEBUG auto texInfo = cocos2d::Director::getInstance()->getTextureCache()->getCachedTextureInfo(); cocos2d::log("texInfo: %s", texInfo.c_str()); #endif auto scheduler = cocos2d::Director::getInstance()->getScheduler(); for (auto it=args->bound; it!=args->resources.end(); ++it) { loadOtherResources(*it); --args->size_res; scheduler->performFunctionInCocosThread(std::bind(args->callback, args->size_res)); if (args->size_res == 0) { delete args; return; } } }
void HttpDownload::onProgress(double percent, void *delegate, string filefullPath){ // 下载进度 if (_stopDownload) { CurlDown * cd = (CurlDown *)delegate; cd->setStopDown(); _stopDownload = false; } //进入Cocos主线程然后分发 auto scheduler = Director::getInstance()->getScheduler(); scheduler->performFunctionInCocosThread([this,percent,delegate,filefullPath] { //TODO:分发给LUA CURLDOWNLOG("Download Progress %.2f%%",percent); if (_delegate) { _delegate->onProgress(percent,delegate,filefullPath); } }); }
/** * Callback Methods */ void TestEmailService::onEmailRequestCompleted( void *response) { App42EmailResponse *emailResponse = (App42EmailResponse*)response; printf("\ncode=%d...%d",emailResponse->getCode(),emailResponse->isSuccess); printf("\nResponse Body=%s",emailResponse->getBody().c_str()); string code = StringUtils::format("Code = %d",emailResponse->getCode()); responseArray.push_back(code); if(emailResponse->isSuccess) { printf("\n From=%s",emailResponse->from.c_str()); printf("\n To=%s",emailResponse->to.c_str()); printf("\n Subject=%s",emailResponse->subject.c_str()); printf("\n Body=%s",emailResponse->body.c_str()); for(std::vector<App42Configuration>::iterator it = emailResponse->configurationArray.begin(); it != emailResponse->configurationArray.end(); ++it) { printf("\n EmailId=%s",it->emailId.c_str()); printf("\n Host=%s\n",it->host.c_str()); printf("\n Port=%d\n",it->port); printf("\n SSL=%d\n",it->ssl); } } else { printf("\nerrordetails:%s",emailResponse->errorDetails.c_str()); printf("\nerrorMessage:%s",emailResponse->errorMessage.c_str()); printf("\nappErrorCode:%d",emailResponse->appErrorCode); printf("\nhttpErrorCode:%d",emailResponse->httpErrorCode); string error = StringUtils::format("Error = %s",emailResponse->errorDetails.c_str()); responseArray.push_back(error); string errorMsg = StringUtils::format("ErrorMessage = %s",emailResponse->errorMessage.c_str()); responseArray.push_back(errorMsg); } auto scheduler = Director::getInstance()->getScheduler(); scheduler->performFunctionInCocosThread(CC_CALLBACK_0(TestEmailService::loadResponseScene, this)); }
void ComsumeController::showSPrite() { char message[100]; Size winSize = Director::getInstance()->getVisibleSize(); powerSavingMode(message); this->removeChild(_sprite1); if(_doorStatus == 0){ _sprite1 = Sprite::create("normal_door.png"); _sprite1->setScale(1.0f); _sprite1->setPosition(Vec2(winSize.width/2, winSize.height/2)); _doorStatus = 1; }else{ _sprite1 = Sprite::create("normal_door_close.png"); _sprite1->setScale(1.0f); _sprite1->setPosition(Vec2(winSize.width/2, winSize.height/2)); _doorStatus = 0; } addChild(_sprite1); // 別スレッドを生成して引数を渡して実行する auto t = std::thread([this] (int n) { for (int i = 0; i < 100; i++) { mtx.lock(); log("%d", n + i); mtx.unlock(); } // 処理が一通り終わったのでメインスレッドに戻してメソッドを呼ぶ auto scheduler = Director::getInstance()->getScheduler(); scheduler->performFunctionInCocosThread(CC_CALLBACK_0(ComsumeController::dispatchThreadCallbacks, this)); }, 1000); // スレッドの管理を手放す // スレッドの処理を待つ場合はt.join()かstd::asyncを使う t.detach(); }
/** * Callback Methods */ void TestTimerService::onTimerServiceRequestCompleted( void *response) { App42TimerResponse *app42TimerResponse = (App42TimerResponse*)response; string code = StringUtils::format("Code = %d",app42TimerResponse->getCode()); responseArray.push_back(code); if(app42TimerResponse->isSuccess) { printf("\ncode=%d",app42TimerResponse->getCode()); printf("\nisSuccess=%d",app42TimerResponse->isSuccess); printf("\nResponse Body=%s",app42TimerResponse->getBody().c_str()); printf("\n TimerName =%s",app42TimerResponse->app42Timer.name.c_str()); printf("\n userName =%s",app42TimerResponse->app42Timer.userName.c_str()); printf("\n currentTime =%s",app42TimerResponse->app42Timer.currentTime.c_str()); printf("\n startTime =%s",app42TimerResponse->app42Timer.startTime.c_str()); printf("\n endTime =%s",app42TimerResponse->app42Timer.endTime.c_str()); printf("\n timeInSeconds=%ld",app42TimerResponse->app42Timer.timeInSeconds); printf("\n isTimerActive=%d",app42TimerResponse->app42Timer.isTimerActive); } else { printf("\nerrordetails:%s",app42TimerResponse->errorDetails.c_str()); printf("\nerrorMessage:%s",app42TimerResponse->errorMessage.c_str()); printf("\nappErrorCode:%d",app42TimerResponse->appErrorCode); printf("\nhttpErrorCode:%d",app42TimerResponse->httpErrorCode); string error = StringUtils::format("Error = %s",app42TimerResponse->errorDetails.c_str()); responseArray.push_back(error); string errorMsg = StringUtils::format("ErrorMessage = %s",app42TimerResponse->errorMessage.c_str()); responseArray.push_back(errorMsg); } auto scheduler = Director::getInstance()->getScheduler(); scheduler->performFunctionInCocosThread(CC_CALLBACK_0(TestTimerService::loadResponseScene, this)); }
void TestUploadService::onUploadRequestCompleted( void *response) { App42UploadResponse *uploadResponse = (App42UploadResponse*)response; printf("\ncode=%d",uploadResponse->getCode()); printf("\nResponse Body=%s",uploadResponse->getBody().c_str()); string code = StringUtils::format("Code = %d",uploadResponse->getCode()); responseArray.push_back(code); if(uploadResponse->isSuccess) { printf("\nTotalRecords=%d",uploadResponse->getTotalRecords()); for(std::vector<App42Upload>::iterator it = uploadResponse->uploadArray.begin(); it != uploadResponse->uploadArray.end(); ++it) { printf("\n Name=%s",it->name.c_str()); printf("\n UserName=%s",it->userName.c_str()); printf("\n Type=%s",it->type.c_str()); printf("\n Description=%s",it->description.c_str()); printf("\n TinyUrl=%s",it->tinyUrl.c_str()); printf("\n Url=%s",it->url.c_str()); printf("\n CreatedOn=%s",it->createdOn.c_str()); } } else { printf("\nerrordetails :%s",uploadResponse->errorDetails.c_str()); printf("\nerrorMessage :%s",uploadResponse->errorMessage.c_str()); printf("\nappErrorCode :%d",uploadResponse->appErrorCode); printf("\nhttpErrorCode:%d",uploadResponse->httpErrorCode); string error = StringUtils::format("Error = %s",uploadResponse->errorDetails.c_str()); responseArray.push_back(error); string errorMsg = StringUtils::format("ErrorMessage = %s",uploadResponse->errorMessage.c_str()); responseArray.push_back(errorMsg); } auto scheduler = Director::getInstance()->getScheduler(); scheduler->performFunctionInCocosThread(CC_CALLBACK_0(TestUploadService::loadResponseScene, this)); }
// Worker thread void HttpClient::networkThreadAlone(HttpRequest* request, HttpResponse* response) { std::string errorStr; processHttpResponse(response, errorStr); auto scheduler = Director::getInstance()->getScheduler(); scheduler->performFunctionInCocosThread([response, request]{ const ccHttpRequestCallback& callback = request->getCallback(); Ref* pTarget = request->getTarget(); SEL_HttpResponse pSelector = request->getSelector(); if (callback != nullptr) { callback(s_pHttpClient, response); } else if (pTarget && pSelector) { (pTarget->*pSelector)(s_pHttpClient, response); } response->release(); // do not release in other thread request->release(); }); }
void TcpClient::processPacket() { auto scheduler = cocos2d::Director::getInstance()->getScheduler(); /// 패킷을 파싱해서 완성되는 패킷이 있으면, 해당 콜백을 불러준다. while (true) { PacketHeader header; if (false == mRecvBuffer.Peek((char*)&header, sizeof(PacketHeader))) break; if (header.mSize > mRecvBuffer.GetStoredSize()) break; if (cocos2d::Director::getInstance()->getRunningScene() == nullptr) break; switch (header.mType) { case PKT_SC_LOGIN: { LoginResult recvData; bool ret = mRecvBuffer.Read((char*)&recvData, recvData.mSize); assert(ret && recvData.mPlayerId != -1); mLoginId = recvData.mPlayerId; auto scene = GET_NETWORK_SCENE; if (scene) { //다음 update를 위한 초기화 scheduler->performFunctionInCocosThread(CC_CALLBACK_0(NetworkScene::ClearRoomInfo, scene)); for (auto& room : recvData.mRoomList) { if (room.mRoomNum < 0) // roomNum이 0이하면 roomList의 끝이므로 break break; scheduler->performFunctionInCocosThread(CC_CALLBACK_0(NetworkScene::PushRoomInfo, scene, room)); } scheduler->performFunctionInCocosThread(CC_CALLBACK_0(NetworkScene::UpdateRoomInfo, scene)); } } break; case PKT_SC_MAKE_ROOM: { MakeRoomResult recvData; bool ret = mRecvBuffer.Read((char*)&recvData, recvData.mSize); assert(ret && recvData.mPlayerId != -1); auto scene = GET_NETWORK_SCENE; if (scene) { scheduler->performFunctionInCocosThread(CC_CALLBACK_0(NetworkScene::MakeRoomComplete, scene, recvData.mRoomInfo)); } } break; case PKT_SC_INOUT_ROOM: { InOutRoomResult recvData; bool ret = mRecvBuffer.Read((char*)&recvData, recvData.mSize); assert(ret && recvData.mPlayerId != -1); if (recvData.mPlayerId != mLoginId) { auto scene = GET_ROOM_SCENE; if (scene) { scheduler->performFunctionInCocosThread(CC_CALLBACK_0(RoomScene::UpdateRoomInfo, scene, recvData.mRoomInfo)); } auto player = GET_GM.GetPlayer(recvData.mPlayerId); if (player && !recvData.mIsIn) { GET_GM.DeletePlayer(recvData.mPlayerId); } } else { auto scene = GET_NETWORK_SCENE; if (scene) { scheduler->performFunctionInCocosThread(CC_CALLBACK_0(NetworkScene::JoinRoomComplete, scene, recvData.mRoomInfo)); } } } break; case PKT_SC_GAME_READY: { GameReadyResult recvData; bool ret = mRecvBuffer.Read((char*)&recvData, recvData.mSize); assert(ret && recvData.mPlayerId != -1); auto player = GET_GM.GetPlayer(recvData.mPlayerId); if (!player) { GET_GM.SetPlayer(recvData.mPlayerId); GET_GM.GetPlayer(recvData.mPlayerId)->SetPlayerName(recvData.mPlayerName); } auto scene = GET_ROOM_SCENE; } break; case PKT_SC_ALL_READY: { AllReadyNotify recvData; bool ret = mRecvBuffer.Read((char*)&recvData, recvData.mSize); assert(ret && recvData.mPlayerId != -1); auto scene = GET_ROOM_SCENE; if (scene) { scheduler->performFunctionInCocosThread(CC_CALLBACK_0(RoomScene::GameStart, scene)); } } return; // 이 다음 패킷 수신 전에 콜백함수 호출이 필요하므로 리턴 case PKT_SC_CREATE_HERO: { CreateHeroResult recvData; bool ret = mRecvBuffer.Read((char*)&recvData, recvData.mSize); assert(ret && recvData.mPlayerId != -1); Vec2 pos = CONVERT(recvData.mPos); if (recvData.mPlayerId == mLoginId) { mTeam = recvData.mTeam; } if (GET_GAME_SCENE == nullptr) { break; } auto layer = GET_OBJECT_LAYER; if (layer) { scheduler->performFunctionInCocosThread(CC_CALLBACK_0(ObjectLayer::CreateHero, layer, recvData.mPlayerId, recvData.mUnitId, pos, recvData.mTeam, recvData.mRoomType)); } } break; case PKT_SC_CREATE_MAP: { CreateMapResult recvData; bool ret = mRecvBuffer.Read((char*)&recvData, recvData.mSize); assert(ret && recvData.mPlayerId != -1); Vec2 pos = CONVERT(recvData.mPos); if (GET_GAME_SCENE == nullptr) { break; } auto layer = GET_OBJECT_LAYER; if (layer) { scheduler->performFunctionInCocosThread(CC_CALLBACK_0(ObjectLayer::CreateMapObject, layer, recvData.mUnitId, pos)); } } break; case PKT_SC_CREATE_MOB: { CreateMobResult recvData; bool ret = mRecvBuffer.Read((char*)&recvData, recvData.mSize); assert(ret && recvData.mPlayerId != -1); Vec2 pos = CONVERT(recvData.mPos); if (GET_GAME_SCENE == nullptr) { break; } auto layer = GET_OBJECT_LAYER; if (layer) { scheduler->performFunctionInCocosThread(CC_CALLBACK_0(ObjectLayer::CreateMob, layer, recvData.mPlayerId, recvData.mUnitId, pos, recvData.mHp, recvData.mSpeed)); } } break; case PKT_SC_CREATE_ITEM: { ItemBroadcastResult recvData; bool ret = mRecvBuffer.Read((char*)&recvData, recvData.mSize); assert(ret && recvData.mPlayerId != -1); Vec2 pos = CONVERT(recvData.mPos); if (GET_GAME_SCENE == nullptr) { break; } auto layer = GET_OBJECT_LAYER; if (layer) { if (recvData.mIsCreate) { scheduler->performFunctionInCocosThread(CC_CALLBACK_0(ObjectLayer::CreateItem, layer, recvData.mPlayerId, recvData.mUnitId, pos, recvData.mBuffType)); } else { scheduler->performFunctionInCocosThread(CC_CALLBACK_0(ObjectLayer::RemoveItem, layer, recvData.mPlayerId, recvData.mUnitId)); } } } break; case PKT_SC_RUN_COMPLETE: { ServerRunCompleteNotify recvData; bool ret = mRecvBuffer.Read((char*)&recvData, recvData.mSize); assert(ret && recvData.mPlayerId != -1); if (GET_GAME_SCENE == nullptr) { break; } auto layer = GET_LOADING_LAYER; if (layer) { scheduler->performFunctionInCocosThread(CC_CALLBACK_0(LoadingBGLayer::SetLoadingFin, layer)); } } return; // 이 다음 패킷 수신 전에 콜백함수 호출이 필요하므로 리턴 case PKT_SC_START_GAME: { StartGameNotify recvData; bool ret = mRecvBuffer.Read((char*)&recvData, recvData.mSize); assert(ret && recvData.mPlayerId != -1); auto scene = GET_GAME_SCENE; if (scene) { scheduler->performFunctionInCocosThread(CC_CALLBACK_0(GameScene::StartGame, scene)); } } break; case PKT_SC_MOVE: { MoveBroadcastResult recvData; bool ret = mRecvBuffer.Read((char*)&recvData, recvData.mSize); assert(ret && recvData.mPlayerId != -1); Vec2 targetPos = CONVERT(recvData.mTargetPos); if (GET_GAME_SCENE == nullptr) { break; } auto layer = GET_OBJECT_LAYER; if (layer) { scheduler->performFunctionInCocosThread(CC_CALLBACK_0(ObjectLayer::UnitMove, layer, recvData.mUnitId, targetPos)); } } break; case PKT_SC_CRASH: { CrashedBroadcastResult recvData; bool ret = mRecvBuffer.Read((char*)&recvData, recvData.mSize); assert(ret && recvData.mPlayerId != -1); Vec2 expectPos = CONVERT(recvData.mExpectPos); if (GET_GAME_SCENE == nullptr) { break; } auto layer = GET_OBJECT_LAYER; if (layer) { scheduler->performFunctionInCocosThread(CC_CALLBACK_0(ObjectLayer::UnitCrash, layer, recvData.mUnitId, expectPos)); } } break; case PKT_SC_SYNC: { SyncPosBroadcastResult recvData; bool ret = mRecvBuffer.Read((char*)&recvData, recvData.mSize); assert(ret && recvData.mPlayerId != -1); Vec2 revisionPos = CONVERT(recvData.mCurrentPos); if (GET_GAME_SCENE == nullptr) { break; } auto layer = GET_OBJECT_LAYER; if (layer) { scheduler->performFunctionInCocosThread(CC_CALLBACK_0(ObjectLayer::UnitCrashEnd, layer, recvData.mUnitId, revisionPos)); scheduler->performFunctionInCocosThread(CC_CALLBACK_0(ObjectLayer::MissileCrash, layer, recvData.mUnitId)); } } break; case PKT_SC_SKILL: { SkillBroadcastResult recvData; bool ret = mRecvBuffer.Read((char*)&recvData, recvData.mSize); assert(ret && recvData.mPlayerId != -1); Vec2 curPos = CONVERT(recvData.mCurrentPos); Vec2 targetPos = CONVERT(recvData.mTargetPos); if (GET_GAME_SCENE == nullptr) { break; } auto layer = GET_OBJECT_LAYER; if (layer) { scheduler->performFunctionInCocosThread(CC_CALLBACK_0(ObjectLayer::UnitSkillUse, layer, recvData.mPlayerId, recvData.mUnitId, recvData.mKey, curPos, targetPos)); } } break; case PKT_SC_MISSILE: { MissileBroadcastResult recvData; bool ret = mRecvBuffer.Read((char*)&recvData, recvData.mSize); assert(ret && recvData.mPlayerId != -1); Vec2 curPos = CONVERT(recvData.mCurrentPos); Vec2 targetPos = CONVERT(recvData.mTargetPos); if (GET_GAME_SCENE == nullptr) { break; } auto layer = GET_OBJECT_LAYER; if (layer) { scheduler->performFunctionInCocosThread(CC_CALLBACK_0(ObjectLayer::ShootMissile, layer, recvData.mUnitId, curPos, targetPos)); } } break; case PKT_SC_HP: { HpBroadcastResult recvData; bool ret = mRecvBuffer.Read((char*)&recvData, recvData.mSize); assert(ret && recvData.mPlayerId != -1); if (GET_GAME_SCENE == nullptr) { break; } auto layer = GET_OBJECT_LAYER; if (layer) { scheduler->performFunctionInCocosThread(CC_CALLBACK_0(ObjectLayer::UnitHpUpdate, layer, recvData.mPlayerId, recvData.mUnitId, recvData.mHp)); } } break; case PKT_SC_BUFF: { BuffBroadcastResult recvData; bool ret = mRecvBuffer.Read((char*)&recvData, recvData.mSize); assert(ret && recvData.mPlayerId != -1); if (GET_GAME_SCENE == nullptr) { break; } auto layer = GET_OBJECT_LAYER; if (layer) { scheduler->performFunctionInCocosThread(CC_CALLBACK_0(ObjectLayer::UnitBuffApply, layer, recvData.mUnitId, recvData.mBonus, recvData.mBuffTarget, recvData.mIsOn)); } } break; case PKT_SC_EFFECT: { EffectBroadcastResult recvData; bool ret = mRecvBuffer.Read((char*)&recvData, recvData.mSize); assert(ret && recvData.mPlayerId != -1); Vec2 pos = CONVERT(recvData.mPos); if (GET_GAME_SCENE == nullptr) { break; } auto layer = GET_OBJECT_LAYER; if (layer) { scheduler->performFunctionInCocosThread(CC_CALLBACK_0(ObjectLayer::CreateEffect, layer, recvData.mEffectType, pos)); } } break; case PKT_SC_HIDE: { HideBroadcastResult recvData; bool ret = mRecvBuffer.Read((char*)&recvData, recvData.mSize); assert(ret && recvData.mPlayerId != -1); if (GET_GAME_SCENE == nullptr) { break; } auto layer = GET_OBJECT_LAYER; if (layer) { scheduler->performFunctionInCocosThread(CC_CALLBACK_0(ObjectLayer::UnitHide, layer, recvData.mPlayerId, recvData.mUnitId, recvData.mIsOn)); } } break; case PKT_SC_GAMEOVER: { GameOverNotify recvData; bool ret = mRecvBuffer.Read((char*)&recvData, recvData.mSize); assert(ret && recvData.mPlayerId != -1); bool isWin = false; if (mTeam == recvData.mWinTeam) { isWin = true; } auto scene = GET_GAME_SCENE; if (scene) { scheduler->performFunctionInCocosThread(CC_CALLBACK_0(GameScene::GameOver, scene, mLoginId, isWin)); } } return; default: assert(false); } } }
// 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; } }
// 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); processResponse(response, s_errorBuffer); // 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; } }
void TestController::traverseTestList(TestList* testList) { if (testList == _rootTestList) { _sleepCondition.wait_for(*_sleepUniqueLock, std::chrono::milliseconds(500)); } else { _logIndentation += LOG_INDENTATION; _sleepCondition.wait_for(*_sleepUniqueLock, std::chrono::milliseconds(500)); } logEx("%s%sBegin traverse TestList:%s", LOG_TAG, _logIndentation.c_str(), testList->getTestName().c_str()); auto scheduler = _director->getScheduler(); int testIndex = 0; for (auto& callback : testList->_testCallbacks) { if (_stopAutoTest) break; while (_isRunInBackground) { logEx("_director is paused"); _sleepCondition.wait_for(*_sleepUniqueLock, std::chrono::milliseconds(500)); } if (callback) { auto test = callback(); test->setTestParent(testList); test->setTestName(testList->_childTestNames[testIndex++]); if (test->isTestList()) { scheduler->performFunctionInCocosThread([&](){ test->runThisTest(); }); traverseTestList((TestList*)test); } else { traverseTestSuite((TestSuite*)test); } } } if (testList == _rootTestList) { _stopAutoTest = true; } else { if (!_stopAutoTest) { //Backs up one level and release TestList object. scheduler->performFunctionInCocosThread([&](){ testList->_parentTest->runThisTest(); }); _sleepCondition.wait_for(*_sleepUniqueLock, std::chrono::milliseconds(500)); testList->release(); } _logIndentation.erase(_logIndentation.rfind(LOG_INDENTATION)); } }
void TestController::traverseTestSuite(TestSuite* testSuite) { auto scheduler = _director->getScheduler(); int testIndex = 0; float testCaseDuration = 0.0f; _logIndentation += LOG_INDENTATION; logEx("%s%sBegin traverse TestSuite:%s", LOG_TAG, _logIndentation.c_str(), testSuite->getTestName().c_str()); _logIndentation += LOG_INDENTATION; testSuite->_currTestIndex = -1; auto logIndentation = _logIndentation; for (auto& callback : testSuite->_testCallbacks) { auto testName = testSuite->_childTestNames[testIndex++]; Scene* testScene = nullptr; TestCase* testCase = nullptr; TransitionScene* transitionScene = nullptr; if (_stopAutoTest) break; while (_isRunInBackground) { logEx("_director is paused"); _sleepCondition.wait_for(*_sleepUniqueLock, std::chrono::milliseconds(500)); } //Run test case in the cocos[GL] thread. scheduler->performFunctionInCocosThread([&, logIndentation, testName](){ if (_stopAutoTest) return; logEx("%s%sRun test:%s.", LOG_TAG, logIndentation.c_str(), testName.c_str()); auto scene = callback(); if (_stopAutoTest) return; if (scene) { transitionScene = dynamic_cast<TransitionScene*>(scene); if (transitionScene) { testCase = (TestCase*)transitionScene->getInScene(); testCaseDuration = transitionScene->getDuration() + 0.5f; } else { testCase = (TestCase*)scene; testCaseDuration = testCase->getDuration(); } testSuite->_currTestIndex++; testCase->setTestSuite(testSuite); testCase->setTestCaseName(testName); testCase->setAutoTesting(true); _director->replaceScene(scene); testScene = scene; } }); if (_stopAutoTest) break; //Wait for the test case be created. float waitTime = 0.0f; while (!testScene && !_stopAutoTest) { _sleepCondition.wait_for(*_sleepUniqueLock, std::chrono::milliseconds(50)); if (!_isRunInBackground) { waitTime += 0.05f; } if (waitTime > CREATE_TIME_OUT) { logEx("%sCreate test %s time out", LOG_TAG, testName.c_str()); _stopAutoTest = true; break; } } if (_stopAutoTest) break; //Wait for test completed. _sleepCondition.wait_for(*_sleepUniqueLock, std::chrono::milliseconds(int(1000 * testCaseDuration))); if (transitionScene == nullptr) { waitTime = 0.0f; while (!_stopAutoTest && testCase->isAutoTesting()) { _sleepCondition.wait_for(*_sleepUniqueLock, std::chrono::milliseconds(50)); if (!_isRunInBackground) { waitTime += 0.05f; } if (waitTime > TEST_TIME_OUT) { logEx("%sRun test %s time out", LOG_TAG, testName.c_str()); _stopAutoTest = true; break; } } if (!_stopAutoTest) { //Check the result of test. checkTest(testCase); } } } if (!_stopAutoTest) { //Backs up one level and release TestSuite object. auto parentTest = testSuite->_parentTest; scheduler->performFunctionInCocosThread([parentTest](){ parentTest->runThisTest(); }); _sleepCondition.wait_for(*_sleepUniqueLock, std::chrono::milliseconds(1000)); testSuite->release(); } _logIndentation.erase(_logIndentation.rfind(LOG_INDENTATION)); _logIndentation.erase(_logIndentation.rfind(LOG_INDENTATION)); }