aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/LuaSL
diff options
context:
space:
mode:
authorDavid Walter Seikel2012-02-25 09:43:05 +1000
committerDavid Walter Seikel2012-02-25 09:43:05 +1000
commitbd82e0ebd6db7ab7a9577c9ec6d9a9a9c2d73db8 (patch)
tree47fb8b023eceb67bb94751d307d7486ced3fed0b /LuaSL
parentPartial rewrite of the luaproc messages. Still not fixed yet. (diff)
downloadSledjHamr-bd82e0ebd6db7ab7a9577c9ec6d9a9a9c2d73db8.zip
SledjHamr-bd82e0ebd6db7ab7a9577c9ec6d9a9a9c2d73db8.tar.gz
SledjHamr-bd82e0ebd6db7ab7a9577c9ec6d9a9a9c2d73db8.tar.bz2
SledjHamr-bd82e0ebd6db7ab7a9577c9ec6d9a9a9c2d73db8.tar.xz
Beat the script messsage passing into shape, mostly by knocking large chunks off. lol
Diffstat (limited to 'LuaSL')
-rw-r--r--LuaSL/src/LSL.lua12
-rw-r--r--LuaSL/src/LuaSL.h1
-rw-r--r--LuaSL/src/LuaSL_main.c10
-rw-r--r--LuaSL/src/LuaSL_test.c12
-rw-r--r--LuaSL/src/LuaSL_threads.c451
-rw-r--r--LuaSL/src/LuaSL_threads.h9
6 files changed, 108 insertions, 387 deletions
diff --git a/LuaSL/src/LSL.lua b/LuaSL/src/LSL.lua
index 3810abc..662c880 100644
--- a/LuaSL/src/LSL.lua
+++ b/LuaSL/src/LSL.lua
@@ -82,6 +82,7 @@ end
82 82
83events = {} 83events = {}
84 84
85function start() paused = false end
85function stop() paused = true end 86function stop() paused = true end
86function quit() running = false end 87function quit() running = false end
87 88
@@ -761,26 +762,18 @@ function LSL.stateChange(x)
761end; 762end;
762 763
763function LSL.mainLoop(sid, name, x) 764function LSL.mainLoop(sid, name, x)
764 local status, errorMsg = luaproc.newchannel(sid) 765 local status, errorMsg
765 local result 766 local result
766 767
767 SID = sid 768 SID = sid
768 scriptName = name 769 scriptName = name
769
770 LSL.EOF = "\n\n\n" -- Fix this up now. 770 LSL.EOF = "\n\n\n" -- Fix this up now.
771 771
772 if not status then
773 msg("Can't open the luaproc channel " .. sid .. " ERROR MESSAGE: " .. errorMsg)
774 return
775 end
776
777 LSL.stateChange(x); 772 LSL.stateChange(x);
778 waitAndProcess(false) 773 waitAndProcess(false)
779 msg("Script quitting.") 774 msg("Script quitting.")
780end 775end
781 776
782-- Need a FIFO queue of incoming events. Which will be in the C main thread, coz that's listening on the socket for us.
783-- The ecore_con stuff ends up being a FIFO queue of the commands coming from OpenSim. So no worries.
784function waitAndProcess(returnWanted) 777function waitAndProcess(returnWanted)
785 local Type = "event" 778 local Type = "event"
786 779
@@ -798,6 +791,7 @@ function waitAndProcess(returnWanted)
798 else 791 else
799 -- Set the functions environment to ours, for the protection of the script, coz loadstring sets it to the global environment instead. 792 -- Set the functions environment to ours, for the protection of the script, coz loadstring sets it to the global environment instead.
800 -- TODO - On the other hand, we will need the global environment when we call event handlers. So we should probably stash it around here somewhere. 793 -- TODO - On the other hand, we will need the global environment when we call event handlers. So we should probably stash it around here somewhere.
794 -- Meh, seems to be working fine as it is.
801 setfenv(result, getfenv(1)) 795 setfenv(result, getfenv(1))
802 status, result = pcall(result) 796 status, result = pcall(result)
803 if not status then 797 if not status then
diff --git a/LuaSL/src/LuaSL.h b/LuaSL/src/LuaSL.h
index 057788b..086d1b7 100644
--- a/LuaSL/src/LuaSL.h
+++ b/LuaSL/src/LuaSL.h
@@ -84,7 +84,6 @@ struct _script
84 boolean running; 84 boolean running;
85 int status; 85 int status;
86 int args; 86 int args;
87 channel chan;
88 Eina_Clist messages; 87 Eina_Clist messages;
89 Ecore_Con_Client *client; 88 Ecore_Con_Client *client;
90 Ecore_Timer *timer; 89 Ecore_Timer *timer;
diff --git a/LuaSL/src/LuaSL_main.c b/LuaSL/src/LuaSL_main.c
index c03a827..f15ae4a 100644
--- a/LuaSL/src/LuaSL_main.c
+++ b/LuaSL/src/LuaSL_main.c
@@ -12,7 +12,7 @@ static Eina_Bool _sleep_timer_cb(void *data)
12 gameGlobals *game = script->game; 12 gameGlobals *game = script->game;
13 13
14 PD("Waking up %s", script->SID); 14 PD("Waking up %s", script->SID);
15 sendToChannel(game, script->SID, "return 0.0", NULL, NULL); 15 sendToChannel(game, script->SID, "return 0.0");
16 return ECORE_CALLBACK_CANCEL; 16 return ECORE_CALLBACK_CANCEL;
17} 17}
18 18
@@ -22,7 +22,7 @@ static Eina_Bool _timer_timer_cb(void *data)
22 gameGlobals *game = script->game; 22 gameGlobals *game = script->game;
23 23
24 PD("Timer for %s", script->SID); 24 PD("Timer for %s", script->SID);
25 sendToChannel(game, script->SID, "events.timer()", NULL, NULL); 25 sendToChannel(game, script->SID, "events.timer()");
26 return ECORE_CALLBACK_RENEW; 26 return ECORE_CALLBACK_RENEW;
27} 27}
28 28
@@ -82,9 +82,9 @@ void scriptSendBack(void * data)
82 while (isspace(*temp)) 82 while (isspace(*temp))
83 temp++; 83 temp++;
84 if ('1' == *temp) 84 if ('1' == *temp)
85 sendToChannel(game, them->SID, "start()", NULL, NULL); 85 sendToChannel(game, them->SID, "start()");
86 else 86 else
87 sendToChannel(game, them->SID, "stop()", NULL, NULL); 87 sendToChannel(game, them->SID, "stop()");
88 PD("Stopped %s", them->fileName); 88 PD("Stopped %s", them->fileName);
89 } 89 }
90 else 90 else
@@ -191,7 +191,7 @@ static Eina_Bool _data(void *data, int type __UNUSED__, Ecore_Con_Event_Client_D
191 { 191 {
192 const char *status = NULL; 192 const char *status = NULL;
193 193
194 status = sendToChannel(game, SID, command, NULL, NULL); 194 status = sendToChannel(game, SID, command);
195 if (status) 195 if (status)
196 PE("Error sending command %s to script %s : %s", command, SID, status); 196 PE("Error sending command %s to script %s : %s", command, SID, status);
197 } 197 }
diff --git a/LuaSL/src/LuaSL_test.c b/LuaSL/src/LuaSL_test.c
index ec76a32..463ae3b 100644
--- a/LuaSL/src/LuaSL_test.c
+++ b/LuaSL/src/LuaSL_test.c
@@ -112,19 +112,17 @@ static Eina_Bool _timer_cb(void *data)
112 { 112 {
113 case 5 : 113 case 5 :
114 { 114 {
115 // TODO - do it as one line, coz sendToChannel() locks up if I do them one at a time too quickly. 115 sendForth(game, me->SID, "events.detectedKeys({\"%s\"})", ownerKey);
116 sendForth(game, me->SID, "events.detectedKeys({\"%s\"}); events.detectedNames({\"%s\"}); events.touch_start(1)", ownerKey, ownerName); 116 sendForth(game, me->SID, "events.detectedNames({\"%s\"})", ownerName);
117// sendForth(game, me->SID, "events.detectedKeys({\"%s\"})", ownerKey); 117 sendForth(game, me->SID, "events.touch_start(1)");
118// sendForth(game, me->SID, "events.detectedNames({\"%s\"})", ownerName);
119// sendForth(game, me->SID, "events.touch_start(1)");
120 break; 118 break;
121 } 119 }
122 case 9+3 : 120 case 9 :
123 { 121 {
124 sendForth(game, me->SID, "quit()"); 122 sendForth(game, me->SID, "quit()");
125 break; 123 break;
126 } 124 }
127 case 11+3 : 125 case 11 :
128 { 126 {
129 exit = TRUE; 127 exit = TRUE;
130 break; 128 break;
diff --git a/LuaSL/src/LuaSL_threads.c b/LuaSL/src/LuaSL_threads.c
index 4a7397e..aec5ed6 100644
--- a/LuaSL/src/LuaSL_threads.c
+++ b/LuaSL/src/LuaSL_threads.c
@@ -33,10 +33,6 @@ THE SOFTWARE.
33/* This is a redesign of luaproc. The design goals and notes - 33/* This is a redesign of luaproc. The design goals and notes -
34 * 34 *
35 * In general use EFL where it is useful. 35 * In general use EFL where it is useful.
36 * One fixed unique message channel per script.
37 * No need for channel.c / .h, we are not using that sort of arbitrary channels.
38 * FIFO queue on message channels, seems the C socket queue is not enough.
39 * On the other hand, could just peel messages of the socket queue, then shove them on the scripts queue.
40 * Probably one fixed unique message channel per object, which each script in the object shares. 36 * 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. 37 * But might be better to handle that C side anyway.
42 * Better integration with LuaSL. 38 * Better integration with LuaSL.
@@ -50,16 +46,9 @@ THE SOFTWARE.
50#include "LuaSL.h" 46#include "LuaSL.h"
51 47
52 48
53#define CHANNEL_MAX_NAME_LENGTH 255
54
55#define CHANNEL_DESTROYED 0
56
57/* ready process queue insertion status */ 49/* ready process queue insertion status */
58#define LUAPROC_SCHED_QUEUE_PROC_OK 0 50#define LUAPROC_SCHED_QUEUE_PROC_OK 0
59#define LUAPROC_SCHED_QUEUE_PROC_ERR -1 51//#define LUAPROC_SCHED_QUEUE_PROC_ERR -1
60
61/* scheduler default number of worker threads */
62#define LUAPROC_SCHED_DEFAULT_WORKER_THREADS 1
63 52
64/* process is idle */ 53/* process is idle */
65#define LUAPROC_STAT_IDLE 0 54#define LUAPROC_STAT_IDLE 0
@@ -71,14 +60,6 @@ THE SOFTWARE.
71#define LUAPROC_STAT_BLOCKED_RECV 3 60#define LUAPROC_STAT_BLOCKED_RECV 3
72 61
73 62
74/* message channel */
75struct stchannel {
76 Eina_Clist send;
77 Eina_Clist recv;
78 pthread_mutex_t *mutex;
79 pthread_cond_t *in_use;
80};
81
82typedef struct 63typedef struct
83{ 64{
84 Eina_Clist node; 65 Eina_Clist node;
@@ -89,12 +70,6 @@ typedef struct
89* globals 70* globals
90*********/ 71*********/
91 72
92/* global channel lua_State mutex */
93pthread_mutex_t mutex_channel_lstate = PTHREAD_MUTEX_INITIALIZER;
94
95/* global where channels will be stored */
96Eina_Hash *channels;
97
98/* ready process list */ 73/* ready process list */
99Eina_Clist lpready; 74Eina_Clist lpready;
100 75
@@ -133,8 +108,6 @@ Eina_Clist recyclelp;
133static int luaproc_send( lua_State *L ); 108static int luaproc_send( lua_State *L );
134/* receive a message from a lua process */ 109/* receive a message from a lua process */
135static int luaproc_receive( lua_State *L ); 110static int luaproc_receive( lua_State *L );
136/* create a new channel */
137static int luaproc_create_channel( lua_State *L );
138/* send a message back to the main loop */ 111/* send a message back to the main loop */
139static int luaproc_send_back( lua_State *L ); 112static int luaproc_send_back( lua_State *L );
140 113
@@ -148,59 +121,11 @@ static const struct luaL_reg luaproc_funcs_parent[] = {
148static const struct luaL_reg luaproc_funcs_child[] = { 121static const struct luaL_reg luaproc_funcs_child[] = {
149 { "send", luaproc_send }, 122 { "send", luaproc_send },
150 { "receive", luaproc_receive }, 123 { "receive", luaproc_receive },
151 { "newchannel", luaproc_create_channel },
152 { "sendback", luaproc_send_back }, 124 { "sendback", luaproc_send_back },
153 { NULL, NULL } 125 { NULL, NULL }
154}; 126};
155 127
156 128
157/* queue a lua process sending a message without a matching receiver */
158static void luaproc_queue_sender(script *lp)
159{
160 eina_clist_add_tail(&(lp->chan->send), &(lp->node));
161}
162
163/* dequeue a lua process sending a message with a receiver match */
164static script *luaproc_dequeue_sender(channel chan)
165{
166 script *lp;
167
168 if ((lp = (script *) eina_clist_head(&(chan->send))))
169 eina_clist_remove(&(lp->node));
170
171 return lp;
172}
173
174/* queue a luc process receiving a message without a matching sender */
175static void luaproc_queue_receiver(script *lp)
176{
177 eina_clist_add_tail(&(lp->chan->recv), &(lp->node));
178}
179
180/* dequeue a lua process receiving a message with a sender match */
181static script *luaproc_dequeue_receiver(channel chan)
182{
183 script *lp;
184
185 if ((lp = (script *) eina_clist_head(&(chan->recv))))
186 eina_clist_remove(&(lp->node));
187
188 return lp;
189}
190
191/* unlock access to a channel */
192static void luaproc_unlock_channel(channel chan)
193{
194 /* get exclusive access to operate on channels */
195 pthread_mutex_lock(&mutex_channel);
196 /* unlock channel access */
197 pthread_mutex_unlock(chan->mutex);
198 /* signal channel not in use */
199 pthread_cond_signal(chan->in_use);
200 /* free access to operate on channels */
201 pthread_mutex_unlock(&mutex_channel);
202}
203
204/* increase active lua process count */ 129/* increase active lua process count */
205static void sched_lpcount_inc(void) 130static void sched_lpcount_inc(void)
206{ 131{
@@ -255,7 +180,6 @@ static void *workermain( void *args ) {
255 180
256 /* execute the lua code specified in the lua process struct */ 181 /* execute the lua code specified in the lua process struct */
257 procstat = lua_resume(lp->L, lp->args); 182 procstat = lua_resume(lp->L, lp->args);
258
259 /* reset the process argument count */ 183 /* reset the process argument count */
260 lp->args = 0; 184 lp->args = 0;
261 185
@@ -273,8 +197,8 @@ static void *workermain( void *args ) {
273 sched_lpcount_dec(); 197 sched_lpcount_dec();
274 } 198 }
275 lua_close(lp->L); 199 lua_close(lp->L);
276// if (lp->timer) 200 if (lp->timer)
277// ecore_timer_del(lp->timer); 201 ecore_timer_del(lp->timer);
278 free(lp); 202 free(lp);
279 } 203 }
280 204
@@ -282,22 +206,15 @@ static void *workermain( void *args ) {
282 else if ( procstat == LUA_YIELD ) { 206 else if ( procstat == LUA_YIELD ) {
283 207
284 /* if so, further check if yield originated from an unmatched send/recv operation */ 208 /* if so, further check if yield originated from an unmatched send/recv operation */
285 if ( lp->status == LUAPROC_STAT_BLOCKED_SEND ) { 209 if (lp->status == LUAPROC_STAT_BLOCKED_SEND)
286 /* queue blocked lua process on corresponding channel */ 210 {
287 luaproc_queue_sender( lp );
288 /* unlock channel access */
289 luaproc_unlock_channel(lp->chan);
290 } 211 }
291 212 else if (lp->status == LUAPROC_STAT_BLOCKED_RECV)
292 else if ( lp->status == LUAPROC_STAT_BLOCKED_RECV ) { 213 {
293 /* queue blocked lua process on corresponding channel */
294 luaproc_queue_receiver( lp );
295 /* unlock channel access */
296 luaproc_unlock_channel(lp->chan);
297 } 214 }
298
299 /* or if yield resulted from an explicit call to coroutine.yield in the lua code being executed */ 215 /* or if yield resulted from an explicit call to coroutine.yield in the lua code being executed */
300 else { 216 else
217 {
301 /* get exclusive access to the ready process queue */ 218 /* get exclusive access to the ready process queue */
302 pthread_mutex_lock( &mutex_queue_access ); 219 pthread_mutex_lock( &mutex_queue_access );
303 /* re-insert the job at the end of the ready process queue */ 220 /* re-insert the job at the end of the ready process queue */
@@ -306,9 +223,9 @@ static void *workermain( void *args ) {
306 pthread_mutex_unlock( &mutex_queue_access ); 223 pthread_mutex_unlock( &mutex_queue_access );
307 } 224 }
308 } 225 }
309
310 /* check if there was any execution error (LUA_ERRRUN, LUA_ERRSYNTAX, LUA_ERRMEM or LUA_ERRERR) */ 226 /* check if there was any execution error (LUA_ERRRUN, LUA_ERRSYNTAX, LUA_ERRMEM or LUA_ERRERR) */
311 else { 227 else
228 {
312 /* print error message */ 229 /* print error message */
313 fprintf( stderr, "close lua_State (error: %s)\n", luaL_checkstring(lp->L, -1 )); 230 fprintf( stderr, "close lua_State (error: %s)\n", luaL_checkstring(lp->L, -1 ));
314 /* close lua state */ 231 /* close lua state */
@@ -365,20 +282,16 @@ void sched_join_workerthreads( void ) {
365} 282}
366 283
367/* create a new worker pthread */ 284/* create a new worker pthread */
368int sched_create_worker( void ) { 285int sched_create_worker(void)
369 286{
370 pthread_t worker; 287 pthread_t worker;
371
372 /* create a new pthread */
373 if ( pthread_create( &worker, NULL, workermain, NULL ) != 0 ) {
374 return LUAPROC_SCHED_PTHREAD_ERROR;
375 }
376 288
377 return LUAPROC_SCHED_OK; 289 /* create a new pthread */
290 if (pthread_create( &worker, NULL, workermain, NULL ) != 0)
291 return LUAPROC_SCHED_PTHREAD_ERROR;
292 return LUAPROC_SCHED_OK;
378} 293}
379 294
380
381
382void newProc(const char *code, int file, script *lp) 295void newProc(const char *code, int file, script *lp)
383{ 296{
384 int ret; 297 int ret;
@@ -408,7 +321,6 @@ void newProc(const char *code, int file, script *lp)
408 321
409 lp->status = LUAPROC_STAT_IDLE; 322 lp->status = LUAPROC_STAT_IDLE;
410 lp->args = 0; 323 lp->args = 0;
411 lp->chan = NULL;
412 eina_clist_element_init(&(lp->node)); 324 eina_clist_element_init(&(lp->node));
413 eina_clist_init(&(lp->messages)); 325 eina_clist_init(&(lp->messages));
414 326
@@ -439,18 +351,6 @@ void newProc(const char *code, int file, script *lp)
439 } 351 }
440} 352}
441 353
442/* moves values between lua states' stacks */
443static void luaproc_movevalues( lua_State *Lfrom, lua_State *Lto ) {
444
445 int i;
446 int n = lua_gettop( Lfrom );
447
448 /* move values between lua states' stacks */
449 for ( i = 2; i <= n; i++ ) {
450 lua_pushstring( Lto, lua_tostring( Lfrom, i ));
451 }
452}
453
454/* return the lua process associated with a given lua state */ 354/* return the lua process associated with a given lua state */
455static script *luaproc_getself(lua_State *L) 355static script *luaproc_getself(lua_State *L)
456{ 356{
@@ -462,70 +362,26 @@ static script *luaproc_getself(lua_State *L)
462 return lp; 362 return lp;
463} 363}
464 364
465/* create a new channel */ 365/* send a message to the client process */
466static int luaproc_create_channel(lua_State *L) 366static int luaproc_send_back(lua_State *L)
467{ 367{
468 const char *name = luaL_checkstring(L, 1); 368 script *self = luaproc_getself(L);
469 channel chan; 369 const char *message = luaL_checkstring(L, 1);
470 370
471 /* get exclusive access to operate on channels */ 371 if (self)
472 pthread_mutex_lock(&mutex_channel);
473
474 /* check if channel exists */
475 if (eina_hash_find(channels, name) != NULL)
476 { 372 {
477 /* free access to operate on channels */ 373 scriptMessage *sm = calloc(1, sizeof(scriptMessage));
478 pthread_mutex_unlock(&mutex_channel);
479 /* return an error to lua */
480 lua_pushnil(L);
481 lua_pushstring(L, "channel already exists");
482 return 2;
483 }
484
485 /* get exclusive access to the channel table */
486 pthread_mutex_lock(&mutex_channel_lstate);
487
488 /* create a new channel */
489 chan = (channel) calloc(1, sizeof(struct stchannel));
490 eina_clist_init(&(chan->send));
491 eina_clist_init(&(chan->recv));
492 chan->mutex = (pthread_mutex_t *) malloc(sizeof(pthread_mutex_t));
493 pthread_mutex_init( chan->mutex, NULL );
494 chan->in_use = (pthread_cond_t *) malloc(sizeof(pthread_cond_t));
495 pthread_cond_init(chan->in_use, NULL);
496 eina_hash_add(channels, name, chan);
497
498 /* let others access the channel table */
499 pthread_mutex_unlock(&mutex_channel_lstate);
500
501 /* free access to operate on channels */
502 pthread_mutex_unlock(&mutex_channel);
503
504 lua_pushboolean(L, TRUE);
505 return 1;
506}
507 374
508/* send a message to the client process */ 375 if (sm)
509static int luaproc_send_back( lua_State *L ) {
510
511 script *self;
512 const char *message = luaL_checkstring( L, 1 );
513
514 self = luaproc_getself(L);
515 if (self)
516 { 376 {
517 scriptMessage *sm = calloc(1, sizeof(scriptMessage)); 377 eina_clist_element_init(&(sm->node));
518 378 sm->script = self;
519 if (sm) 379 strcpy((char *) sm->message, message);
520 { 380 ecore_main_loop_thread_safe_call_async(scriptSendBack, sm);
521 eina_clist_element_init(&(sm->node));
522 sm->script = self;
523 strcpy((char *) sm->message, message);
524 ecore_main_loop_thread_safe_call_async(scriptSendBack, sm);
525 }
526 } 381 }
382 }
527 383
528 return 0; 384 return 0;
529} 385}
530 386
531/* error messages for the sendToChannel function */ 387/* error messages for the sendToChannel function */
@@ -536,224 +392,105 @@ const char *sendToChannelErrors[] =
536}; 392};
537 393
538/* send a message to a lua process */ 394/* send a message to a lua process */
539const char *sendToChannel(gameGlobals *game, const char *chname, const char *message, script **dst, channel *chn) 395const char *sendToChannel(gameGlobals *game, const char *SID, const char *message)
540{ 396{
541 const char *result = NULL; 397 const char *result = NULL;
542 channel chan;
543 script *dstlp; 398 script *dstlp;
544 scriptMessage *sm = NULL;
545 399
546 /* get exclusive access to operate on channels */ 400 /* get exclusive access to operate on channels */
547 pthread_mutex_lock(&mutex_channel); 401 pthread_mutex_lock(&mutex_channel);
548 402
549 // Add the message to the queue. 403 // Add the message to the queue.
550 if ((dstlp = eina_hash_find(game->scripts, chname))) 404 if ((dstlp = eina_hash_find(game->scripts, SID)))
551 { 405 {
406 scriptMessage *sm = NULL;
407
552 if ((sm = malloc(sizeof(scriptMessage)))) 408 if ((sm = malloc(sizeof(scriptMessage))))
553 { 409 {
554 sm->script = dstlp; 410 sm->script = dstlp;
555 strcpy((char *) sm->message, message); 411 strcpy((char *) sm->message, message);
556 eina_clist_add_tail(&(sm->script->messages), &(sm->node)); 412 eina_clist_add_tail(&(dstlp->messages), &(sm->node));
557 } 413 }
558 }
559
560 /* wait until channel is not in use */
561 while( ((chan = eina_hash_find(channels, chname)) != NULL) && (pthread_mutex_trylock(chan->mutex) != 0 ))
562 {
563 pthread_cond_wait(chan->in_use, &mutex_channel);
564 }
565
566 /* free access to operate on channels */
567 pthread_mutex_unlock(&mutex_channel);
568
569 /* if channel is not found, return an error */
570 if (chan == NULL)
571 return sendToChannelErrors[0];
572
573 /* try to find a matching receiver */
574 dstlp = luaproc_dequeue_receiver(chan);
575
576 /* if a match is found, send the message to it and (queue) wake it */
577 if (dstlp != NULL)
578 {
579 scriptMessage *msg = (scriptMessage *) eina_clist_head(&(dstlp->messages));
580 414
581 // See if there's a message on the queue. Note, this may not be the same as the incoming message, if there was already a queue. 415 /* if it's already waiting, send the next message to it and (queue) wake it */
582 if (msg) 416 if (dstlp->status == LUAPROC_STAT_BLOCKED_RECV)
583 { 417 {
584 eina_clist_remove(&(msg->node)); 418 scriptMessage *msg = (scriptMessage *) eina_clist_head(&(dstlp->messages));
585 message = msg->message;
586 }
587 /* push the message onto the receivers stack */
588 lua_pushstring(dstlp->L, message);
589 dstlp->args = lua_gettop(dstlp->L) - 1;
590 if (msg)
591 free(msg);
592
593 if (sched_queue_proc(dstlp) != LUAPROC_SCHED_QUEUE_PROC_OK)
594 {
595 /* unlock channel access */
596 luaproc_unlock_channel(chan);
597 419
598 /* decrease active luaproc count */ 420 // See if there's a message on the queue. Note, this may not be the same as the incoming message, if there was already a queue.
599 sched_lpcount_dec(); 421 if (msg)
422 {
423 eina_clist_remove(&(msg->node));
424 message = msg->message;
425 }
426 /* push the message onto the receivers stack */
427 lua_pushstring(dstlp->L, message);
428 dstlp->args = lua_gettop(dstlp->L) - 1;
429 if (msg)
430 free(msg);
600 431
601 /* close lua_State */ 432 if (sched_queue_proc(dstlp) != LUAPROC_SCHED_QUEUE_PROC_OK)
602 lua_close(dstlp->L); 433 {
603 return sendToChannelErrors[1]; 434 sched_lpcount_dec();
435 lua_close(dstlp->L);
436 result = sendToChannelErrors[1];
437 }
604 } 438 }
605
606 /* unlock channel access */
607 luaproc_unlock_channel(chan);
608 } 439 }
609 else if (dst)
610 *dst = dstlp;
611 440
612 if (chn) 441 pthread_mutex_unlock(&mutex_channel);
613 chn = &chan; 442
614 return result; 443 return result;
615} 444}
616 445
617/* send a message to a lua process */ 446/* send a message to a lua process */
618static int luaproc_send( lua_State *L ) { 447static int luaproc_send(lua_State *L)
619 448{
620 channel chan; 449 script *self = luaproc_getself(L);
621 script *dstlp, *self = luaproc_getself(L); 450 const char *result = sendToChannel(self->game, luaL_checkstring(L, 1), luaL_checkstring(L, 2));
622 const char *chname = luaL_checkstring( L, 1 );
623 const char *message = luaL_checkstring( L, 2 );
624 const char *result = sendToChannel(self->game, chname, message, &dstlp, &chan);
625
626 if (result) {
627 lua_pushnil( L );
628 lua_pushstring( L, result );
629 return 2;
630 }
631
632 if ( dstlp == NULL ) {
633
634 if ( self != NULL ) {
635 self->status = LUAPROC_STAT_BLOCKED_SEND;
636 self->chan = chan;
637 }
638 451
639 /* just yield the lua process, channel unlocking will be done by the scheduler */ 452 if (result)
640 return lua_yield( L, lua_gettop( L )); 453 {
641 } 454 lua_pushnil(L);
455 lua_pushstring(L, result);
456 return 2;
457 }
642 458
643 lua_pushboolean( L, TRUE ); 459 lua_pushboolean(L, TRUE);
644 return 1; 460 return 1;
645} 461}
646 462
647/* receive a message from a lua process */ 463/* receive a message from a lua process */
648static int luaproc_receive( lua_State *L ) { 464static int luaproc_receive(lua_State *L)
649 465{
650 channel chan; 466 script *self;
651 script *srclp, *self; 467 const char *chname = luaL_checkstring(L, 1);
652 const char *chname = luaL_checkstring( L, 1 ); 468 scriptMessage *msg;
653 scriptMessage *msg;
654
655 // First check if there are queued messages, and grab one.
656 self = luaproc_getself(L);
657 if ((msg = (scriptMessage *) eina_clist_head(&(self->messages))))
658 {
659 eina_clist_remove(&(msg->node));
660 lua_pushstring(L, msg->message);
661 free(msg);
662 return lua_gettop(L) - 1;
663 }
664
665 /* get exclusive access to operate on channels */
666 pthread_mutex_lock( &mutex_channel );
667
668 /* wait until channel is not in use */
669 while((( chan = eina_hash_find(channels, chname)) != NULL ) && ( pthread_mutex_trylock(chan->mutex) != 0 )) {
670 pthread_cond_wait(chan->in_use, &mutex_channel );
671 }
672
673 /* free access to operate on channels */
674 pthread_mutex_unlock( &mutex_channel );
675
676 /* if channel is not found, free access to operate on channels and return an error to Lua */
677 if ( chan == NULL ) {
678 lua_pushnil( L );
679 lua_pushstring( L, "non-existent channel" );
680 return 2;
681 }
682
683 /* try to find a matching sender */
684 srclp = luaproc_dequeue_sender( chan );
685
686 /* if a match is found, get values from it and (queue) wake it */
687 if ( srclp != NULL ) {
688
689 /* move values between Lua states' stacks */
690 luaproc_movevalues( srclp->L, L );
691
692 /* return to sender indicanting message was sent */
693 lua_pushboolean( srclp->L, TRUE );
694 srclp->args = 1;
695
696 if ( sched_queue_proc( srclp ) != LUAPROC_SCHED_QUEUE_PROC_OK ) {
697
698 /* unlock channel access */
699 luaproc_unlock_channel( chan );
700
701 /* decrease active luaproc count */
702 sched_lpcount_dec();
703
704 /* close lua_State */
705 lua_close( srclp->L );
706 lua_pushnil( L );
707 lua_pushstring( L, "error scheduling process" );
708 return 2;
709 }
710
711 /* unlock channel access */
712 luaproc_unlock_channel( chan );
713
714 return lua_gettop( L ) - 1;
715 }
716
717 /* otherwise queue (block) the receiving process (sync) or return immediatly (async) */
718 else {
719
720 /* if trying an asynchronous receive, unlock channel access and return an error */
721 if ( lua_toboolean( L, 2 )) {
722 /* unlock channel access */
723 luaproc_unlock_channel( chan );
724 /* return an error */
725 lua_pushnil( L );
726 lua_pushfstring( L, "no senders waiting on channel %s", chname );
727 return 2;
728 }
729
730 /* otherwise (synchronous receive) simply block process */
731 else {
732 469
733 if ( self != NULL ) { 470 // First check if there are queued messages, and grab one.
734 self->status = LUAPROC_STAT_BLOCKED_RECV; 471 self = luaproc_getself(L);
735 self->chan = chan; 472 if ((msg = (scriptMessage *) eina_clist_head(&(self->messages))))
736 } 473 {
474 eina_clist_remove(&(msg->node));
475 lua_pushstring(L, msg->message);
476 free(msg);
477 return lua_gettop(L) - 1;
478 }
737 479
738 /* just yield the lua process, channel unlocking will be done by the scheduler */ 480 /* if trying an asynchronous receive, return an error */
739 return lua_yield( L, lua_gettop( L )); 481 if ( lua_toboolean( L, 2 ))
740 } 482 {
741 } 483 lua_pushnil(L);
484 lua_pushfstring(L, "no senders waiting on channel %s", chname);
485 return 2;
486 }
487 /* otherwise (synchronous receive) simply block process */
488 self->status = LUAPROC_STAT_BLOCKED_RECV;
489 return lua_yield(L, lua_gettop(L));
742} 490}
743 491
744void luaprocInit(void) 492void luaprocInit(void)
745{ 493{
746 eina_clist_init(&recyclelp); 494 eina_clist_init(&recyclelp);
747
748 int tid;
749 pthread_t worker;
750
751 eina_clist_init(&lpready); 495 eina_clist_init(&lpready);
752 channels = eina_hash_string_superfast_new(NULL);
753
754 /* create initial worker threads */
755 for (tid = 0; tid < LUAPROC_SCHED_DEFAULT_WORKER_THREADS; tid++)
756 {
757 pthread_create( &worker, NULL, workermain, NULL);
758 }
759} 496}
diff --git a/LuaSL/src/LuaSL_threads.h b/LuaSL/src/LuaSL_threads.h
index b7f6449..78c6639 100644
--- a/LuaSL/src/LuaSL_threads.h
+++ b/LuaSL/src/LuaSL_threads.h
@@ -43,17 +43,10 @@ THE SOFTWARE.
43#define LUAPROC_SCHED_INIT_ERROR -7 43#define LUAPROC_SCHED_INIT_ERROR -7
44 44
45 45
46/* message channel pointer type */
47typedef struct stchannel *channel;
48
49
50void luaprocInit(void); 46void luaprocInit(void);
51
52/* create a new worker pthread */
53int sched_create_worker(void); 47int sched_create_worker(void);
54
55void newProc(const char *code, int file, script *lp); 48void newProc(const char *code, int file, script *lp);
56const char *sendToChannel(gameGlobals *game, const char *chname, const char *message, script **dst, channel *chn); 49const char *sendToChannel(gameGlobals *game, const char *SID, const char *message);
57 50
58/* join all worker threads and exit */ 51/* join all worker threads and exit */
59void sched_join_workerthreads(void); 52void sched_join_workerthreads(void);