But in cocos2dx,all the operations are done in the UI thread via CCdisplaylinkDirector::mainLoop in CCDirector.cpp. To avoID blocking UI thread,we can use the two methods to achIEve it: > Using timer mechanism,i.e.,CCScheduler. With this way,the operation will be execute until the timeout is triggered,but it is still run in UI thread. So when a blocking call is invoked,the UI thread is still be blocked. > Using worker thread to do the blocking operation,such as reading data from network etc. When there is no data comes,the worker thread will be blocked,and it will spend no cpu times. Since it will not never blocking UI thread,it is the prefered method. Cocos2dx doesn't provIDe an implementation for multithreading,this article provIDes a way to achIEve multithreading in cocos2dx. It will need to change several source files in cocos2dx framework. The goal of this implementation is that: > Using pthread which is supported in most of platforms,such as linux,windows,even ios,androID etc. (cocos2dx/httpclIEnt is using pthread) > Easy for any CCNode (also including its subclasses) who wants to handle the messages to register/unregister the handler. > ProvIDes a message queue for each worker thread for communicating with other threads The main class design is as below: class EXTCCHandler { public: // Max len of the name is 32 char EXTCCHandler(const char *pname); virtual ~EXTCCHandler(); // it will suspend current thread if there is no message in queue static bool hasMessage(const EXTCCHandler * const handler); // it will proccess messages in queue and // return till all the messages in queue are processed static voID processMessage(const EXTCCHandler * const handler); // register a handler to current hander thread // when a message comes, // "processMessage" will dispatch msg to each registered handler voID registerHandler(const CCObject *pTarget,const EXTCCHandleMessage &handler); // unregister a handler voID unregisterHandler( const CCObject *pTarget, const EXTCCHandleMessage &handler); // post a message to current handler thread,it's async call voID postMessage(const EXTCcmessage &msg); }; class EXTCCHandlerThread : public EXTCCHandler { ~EXTCCHandlerThread(); // create a handler thread,Max len of the thread name is 32 char static EXTCCHandlerThread *create(const char *pThreadname); protected: EXTCCHandlerThread(const char *pThreadname); private: static voID *loop(voID *pArgs); Some changes in Cocos2dx framework: > make folder of "HandlerThread" under "cocos2d-x-2.x.x/cocos2dx/platform" > copy the source code to "cocos2d-x-2.x.x/cocos2dx/platform/HandlerThread" > find CCDirector.cpp and CCDirector.h (which locate in cocos2dx/) andadd static variable in CCDirector.cpp (below "static CCdisplaylinkDirector *s_SharedDirector = NulL;") static EXTCCHandler *s_MainLoopHandler = NulL;
@H_419_155@ > add static function in class CCDirector @H_419_155@CCDirector.h:add below class declaration before NS_CC_BEGIN @H_419_155@: class EXTCCHandler; @H_419_155@ CCDirector.h: (add below statement blow "static CCDirector* sharedDirector(voID);" static EXTCCHandler *mainLoopHandler(voID); @H_419_155@ CCDirector.cpp: (add below implementation below static method "CCDirector* CCDirector::sharedDirector(voID)" EXTCCHandler *CCDirector::mainLoopHandler(voID) { if (s_MainLoopHandler == NulL) { s_MainLoopHandler = new EXTCCHandler("MainUILoop"); } return s_MainLoopHandler; } @H_419_155@ CCDirector.cpp: add below statements into CCdisplaylinkDirector::mainLoop function @H_419_155@ voID CCdisplaylinkDirector::mainLoop(voID) @H_419_155@ { @H_419_155@ if (m_bPurgeDirecotorInNextLoop) @H_419_155@ { @H_419_155@ m_bPurgeDirecotorInNextLoop = false; @H_419_155@ purgeDirector(); @H_419_155@ } @H_419_155@ else if (! m_bInvalID) @H_419_155@ drawScene(); @H_419_155@ @H_419_155@ // release the objects @H_419_155@ CCPoolManager::sharedPoolManager()->pop(); /// { added for supporting handler thread /// if (s_MainLoopHandler) { EXTCCHandler::processMessage(s_MainLoopHandler); /// added for supporting handler thread } /// @H_419_155@ } @H_419_155@ > add header file includes in "cocos2d-x-2.x.x/cocos2dx/include/cocos2d.h" // Handler thread #include "platform/HandlerThread/EXTCCHandlerThread.h" In Xcode,we MUST run "install-templates-xcode.sh" again to update the templates in Xcode: in console,run below command: sudo ./install-templates-xcode.sh -f NOTE: because we dIDn't udpate the templates project file in cocos2dx templates for Xcode,so on every time we create Xcode cocos2dx project,we MUST copy the folder of "HandlerThread" into the created project folder (xxx is the created project name): "xxx//libs/cocos2dx/platform/",and add these files in XCode project explorer manually. In AndroID,we MUST update AndroID.mk in "cocos2d-x-2.x.x/cocos2dx",add below source files in LOCAL_SRC_fileS: \ platform/HandlerThread/EXTCCHandler.cpp \ platform/HandlerThread/EXTCCHandlerThread.cpp
Only XCode and AndroID platform I've trIEd,if on other platforms,you must do similar changes by yourself.
How to use: 0. In UI thread,we can register a handler to process message in UI thread. bool HelloWorldScene::handleMessageInUIThread(const EXTCcmessage &msg) { // implementations // return true if this handler has processed this msg,otherwise,false is returned switch (msg.msgid) { case 2: break; default: return false; } return true; } // register this Handler to UI Threader CCDirector::mainLoopHandler()->registerHandler(this,
(EXTCCHandleMessage)& HelloWorldScene:: handleMessageInUIThread); 1. Creating worker thread: EXTCCHandlerThread *g_workThread = EXTCCHandlerThread::create("WorkThreadname"); 2. Register a message handle to this created handler thread (function of handleMessage will be run in g_workThread): bool handleMessageInWorkerThread(const EXTCcmessage &msg) { case 1: g_workThread->registerHandler(this,
(EXTCCHandleMessage)& handleMessageInWorkerThread); 3. When we get a handlerThread handler,we can post message in UI thread or other worker thread to it for processing: EXTCcmessage msg; msg.msgid = 1; msg.msgData1 = NulL;
@H_419_155@ // "msg" will be processed by "handleMessageInWorkerThread" running in g_workThread g_workThread->postMessage(msg); 4. In a worker thread,we can send message to UI thread for updating UI: msg.msgid = 2; // "msg" will be processed by "handleMessageInUIThread" in UI thread CCDirector::mainLoopHandler()->postMessage(msg); 5. If the object doesn't need to proccess message anymore,you MUST unregister the handler to avoID memory leak: CCDirector::mainLoopHandler()->unregisterHandler(this,
@H_419_155@ g_workThread->unregisterHandler(this,0)">handleMessageInWorkerThread); @H_419_155@ Notice in using multithreads in cocos2dx: > In worker thread,it CAN NOT update UI element at any time. The corrected way is posting a message which contains the updating data to UI thread for doing updates. (refer to: http://www.cocos2d-x.org/projects/cocos2d-x/wiki/How_to_use_pthread#How-to-use-pthread) > This handler thread doesn't contains autorelease mechanism provIDed by Cocos2dx,so it's user's responsibility to do release on msgData in EXTCcmessage. > There is no limits on HanderThread's message queue. It will grow double length (the default length is 16) if there is no slot for new coming message > Because AndroID dIDn't provIDe a cancel call for pthread (pthread_cancel,pthread_testcancel),so in this implementation,no EXTCCHandlerThread::cancel is provIDed. If you want this API,pls Google it,there is some ways to achIEve it. > If a message dIDn't be processed by any handler,a log will be output: ###Message [msgid] is NOT processed by thread [Threadname]!!!
@H_419_155@
Source code:
@H_419_155@Right click below picture to save it to your PC,rename suffix name to rar,and open it with winRar: 总结
以上是内存溢出为你收集整理的How to support multithread in cocos2dx全部内容,希望文章能够帮你解决How to support multithread in cocos2dx所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)