diff options
-rw-r--r-- | LuaSL/src/LuaSL.h | 2 | ||||
-rw-r--r-- | LuaSL/src/LuaSL_threads.c | 146 | ||||
-rw-r--r-- | LuaSL/src/LuaSL_threads.h | 11 |
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 */ | 82 | typedef struct |
84 | struct 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 */ |
164 | static void luaproc_queue_sender(luaproc lp) | 158 | static 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 */ |
170 | static luaproc luaproc_dequeue_sender(channel chan) | 164 | static 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 */ |
181 | static void luaproc_queue_receiver(luaproc lp) | 175 | static 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 */ |
187 | static luaproc luaproc_dequeue_receiver(channel chan) | 181 | static 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 */ |
230 | static void *workermain( void *args ) { | 224 | static 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) */ |
320 | static int sched_queue_proc( luaproc lp ) { | 323 | static 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 | ||
379 | void newProc(const char *code, int file, script *data) | 382 | void 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 */ |
449 | static luaproc luaproc_getself( lua_State *L ) { | 454 | static 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 */ |
501 | static int luaproc_send_back( lua_State *L ) { | 507 | static 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 */ |
532 | const char *sendToChannel(const char *chname, const char *message, luaproc *dst, channel *chn) | 538 | const 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, | |||
590 | static int luaproc_send( lua_State *L ) { | 596 | static 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 ) { | |||
622 | static int luaproc_receive( lua_State *L ) { | 628 | static 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 */ |
47 | typedef struct stchannel *channel; | 47 | typedef struct stchannel *channel; |
48 | 48 | ||
49 | /* lua process pointer type */ | ||
50 | typedef struct stluaproc *luaproc; | ||
51 | |||
52 | 49 | ||
53 | void luaprocInit(void); | 50 | void luaprocInit(void); |
54 | 51 | ||
55 | /* create a new worker pthread */ | 52 | /* create a new worker pthread */ |
56 | int sched_create_worker( void ); | 53 | int sched_create_worker(void); |
57 | 54 | ||
58 | void newProc(const char *code, int file, script *data); | 55 | void newProc(const char *code, int file, script *lp); |
59 | const char *sendToChannel(const char *chname, const char *message, luaproc *dst, channel *chn); | 56 | const 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 */ |
62 | void sched_join_workerthreads( void ); | 59 | void sched_join_workerthreads(void); |
63 | 60 | ||
64 | #endif | 61 | #endif |