Ideas
Implementation Ideas
1. Using the Pthread library, encapsulates a class for performing asynchronous tasks that provide a method to accept a LUA function and then execute that function in a child thread. 2. Use the tolua++ tool to bind a C + + custom class to Lua.
Code Ideas (pseudo code)
Defines a C + + class Asyntaskhandler to handle asynchronous tasks that need to be performed in Lua, which has a queue (FIFO) for holding tasks.
Task task = NULL;
Starts a loop in a child thread to process the task in the queue while
(true) {
//defines whether a bool variable token exits the loop and, at the beginning of the loop, determines whether to exit the loop
if (need_quit) {
break ;
}
task = NULL;
Get tasks from Queue task
= Task_queue.pop ()
//If the queue is empty if
(null = = Task) {
//when the thread is sleeping, wait for the main thread to add tasks and wake the current threads
thread_sleep ();
Continues the current loop continue when the thread is awakened
;
}
Perform task Dotask (Task) If the task is successfully acquired
;
Task.release ();
}
If you exit the cycle
//Cleanup task queue and the resource if
(task_queue) {
task_queue.clear ();
Task_queue = NULL;
}
Exit thread
thread_exit ();
Initialize
void Asyntaskhandler::lazyinit ()
{
//If the task queue is not initialized if
(taskqueue = = NULL)
{
// Create Task queue
Taskqueue = Queue.create ();
Create thread
thread_create ();
Execution thread
thead_execute ();
Initialize exit marked flase
Need_quit = false;}
}
Add Task
void asyntaskhandler::addtask (int task)
{
//Initialize
lazyinit ();
Add to Task Queue
Task_queue.add (Task);
Wakeup worker thread
thread_wakeup ();
}
Implement
#include "AsynTaskHandler.h" #include "CCLuaEngine.h" #include//#include//single static Asyntaskhandler *s_pasyntask =
NULL;
Task Queue static ccarray* s_taskqueue = NULL;
Static Std::vector S_taskqueue;
Thread lock static pthread_mutex_t S_taskqueuemutex;
Conditional variable static pthread_mutex_t S_sleepmutex;
Static pthread_cond_t s_sleepcondition;
Thread ID static pthread_t s_workthread;
Task loop flag static BOOL Need_quit = FALSE;
Worker thread static void* workthread (void *data) {ccinteger* task = NULL;
while (true) {//If an exit signal is received, exit the loop if (Need_quit) {break;
} task = NULL;
Gets the task Pthread_mutex_lock (&s_taskqueuemutex) in the team header from the task queue;
if (0! = S_taskqueue->count ()) {task = dynamic_cast (s_taskqueue->objectatindex (0));
S_taskqueue->removeobjectatindex (0);
} pthread_mutex_unlock (&s_taskqueuemutex); If the queue does not have a task if (NULL = = Task) {//The thread sleeps, waits for the main thread to add the task and wakes the current threads pthread_cond_wait (&s_sleepcondition, &S_SL
Eepmutex); Continue
}//If the Get task succeeds, perform task ccluastack* pstack = ccluaengine::d efaultengine ()->getluastack ();
The first parameter is the integer handle of the function, and the second parameter is the number of function arguments Pstack->executefunctionbyhandler (task->getvalue (), 0);
Pstack->clean ();
Task->release ();
}//If an exit signal is received, Cleanup task queue and release Resources pthread_mutex_lock (&s_taskqueuemutex);
S_taskqueue->removeallobjects ();
Pthread_mutex_unlock (&s_taskqueuemutex);
if (s_taskqueue! = NULL) {Pthread_mutex_destroy (&s_taskqueuemutex);
Pthread_mutex_destroy (&s_sleepmutex);
Pthread_cond_destroy (&s_sleepcondition);
S_taskqueue->release ();
S_taskqueue = NULL;
} pthread_exit (NULL);
return 0;
} void Asyntaskhandler::lazyinit () {if (S_taskqueue = = NULL) {//Create task Queue S_taskqueue = new Ccarray ();
S_taskqueue->init ();
Initialization of the thread lock Pthread_mutex_init (&s_taskqueuemutex, NULL);
Initialize the condition variable pthread_mutex_init (&s_sleepmutex, NULL);
Pthread_cond_init (&s_sleepcondition, NULL); Create Thread pthread_create (&s_workthread, NULL, workthread, NULL);
Execution thread Pthread_detach (s_workthread);
Need_quit = false;
}} Asyntaskhandler::asyntaskhandler () {} asyntaskhandler::~asyntaskhandler () {//stop loop Need_quit = true;
Destroy task queue if (s_taskqueue! = NULL) {//wake thread, clean resource pthread_cond_signal (&s_sleepcondition);
} s_pasyntask = NULL; }/** Return the shared instance **/Asyntaskhandler *asyntaskhandler::getinstance () {if (S_pasyntask = = NULL) {S_pas
Yntask = new Asyntaskhandler ();
} return s_pasyntask;
}/** relase the shared instance **/void Asyntaskhandler::d Estroy () {s_pasyntask->release ();}
Add task void Asyntaskhandler::addtask (int task) {lazyinit ();
Add to Task Queue Pthread_mutex_lock (&s_taskqueuemutex);
S_taskqueue->addobject (Ccinteger::create (Task));
Pthread_mutex_unlock (&s_taskqueuemutex);
Wake-up worker thread pthread_cond_signal (&s_sleepcondition);
} #ifndef __asyntaskhandler_h__ #define __ASYNTASKHANDLER_H__ #include "cocos2d.h" USING_NS_CC; Tools for executing asynchronous tasks in LuaClass Asyntaskhandler:public Ccobject {Public:asyntaskhandler ();
Virtual ~asyntaskhandler ();
void AddTask (int task);
Lazy loading void lazyinit ();
/** Return the shared instance **/static Asyntaskhandler *getinstance ();
/** relase the shared instance **/static void Destroy ();
};
#endif//__asyntaskhandler_h__
binding to Lua
Click to see "Using the tolua++ tool to use C + + custom classes in Lua"
The pkg file that you need to use to bind to Lua is the following code:
Class Asyntaskhandler:public Ccobject
{
asyntaskhandler ();
~asyntaskhandler ();
void AddTask (lua_function task);
Static Asyntaskhandler *getinstance ();
static void Destroy ();
};
The code hint files used in the Cocos Code IDE project are placed in the source directory:
--------Asynchronous Task Tool class
---------------------------------
-@module Asyntaskhandler
----------------------- ----------
-@function [parent= #AsynTaskHandler] AddTask
--@param self--@param #int
Task
------ --------------------------
--@function [parent= #AsynTaskHandler] destory
--@param self
----------- ----------------------
-@function [parent= #AsynTaskHandler] getinstance-
-@param self
--@return Asyntaskhandler#asyntaskhandler ret (return value:asyntaskhandler)
return nil
Test
The test code is as follows (LUA code):
--Test asynchronous execution Task
asyntaskhandler:getinstance (): AddTask (function ()
cclog ("Asyn task is running..")
For I=1, the
"Child thread num=%s", the i)
end
end) for
I=1, the
"main thread Cclog", i) C9/>end
The log output is as follows:
It can be seen in the log that "main thread Num=1" was first output, meaning that the main thread was not blocked.
Note: Cocos2d-x related APIs (such as Cctexturecache) cannot be called in a child thread due to Cocos2d-x's memory management mechanism.
The official note is as follows: Http://www.cocos2d-x.org/wiki/How_to_use_pthread 1.Don ' t call any functions which invokes Ref::retain (), Ref:: Release () or Ref::autorelease (), because Autoreleasepool is not thread-safe. Refer to Reference Count and Autoreleasepool in cocos2d-x for more details. Cocos2d-x use Autoreleasepool every the where in it framework, so my suggestion are that, don ' t invoke any cocos2d-x API in a New thread except Data structures.
Autoreleasepool is not thread-safe.
2.If want to load resources in a new thread, can use Texturecache::addimageasync ()
If you want to load resources asynchronously, you can use Texturecache::addimageasync ().
3.pthread_cond_wait () seems has a bug, it can not wait for the first time, but works properly in subsequence.
Pthread_cond_wait () has a bug. It is not normal at the time of the first call, but the subsequent use will work properly.
about inter-thread communication
You can use Ccnotificationcenter for inter-thread Communication in cocos2d-x2.x (note: Ccnotificationcenter is not thread-safe). In cocos2d-x3.x, you can use Eventcustomelistener for inter-thread communication.
Project git address: Https://coding.net/linchaolong/LuaAsynTaskHandler.git related article: use of "cocos2d-x" Pthread Library