aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-rw-r--r--LuaSL/src/LuaSL.h2
-rw-r--r--LuaSL/src/LuaSL_threads.c146
-rw-r--r--LuaSL/src/LuaSL_threads.h11
3 files changed, 81 insertions, 78 deletions
diff --git a/LuaSL/src/LuaSL.h b/LuaSL/src/LuaSL.h
index bde4c2f..936477f 100644
--- a/LuaSL/src/LuaSL.h
+++ b/LuaSL/src/LuaSL.h
@@ -76,7 +76,7 @@ struct _script
76 gameGlobals *game; 76 gameGlobals *game;
77 char SID[PATH_MAX]; 77 char SID[PATH_MAX];
78 char fileName[PATH_MAX]; 78 char fileName[PATH_MAX];
79 lua_State *lstate; 79 lua_State *L;
80 struct timeval startTime; 80 struct timeval startTime;
81 float compileTime, timerTime; 81 float compileTime, timerTime;
82 int bugs, warnings; 82 int bugs, warnings;
diff --git a/LuaSL/src/LuaSL_threads.c b/LuaSL/src/LuaSL_threads.c
index 399d077..d24f224 100644
--- a/LuaSL/src/LuaSL_threads.c
+++ b/LuaSL/src/LuaSL_threads.c
@@ -40,7 +40,6 @@ THE SOFTWARE.
40 * Probably one fixed unique message channel per object, which each script in the object shares. 40 * Probably one fixed unique message channel per object, which each script in the object shares.
41 * But might be better to handle that C side anyway. 41 * But might be better to handle that C side anyway.
42 * Better integration with LuaSL. 42 * Better integration with LuaSL.
43 * Merge the luaproc structure with the script structure.
44 * Use ecore threads instead of raw pthreads. 43 * Use ecore threads instead of raw pthreads.
45 * Ecore threads pretty much wraps pthreads on posix, but has Windows support to. 44 * Ecore threads pretty much wraps pthreads on posix, but has Windows support to.
46 * Merge in the edje Lua code, and keep an eye on that, coz we might want to actually add this to edje Lua in the future. 45 * Merge in the edje Lua code, and keep an eye on that, coz we might want to actually add this to edje Lua in the future.
@@ -80,16 +79,11 @@ struct stchannel {
80 pthread_cond_t *in_use; 79 pthread_cond_t *in_use;
81}; 80};
82 81
83/* lua process */ 82typedef struct
84struct stluaproc { 83{
85 Eina_Clist node; 84 Eina_Clist node;
86 lua_State *lstate; 85 lua_State *L;
87 int status; 86} recycled;
88 int args;
89 channel chan;
90 void *data;
91};
92
93 87
94/********* 88/*********
95* globals 89* globals
@@ -161,34 +155,34 @@ static const struct luaL_reg luaproc_funcs_child[] = {
161 155
162 156
163/* queue a lua process sending a message without a matching receiver */ 157/* queue a lua process sending a message without a matching receiver */
164static void luaproc_queue_sender(luaproc lp) 158static void luaproc_queue_sender(script *lp)
165{ 159{
166 eina_clist_add_tail(&(lp->chan->send), &(lp->node)); 160 eina_clist_add_tail(&(lp->chan->send), &(lp->node));
167} 161}
168 162
169/* dequeue a lua process sending a message with a receiver match */ 163/* dequeue a lua process sending a message with a receiver match */
170static luaproc luaproc_dequeue_sender(channel chan) 164static script *luaproc_dequeue_sender(channel chan)
171{ 165{
172 luaproc lp; 166 script *lp;
173 167
174 if ((lp = (luaproc) eina_clist_head(&(chan->send)))) 168 if ((lp = (script *) eina_clist_head(&(chan->send))))
175 eina_clist_remove(&(lp->node)); 169 eina_clist_remove(&(lp->node));
176 170
177 return lp; 171 return lp;
178} 172}
179 173
180/* queue a luc process receiving a message without a matching sender */ 174/* queue a luc process receiving a message without a matching sender */
181static void luaproc_queue_receiver(luaproc lp) 175static void luaproc_queue_receiver(script *lp)
182{ 176{
183 eina_clist_add_tail(&(lp->chan->recv), &(lp->node)); 177 eina_clist_add_tail(&(lp->chan->recv), &(lp->node));
184} 178}
185 179
186/* dequeue a lua process receiving a message with a sender match */ 180/* dequeue a lua process receiving a message with a sender match */
187static luaproc luaproc_dequeue_receiver(channel chan) 181static script *luaproc_dequeue_receiver(channel chan)
188{ 182{
189 luaproc lp; 183 script *lp;
190 184
191 if ((lp = (luaproc) eina_clist_head(&(chan->recv)))) 185 if ((lp = (script *) eina_clist_head(&(chan->recv))))
192 eina_clist_remove(&(lp->node)); 186 eina_clist_remove(&(lp->node));
193 187
194 return lp; 188 return lp;
@@ -229,7 +223,7 @@ static void sched_lpcount_dec(void)
229/* worker thread main function */ 223/* worker thread main function */
230static void *workermain( void *args ) { 224static void *workermain( void *args ) {
231 225
232 luaproc lp; 226 script *lp;
233 int procstat; 227 int procstat;
234 228
235 /* detach thread so resources are freed as soon as thread exits (no further joining) */ 229 /* detach thread so resources are freed as soon as thread exits (no further joining) */
@@ -247,7 +241,7 @@ static void *workermain( void *args ) {
247 } 241 }
248 242
249 /* pop the first node from the ready process queue */ 243 /* pop the first node from the ready process queue */
250 if ((lp = (luaproc) eina_clist_head(&lpready))) 244 if ((lp = (script *) eina_clist_head(&lpready)))
251 eina_clist_remove(&(lp->node)); 245 eina_clist_remove(&(lp->node));
252 else { 246 else {
253 /* free access to the process ready queue */ 247 /* free access to the process ready queue */
@@ -260,19 +254,28 @@ static void *workermain( void *args ) {
260 pthread_mutex_unlock( &mutex_queue_access ); 254 pthread_mutex_unlock( &mutex_queue_access );
261 255
262 /* execute the lua code specified in the lua process struct */ 256 /* execute the lua code specified in the lua process struct */
263 procstat = lua_resume(lp->lstate, lp->args); 257 procstat = lua_resume(lp->L, lp->args);
264 258
265 /* reset the process argument count */ 259 /* reset the process argument count */
266 lp->args = 0; 260 lp->args = 0;
267 261
268 /* check if process finished its whole execution, then recycle it */ 262 /* check if process finished its whole execution, then recycle it */
269 if ( procstat == 0 ) { 263 if (procstat == 0)
264 {
265 recycled *trash = malloc(sizeof(recycled));
270 266
267 if (trash)
268 {
269 trash->L = lp->L;
271 pthread_mutex_lock(&mutex_recycle_list); 270 pthread_mutex_lock(&mutex_recycle_list);
272 eina_clist_add_tail(&recyclelp, &(lp->node)); 271 eina_clist_add_tail(&recyclelp, &(trash->node));
273 pthread_mutex_unlock(&mutex_recycle_list); 272 pthread_mutex_unlock(&mutex_recycle_list);
274 sched_lpcount_dec(); 273 sched_lpcount_dec();
275 274 }
275 lua_close(lp->L);
276// if (lp->timer)
277// ecore_timer_del(lp->timer);
278 free(lp);
276 } 279 }
277 280
278 /* check if process yielded */ 281 /* check if process yielded */
@@ -307,9 +310,9 @@ static void *workermain( void *args ) {
307 /* check if there was any execution error (LUA_ERRRUN, LUA_ERRSYNTAX, LUA_ERRMEM or LUA_ERRERR) */ 310 /* check if there was any execution error (LUA_ERRRUN, LUA_ERRSYNTAX, LUA_ERRMEM or LUA_ERRERR) */
308 else { 311 else {
309 /* print error message */ 312 /* print error message */
310 fprintf( stderr, "close lua_State (error: %s)\n", luaL_checkstring(lp->lstate, -1 )); 313 fprintf( stderr, "close lua_State (error: %s)\n", luaL_checkstring(lp->L, -1 ));
311 /* close lua state */ 314 /* close lua state */
312 lua_close(lp->lstate); 315 lua_close(lp->L);
313 /* decrease active lua process count */ 316 /* decrease active lua process count */
314 sched_lpcount_dec(); 317 sched_lpcount_dec();
315 } 318 }
@@ -317,7 +320,7 @@ static void *workermain( void *args ) {
317} 320}
318 321
319/* move process to ready queue (ie, schedule process) */ 322/* move process to ready queue (ie, schedule process) */
320static int sched_queue_proc( luaproc lp ) { 323static int sched_queue_proc( script *lp ) {
321 324
322 /* get exclusive access to the ready process queue */ 325 /* get exclusive access to the ready process queue */
323 pthread_mutex_lock( &mutex_queue_access ); 326 pthread_mutex_lock( &mutex_queue_access );
@@ -376,51 +379,53 @@ int sched_create_worker( void ) {
376 379
377 380
378 381
379void newProc(const char *code, int file, script *data) 382void newProc(const char *code, int file, script *lp)
380{ 383{
381 int ret; 384 int ret;
382 luaproc lp; 385 recycled *trash;
383 386
384 // Try to recycle a Lua state, otherwise create one from scratch. 387 // Try to recycle a Lua state, otherwise create one from scratch.
385 pthread_mutex_lock(&mutex_recycle_list); 388 pthread_mutex_lock(&mutex_recycle_list);
386 /* pop list head */ 389 /* pop list head */
387 if ((lp = (luaproc) eina_clist_head(&recyclelp))) 390 if ((trash = (recycled *) eina_clist_head(&recyclelp)))
388 eina_clist_remove(&(lp->node)); 391 {
392 eina_clist_remove(&(trash->node));
393 lp->L = trash->L;
394 free(trash);
395 }
389 pthread_mutex_unlock(&mutex_recycle_list); 396 pthread_mutex_unlock(&mutex_recycle_list);
390 397
391 if (lp == NULL) 398 if (NULL == lp->L)
392 { 399 {
393 lua_State *lpst = luaL_newstate(); 400 lp->L = luaL_newstate();
394 401
395 /* store the luaproc struct in its own Lua state */ 402 /* store the script struct in its own Lua state */
396 lp = (luaproc) lua_newuserdata(lpst, sizeof(struct stluaproc)); 403 lua_pushlightuserdata(lp->L, lp);
397 lp->lstate = lpst; 404 lua_setfield(lp->L, LUA_REGISTRYINDEX, "_SELF");
398 lua_setfield(lp->lstate, LUA_REGISTRYINDEX, "_SELF"); 405 luaL_openlibs(lp->L);
399 luaL_openlibs(lp->lstate); 406 luaL_register(lp->L, "luaproc", luaproc_funcs_child);
400 luaL_register(lp->lstate, "luaproc", luaproc_funcs_child);
401 eina_clist_element_init(&(lp->node));
402 } 407 }
403 408
404 lp->status = LUAPROC_STAT_IDLE; 409 lp->status = LUAPROC_STAT_IDLE;
405 lp->args = 0; 410 lp->args = 0;
406 lp->chan = NULL; 411 lp->chan = NULL;
412 eina_clist_element_init(&(lp->node));
407 413
408 /* load process' code */ 414 /* load process' code */
409 if (file) 415 if (file)
410 ret = luaL_loadfile(lp->lstate, code); 416 ret = luaL_loadfile(lp->L, code);
411 else 417 else
412 ret = luaL_loadstring(lp->lstate, code); 418 ret = luaL_loadstring(lp->L, code);
413 419
414 /* in case of errors, destroy Lua process */ 420 /* in case of errors, destroy Lua process */
415 if (ret != 0) 421 if (ret != 0)
416 { 422 {
417 lua_close(lp->lstate); 423 lua_close(lp->L);
418 lp = NULL; 424 lp->L = NULL;
419 } 425 }
420 426
421 if (lp) 427 if (lp->L)
422 { 428 {
423 lp->data = data;
424 sched_lpcount_inc(); 429 sched_lpcount_inc();
425 430
426 /* schedule luaproc */ 431 /* schedule luaproc */
@@ -428,7 +433,7 @@ void newProc(const char *code, int file, script *data)
428 { 433 {
429 printf( "[luaproc] error queueing Lua process\n" ); 434 printf( "[luaproc] error queueing Lua process\n" );
430 sched_lpcount_dec(); 435 sched_lpcount_dec();
431 lua_close(lp->lstate); 436 lua_close(lp->L);
432 } 437 }
433 } 438 }
434} 439}
@@ -446,12 +451,13 @@ static void luaproc_movevalues( lua_State *Lfrom, lua_State *Lto ) {
446} 451}
447 452
448/* return the lua process associated with a given lua state */ 453/* return the lua process associated with a given lua state */
449static luaproc luaproc_getself( lua_State *L ) { 454static script *luaproc_getself(lua_State *L)
450 luaproc lp; 455{
451 lua_getfield( L, LUA_REGISTRYINDEX, "_SELF" ); 456 script *lp;
452 lp = (luaproc )lua_touserdata( L, -1 ); 457 lua_getfield(L, LUA_REGISTRYINDEX, "_SELF");
453 lua_pop( L, 1 ); 458 lp = (script *) lua_touserdata(L, -1);
454 return lp; 459 lua_pop(L, 1);
460 return lp;
455} 461}
456 462
457/* create a new channel */ 463/* create a new channel */
@@ -500,17 +506,17 @@ static int luaproc_create_channel(lua_State *L)
500/* send a message to a lua process */ 506/* send a message to a lua process */
501static int luaproc_send_back( lua_State *L ) { 507static int luaproc_send_back( lua_State *L ) {
502 508
503 luaproc self; 509 script *self;
504 const char *message = luaL_checkstring( L, 1 ); 510 const char *message = luaL_checkstring( L, 1 );
505 511
506 self = luaproc_getself( L ); 512 self = luaproc_getself(L);
507 if (self && self->data) 513 if (self)
508 { 514 {
509 scriptMessage *sm = calloc(1, sizeof(scriptMessage)); 515 scriptMessage *sm = calloc(1, sizeof(scriptMessage));
510 516
511 if (sm) 517 if (sm)
512 { 518 {
513 sm->script = self->data; 519 sm->script = self;
514 strcpy((char *) sm->message, message); 520 strcpy((char *) sm->message, message);
515 ecore_main_loop_thread_safe_call_async(scriptSendBack, sm); 521 ecore_main_loop_thread_safe_call_async(scriptSendBack, sm);
516 } 522 }
@@ -529,11 +535,11 @@ const char *sendToChannelErrors[] =
529// TODO - If these come in too quick, then messages might get lost. Also, in at least one case, it locked up this thread I think. 535// TODO - If these come in too quick, then messages might get lost. Also, in at least one case, it locked up this thread I think.
530 536
531/* send a message to a lua process */ 537/* send a message to a lua process */
532const char *sendToChannel(const char *chname, const char *message, luaproc *dst, channel *chn) 538const char *sendToChannel(const char *chname, const char *message, script **dst, channel *chn)
533{ 539{
534 const char *result = NULL; 540 const char *result = NULL;
535 channel chan; 541 channel chan;
536 luaproc dstlp; 542 script *dstlp;
537 543
538 /* get exclusive access to operate on channels */ 544 /* get exclusive access to operate on channels */
539 pthread_mutex_lock(&mutex_channel); 545 pthread_mutex_lock(&mutex_channel);
@@ -558,9 +564,9 @@ const char *sendToChannel(const char *chname, const char *message, luaproc *dst,
558 if (dstlp != NULL) 564 if (dstlp != NULL)
559 { 565 {
560 /* push the message onto the receivers stack */ 566 /* push the message onto the receivers stack */
561 lua_pushstring( dstlp->lstate, message); 567 lua_pushstring( dstlp->L, message);
562 568
563 dstlp->args = lua_gettop(dstlp->lstate) - 1; 569 dstlp->args = lua_gettop(dstlp->L) - 1;
564 570
565 if (sched_queue_proc(dstlp) != LUAPROC_SCHED_QUEUE_PROC_OK) 571 if (sched_queue_proc(dstlp) != LUAPROC_SCHED_QUEUE_PROC_OK)
566 { 572 {
@@ -571,7 +577,7 @@ const char *sendToChannel(const char *chname, const char *message, luaproc *dst,
571 sched_lpcount_dec(); 577 sched_lpcount_dec();
572 578
573 /* close lua_State */ 579 /* close lua_State */
574 lua_close(dstlp->lstate); 580 lua_close(dstlp->L);
575 return sendToChannelErrors[1]; 581 return sendToChannelErrors[1];
576 } 582 }
577 583
@@ -579,7 +585,7 @@ const char *sendToChannel(const char *chname, const char *message, luaproc *dst,
579 luaproc_unlock_channel(chan); 585 luaproc_unlock_channel(chan);
580 } 586 }
581 else if (dst) 587 else if (dst)
582 dst = &dstlp; 588 *dst = dstlp;
583 589
584 if (chn) 590 if (chn)
585 chn = &chan; 591 chn = &chan;
@@ -590,7 +596,7 @@ const char *sendToChannel(const char *chname, const char *message, luaproc *dst,
590static int luaproc_send( lua_State *L ) { 596static int luaproc_send( lua_State *L ) {
591 597
592 channel chan; 598 channel chan;
593 luaproc dstlp, self; 599 script *dstlp, *self;
594 const char *chname = luaL_checkstring( L, 1 ); 600 const char *chname = luaL_checkstring( L, 1 );
595 const char *message = luaL_checkstring( L, 2 ); 601 const char *message = luaL_checkstring( L, 2 );
596 const char *result = sendToChannel(chname, message, &dstlp, &chan); 602 const char *result = sendToChannel(chname, message, &dstlp, &chan);
@@ -622,7 +628,7 @@ static int luaproc_send( lua_State *L ) {
622static int luaproc_receive( lua_State *L ) { 628static int luaproc_receive( lua_State *L ) {
623 629
624 channel chan; 630 channel chan;
625 luaproc srclp, self; 631 script *srclp, *self;
626 const char *chname = luaL_checkstring( L, 1 ); 632 const char *chname = luaL_checkstring( L, 1 );
627 633
628 /* get exclusive access to operate on channels */ 634 /* get exclusive access to operate on channels */
@@ -650,10 +656,10 @@ static int luaproc_receive( lua_State *L ) {
650 if ( srclp != NULL ) { 656 if ( srclp != NULL ) {
651 657
652 /* move values between Lua states' stacks */ 658 /* move values between Lua states' stacks */
653 luaproc_movevalues( srclp->lstate, L ); 659 luaproc_movevalues( srclp->L, L );
654 660
655 /* return to sender indicanting message was sent */ 661 /* return to sender indicanting message was sent */
656 lua_pushboolean( srclp->lstate, TRUE ); 662 lua_pushboolean( srclp->L, TRUE );
657 srclp->args = 1; 663 srclp->args = 1;
658 664
659 if ( sched_queue_proc( srclp ) != LUAPROC_SCHED_QUEUE_PROC_OK ) { 665 if ( sched_queue_proc( srclp ) != LUAPROC_SCHED_QUEUE_PROC_OK ) {
@@ -665,7 +671,7 @@ static int luaproc_receive( lua_State *L ) {
665 sched_lpcount_dec(); 671 sched_lpcount_dec();
666 672
667 /* close lua_State */ 673 /* close lua_State */
668 lua_close( srclp->lstate ); 674 lua_close( srclp->L );
669 lua_pushnil( L ); 675 lua_pushnil( L );
670 lua_pushstring( L, "error scheduling process" ); 676 lua_pushstring( L, "error scheduling process" );
671 return 2; 677 return 2;
diff --git a/LuaSL/src/LuaSL_threads.h b/LuaSL/src/LuaSL_threads.h
index 47f5a69..b5f019b 100644
--- a/LuaSL/src/LuaSL_threads.h
+++ b/LuaSL/src/LuaSL_threads.h
@@ -46,19 +46,16 @@ THE SOFTWARE.
46/* message channel pointer type */ 46/* message channel pointer type */
47typedef struct stchannel *channel; 47typedef struct stchannel *channel;
48 48
49/* lua process pointer type */
50typedef struct stluaproc *luaproc;
51
52 49
53void luaprocInit(void); 50void luaprocInit(void);
54 51
55/* create a new worker pthread */ 52/* create a new worker pthread */
56int sched_create_worker( void ); 53int sched_create_worker(void);
57 54
58void newProc(const char *code, int file, script *data); 55void newProc(const char *code, int file, script *lp);
59const char *sendToChannel(const char *chname, const char *message, luaproc *dst, channel *chn); 56const char *sendToChannel(const char *chname, const char *message, script **dst, channel *chn);
60 57
61/* join all worker threads and exit */ 58/* join all worker threads and exit */
62void sched_join_workerthreads( void ); 59void sched_join_workerthreads(void);
63 60
64#endif 61#endif