aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/LuaSL/src/LuaSL_threads.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--LuaSL/src/LuaSL_threads.c733
1 files changed, 212 insertions, 521 deletions
diff --git a/LuaSL/src/LuaSL_threads.c b/LuaSL/src/LuaSL_threads.c
index a15b506..a8a1681 100644
--- a/LuaSL/src/LuaSL_threads.c
+++ b/LuaSL/src/LuaSL_threads.c
@@ -32,42 +32,47 @@ THE SOFTWARE.
32 32
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 * Use ecore threads instead of raw pthreads.
36 * Ecore threads pretty much wraps pthreads on posix, but has Windows support to.
37 * In general use EFL where it is useful. 35 * In general use EFL where it is useful.
38 * One fixed unique message channel per script. 36 * One fixed unique message channel per script.
39 * Probably one fixed unique message channel per object, which each script in the object shares.
40 * But might be better to handle that C side anyway.
41 * No need for channel.c / .h, we are not using that sort of arbitrary channels. 37 * No need for channel.c / .h, we are not using that sort of arbitrary channels.
42 * FIFO queue on message channels, seems the C socket queue is not enough. 38 * FIFO queue on message channels, seems the C socket queue is not enough.
43 * On the other hand, could just peel messages of the socket queue, then shove them on the scripts queue. 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.
41 * But might be better to handle that C side anyway.
44 * Better integration with LuaSL. 42 * Better integration with LuaSL.
45 * Merge the luaproc structure with the script structure. 43 * Merge the luaproc structure with the script structure.
44 * Use ecore threads instead of raw pthreads.
45 * 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. 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.
47 * Get rid of luaproc.lua, should not need it.
48 * Use my coding standards, or EFL ones. Pffft. 47 * Use my coding standards, or EFL ones. Pffft.
49 * 48 *
50 */ 49 */
51 50
52#include "LuaSL.h" 51#include "LuaSL.h"
53 52
54#include <netdb.h>
55#include <pthread.h>
56#include <string.h>
57#include <arpa/inet.h>
58#include <sys/select.h>
59#include <sys/socket.h>
60 53
54#define CHANNEL_MAX_NAME_LENGTH 255
61 55
62/********* 56#define CHANNEL_DESTROYED 0
63* globals
64*********/
65 57
66/* global channel lua_State mutex */ 58/* ready process queue insertion status */
67pthread_mutex_t mutex_channel_lstate = PTHREAD_MUTEX_INITIALIZER; 59#define LUAPROC_SCHED_QUEUE_PROC_OK 0
60#define LUAPROC_SCHED_QUEUE_PROC_ERR -1
61
62/* scheduler default number of worker threads */
63#define LUAPROC_SCHED_DEFAULT_WORKER_THREADS 1
64
65/* process is idle */
66#define LUAPROC_STAT_IDLE 0
67/* process is ready to run */
68#define LUAPROC_STAT_READY 1
69/* process is blocked on send */
70#define LUAPROC_STAT_BLOCKED_SEND 2
71/* process is blocked on receive */
72#define LUAPROC_STAT_BLOCKED_RECV 3
73/* process is finished */
74#define LUAPROC_STAT_FINISHED 4
68 75
69/* global lua_State where channel hash table will be stored */
70lua_State *chanls = NULL;
71 76
72/* message channel */ 77/* message channel */
73struct stchannel { 78struct stchannel {
@@ -77,7 +82,26 @@ struct stchannel {
77 pthread_cond_t *in_use; 82 pthread_cond_t *in_use;
78}; 83};
79 84
85/* lua process */
86struct stluaproc {
87 Eina_Clist node;
88 lua_State *lstate;
89 int stat;
90 int args;
91 channel chan;
92 void *data;
93};
94
95
96/*********
97* globals
98*********/
99
100/* global channel lua_State mutex */
101pthread_mutex_t mutex_channel_lstate = PTHREAD_MUTEX_INITIALIZER;
80 102
103/* global lua_State where channel hash table will be stored */
104lua_State *chanls = NULL;
81 105
82/* ready process list */ 106/* ready process list */
83Eina_Clist lpready; 107Eina_Clist lpready;
@@ -100,8 +124,6 @@ int lpcount = 0;
100/* no more lua processes flag */ 124/* no more lua processes flag */
101int no_more_processes = FALSE; 125int no_more_processes = FALSE;
102 126
103
104
105/* channel operations mutex */ 127/* channel operations mutex */
106pthread_mutex_t mutex_channel = PTHREAD_MUTEX_INITIALIZER; 128pthread_mutex_t mutex_channel = PTHREAD_MUTEX_INITIALIZER;
107 129
@@ -114,65 +136,30 @@ Eina_Clist recyclelp;
114/* maximum lua processes to recycle */ 136/* maximum lua processes to recycle */
115int recyclemax = 0; 137int recyclemax = 0;
116 138
117/* lua process */
118struct stluaproc {
119 Eina_Clist node;
120 lua_State *lstate;
121 int stat;
122 int args;
123 channel chan;
124 int destroyworker;
125 void *data;
126 Ecore_Cb callback;
127};
128
129
130 139
131/****************************** 140/******************************
132* library functions prototypes 141* library functions prototypes
133******************************/ 142******************************/
134/* create a new lua process */
135static int luaproc_create_newproc( lua_State *L );
136/* send a message to a lua process */ 143/* send a message to a lua process */
137static int luaproc_send( lua_State *L ); 144static int luaproc_send( lua_State *L );
138/* receive a message from a lua process */ 145/* receive a message from a lua process */
139static int luaproc_receive( lua_State *L ); 146static int luaproc_receive( lua_State *L );
140/* create a new channel */ 147/* create a new channel */
141static int luaproc_create_channel( lua_State *L ); 148static int luaproc_create_channel( lua_State *L );
142/* destroy a channel */
143static int luaproc_destroy_channel( lua_State *L );
144/* wait until all luaprocs have finished and exit */
145static int luaproc_exit( lua_State *L );
146/* create a new worker */
147static int luaproc_create_worker( lua_State *L );
148/* destroy a worker */
149static int luaproc_destroy_worker( lua_State *L );
150/* set amount of lua processes that should be recycled (ie, reused) */
151static int luaproc_recycle_set( lua_State *L );
152/* send a message back to the main loop */ 149/* send a message back to the main loop */
153static int luaproc_send_back( lua_State *L ); 150static int luaproc_send_back( lua_State *L );
154 151
155/* luaproc function registration array - main (parent) functions */ 152/* luaproc function registration array - main (parent) functions */
156static const struct luaL_reg luaproc_funcs_parent[] = { 153static const struct luaL_reg luaproc_funcs_parent[] = {
157 { "newproc", luaproc_create_newproc },
158 { "exit", luaproc_exit },
159 { "createworker", luaproc_create_worker },
160 { "destroyworker", luaproc_destroy_worker },
161 { "recycle", luaproc_recycle_set },
162 { "sendback", luaproc_send_back }, 154 { "sendback", luaproc_send_back },
163 { NULL, NULL } 155 { NULL, NULL }
164}; 156};
165 157
166/* luaproc function registration array - newproc (child) functions */ 158/* luaproc function registration array - newproc (child) functions */
167static const struct luaL_reg luaproc_funcs_child[] = { 159static const struct luaL_reg luaproc_funcs_child[] = {
168 { "newproc", luaproc_create_newproc },
169 { "send", luaproc_send }, 160 { "send", luaproc_send },
170 { "receive", luaproc_receive }, 161 { "receive", luaproc_receive },
171 { "newchannel", luaproc_create_channel }, 162 { "newchannel", luaproc_create_channel },
172 { "delchannel", luaproc_destroy_channel },
173 { "createworker", luaproc_create_worker },
174 { "destroyworker", luaproc_destroy_worker },
175 { "recycle", luaproc_recycle_set },
176 { "sendback", luaproc_send_back }, 163 { "sendback", luaproc_send_back },
177 { NULL, NULL } 164 { NULL, NULL }
178}; 165};
@@ -181,14 +168,14 @@ static const struct luaL_reg luaproc_funcs_child[] = {
181 168
182 169
183/* initialize channel table */ 170/* initialize channel table */
184void channel_init( void ) { 171static void channel_init( void ) {
185 chanls = luaL_newstate(); 172 chanls = luaL_newstate();
186 lua_newtable( chanls ); 173 lua_newtable( chanls );
187 lua_setglobal( chanls, "channeltb" ); 174 lua_setglobal( chanls, "channeltb" );
188} 175}
189 176
190/* create new channel */ 177/* create new channel */
191channel channel_create( const char *cname ) { 178static channel channel_create( const char *cname ) {
192 179
193 channel chan; 180 channel chan;
194 181
@@ -214,26 +201,8 @@ channel channel_create( const char *cname ) {
214 return chan; 201 return chan;
215} 202}
216 203
217/* destroy a channel */
218int channel_destroy( channel chan, const char *chname ) {
219
220 /* get exclusive access to the channel table */
221 pthread_mutex_lock( &mutex_channel_lstate );
222
223 lua_getglobal( chanls, "channeltb");
224 lua_pushstring( chanls, chname );
225 lua_pushnil( chanls );
226 lua_settable( chanls, -3 );
227 lua_pop( chanls, 1 );
228
229 /* let others access the channel table */
230 pthread_mutex_unlock( &mutex_channel_lstate );
231
232 return CHANNEL_DESTROYED;
233}
234
235/* search for and return a channel with a given name */ 204/* search for and return a channel with a given name */
236channel channel_search( const char *cname ) { 205static channel channel_search( const char *cname ) {
237 206
238 channel chan; 207 channel chan;
239 208
@@ -257,34 +226,187 @@ channel channel_search( const char *cname ) {
257} 226}
258 227
259/* return a channel's send queue */ 228/* return a channel's send queue */
260Eina_Clist *channel_get_sendq( channel chan ) { 229static Eina_Clist *channel_get_sendq( channel chan ) {
261 return &chan->send; 230 return &chan->send;
262} 231}
263 232
264/* return a channel's receive queue */ 233/* return a channel's receive queue */
265Eina_Clist *channel_get_recvq( channel chan ) { 234static Eina_Clist *channel_get_recvq( channel chan ) {
266 return &chan->recv; 235 return &chan->recv;
267} 236}
268 237
269/* return a channel's mutex */ 238/* return a channel's mutex */
270pthread_mutex_t *channel_get_mutex( channel chan ) { 239static pthread_mutex_t *channel_get_mutex( channel chan ) {
271 return chan->mutex; 240 return chan->mutex;
272} 241}
273 242
274/* return a channel's conditional variable */ 243/* return a channel's conditional variable */
275pthread_cond_t *channel_get_cond( channel chan ) { 244static pthread_cond_t *channel_get_cond( channel chan ) {
276 return chan->in_use; 245 return chan->in_use;
277} 246}
278 247
279 248
280 249
250/* return status (boolean) indicating if lua process should be recycled */
251static luaproc luaproc_recycle_pop( void ) {
252
253 luaproc lp;
254
255 /* get exclusive access to operate on recycle list */
256 pthread_mutex_lock( &mutex_recycle_list );
257
258 /* check if there are any lua processes on recycle list */
259 if ( eina_clist_count( &recyclelp ) > 0 ) {
260 /* pop list head */
261 if ((lp = (luaproc) eina_clist_head(&recyclelp)))
262 eina_clist_remove(&(lp->node));
263 /* free access to operate on recycle list */
264 pthread_mutex_unlock( &mutex_recycle_list );
265 /* return associated luaproc */
266 return lp;
267 }
268
269 /* free access to operate on recycle list */
270 pthread_mutex_unlock( &mutex_recycle_list );
271
272 /* if no lua processes are available simply return null */
273 return NULL;
274}
275
276/* check if lua process should be recycled and, in case so, add it to the recycle list */
277static int luaproc_recycle_push( luaproc lp ) {
278
279 /* get exclusive access to operate on recycle list */
280 pthread_mutex_lock( &mutex_recycle_list );
281
282 /* check if amount of lua processes currently on recycle list is greater than
283 or equal to the maximum amount of lua processes that should be recycled */
284 if ( eina_clist_count( &recyclelp ) >= recyclemax ) {
285 /* free access to operate on recycle list */
286 pthread_mutex_unlock( &mutex_recycle_list );
287 /* if so, lua process should NOT be recycled and should be destroyed */
288 return FALSE;
289 }
290 /* otherwise, lua process should be added to recycle list */
291 eina_clist_add_tail( &recyclelp, &(lp->node) );
292 /* free access to operate on recycle list */
293 pthread_mutex_unlock( &mutex_recycle_list );
294 /* since lua process will be recycled, it should not be destroyed */
295 return TRUE;
296}
297
298/* queue a lua process sending a message without a matching receiver */
299static void luaproc_queue_sender( luaproc lp ) {
300 /* add the sending process to this process' send queue */
301 eina_clist_add_tail( channel_get_sendq( lp->chan ), &(lp->node));
302}
303
304/* dequeue a lua process sending a message with a receiver match */
305static luaproc luaproc_dequeue_sender( channel chan ) {
306
307 luaproc lp;
308
309 if ( eina_clist_count( channel_get_sendq( chan )) > 0 ) {
310 /* get first node from channel's send queue */
311 if ((lp = (luaproc) eina_clist_head(channel_get_sendq( chan ))))
312 eina_clist_remove(&(lp->node));
313 /* return associated luaproc */
314 return lp;
315 }
316
317 return NULL;
318}
319
320/* queue a luc process receiving a message without a matching sender */
321static void luaproc_queue_receiver( luaproc lp ) {
322 /* add the receiving process to this process' receive queue */
323 eina_clist_add_tail( channel_get_recvq( lp->chan ), &(lp->node));
324}
325
326/* dequeue a lua process receiving a message with a sender match */
327static luaproc luaproc_dequeue_receiver( channel chan ) {
328
329 luaproc lp;
330
331 if ( eina_clist_count( channel_get_recvq( chan )) > 0 ) {
332 /* get first node from channel's recv queue */
333 if ((lp = (luaproc) eina_clist_head(channel_get_recvq( chan ))))
334 eina_clist_remove(&(lp->node));
335 /* return associated luaproc */
336 return lp;
337 }
338
339 return NULL;
340}
341
342/* return a process' status */
343static int luaproc_get_status( luaproc lp ) {
344 return lp->stat;
345}
346
347/* set a process' status */
348static void luaproc_set_status( luaproc lp, int status ) {
349 lp->stat = status;
350}
351
352/* return a process' state */
353static lua_State *luaproc_get_state( luaproc lp ) {
354 return lp->lstate;
355}
356
357/* return the number of arguments expected by a given process */
358static int luaproc_get_args( luaproc lp ) {
359 return lp->args;
360}
361
362/* set the number of arguments expected by a given process */
363static void luaproc_set_args( luaproc lp, int n ) {
364 lp->args = n;
365}
366
367
368/* return the channel where the corresponding luaproc is blocked at */
369static channel luaproc_get_channel( luaproc lp ) {
370 return lp->chan;
371}
372
373/* unlock access to a channel */
374static void luaproc_unlock_channel( channel chan ) {
375 /* get exclusive access to operate on channels */
376 pthread_mutex_lock( &mutex_channel );
377 /* unlock channel access */
378 pthread_mutex_unlock( channel_get_mutex( chan ));
379 /* signal channel not in use */
380 pthread_cond_signal( channel_get_cond( chan ));
381 /* free access to operate on channels */
382 pthread_mutex_unlock( &mutex_channel );
383}
384
385
386
387/* increase active lua process count */
388static void sched_lpcount_inc( void ) {
389 pthread_mutex_lock( &mutex_lp_count );
390 lpcount++;
391 pthread_mutex_unlock( &mutex_lp_count );
392}
393
394/* decrease active lua process count */
395static void sched_lpcount_dec( void ) {
396 pthread_mutex_lock( &mutex_lp_count );
397 lpcount--;
398 /* if count reaches zero, signal there are no more active processes */
399 if ( lpcount == 0 ) {
400 pthread_cond_signal( &cond_no_active_lp );
401 }
402 pthread_mutex_unlock( &mutex_lp_count );
403}
281 404
282/* worker thread main function */ 405/* worker thread main function */
283void *workermain( void *args ) { 406static void *workermain( void *args ) {
284 407
285 luaproc lp; 408 luaproc lp;
286 int procstat; 409 int procstat;
287 int destroyworker;
288 410
289 /* detach thread so resources are freed as soon as thread exits (no further joining) */ 411 /* detach thread so resources are freed as soon as thread exits (no further joining) */
290 pthread_detach( pthread_self( )); 412 pthread_detach( pthread_self( ));
@@ -322,9 +444,6 @@ void *workermain( void *args ) {
322 /* check if process finished its whole execution */ 444 /* check if process finished its whole execution */
323 if ( procstat == 0 ) { 445 if ( procstat == 0 ) {
324 446
325 /* check if worker thread should be destroyed */
326 destroyworker = luaproc_get_destroyworker( lp );
327
328 /* set process status to finished */ 447 /* set process status to finished */
329 luaproc_set_status( lp, LUAPROC_STAT_FINISHED ); 448 luaproc_set_status( lp, LUAPROC_STAT_FINISHED );
330 449
@@ -336,11 +455,6 @@ void *workermain( void *args ) {
336 /* decrease active lua process count */ 455 /* decrease active lua process count */
337 sched_lpcount_dec(); 456 sched_lpcount_dec();
338 457
339 /* check if thread should be finished after lua process conclusion */
340 if ( destroyworker ) {
341 /* if so, finish thread */
342 pthread_exit( NULL );
343 }
344 } 458 }
345 459
346 /* check if process yielded */ 460 /* check if process yielded */
@@ -385,14 +499,13 @@ void *workermain( void *args ) {
385} 499}
386 500
387/* local scheduler initialization */ 501/* local scheduler initialization */
388int sched_init_local( int numworkers ) { 502static int sched_init_local( int numworkers ) {
389 503
390 int tid; 504 int tid;
391 int workercount = 0; 505 int workercount = 0;
392 pthread_t worker; 506 pthread_t worker;
393 507
394 /* initialize ready process list */ 508 /* initialize ready process list */
395// lpready = list_new();
396 eina_clist_init(&lpready); 509 eina_clist_init(&lpready);
397 510
398 /* initialize channels */ 511 /* initialize channels */
@@ -412,17 +525,8 @@ int sched_init_local( int numworkers ) {
412 return LUAPROC_SCHED_OK; 525 return LUAPROC_SCHED_OK;
413} 526}
414 527
415/* exit scheduler */
416void sched_exit( void ) {
417
418 /* get exclusive access to the ready process queue */
419 pthread_mutex_lock( &mutex_queue_access );
420 /* free access to the process ready queue */
421 pthread_mutex_unlock( &mutex_queue_access );
422}
423
424/* move process to ready queue (ie, schedule process) */ 528/* move process to ready queue (ie, schedule process) */
425int sched_queue_proc( luaproc lp ) { 529static int sched_queue_proc( luaproc lp ) {
426 530
427 /* get exclusive access to the ready process queue */ 531 /* get exclusive access to the ready process queue */
428 pthread_mutex_lock( &mutex_queue_access ); 532 pthread_mutex_lock( &mutex_queue_access );
@@ -467,24 +571,6 @@ void sched_join_workerthreads( void ) {
467 571
468} 572}
469 573
470/* increase active lua process count */
471void sched_lpcount_inc( void ) {
472 pthread_mutex_lock( &mutex_lp_count );
473 lpcount++;
474 pthread_mutex_unlock( &mutex_lp_count );
475}
476
477/* decrease active lua process count */
478void sched_lpcount_dec( void ) {
479 pthread_mutex_lock( &mutex_lp_count );
480 lpcount--;
481 /* if count reaches zero, signal there are no more active processes */
482 if ( lpcount == 0 ) {
483 pthread_cond_signal( &cond_no_active_lp );
484 }
485 pthread_mutex_unlock( &mutex_lp_count );
486}
487
488/* create a new worker pthread */ 574/* create a new worker pthread */
489int sched_create_worker( void ) { 575int sched_create_worker( void ) {
490 576
@@ -498,80 +584,10 @@ int sched_create_worker( void ) {
498 return LUAPROC_SCHED_OK; 584 return LUAPROC_SCHED_OK;
499} 585}
500 586
501
502
503
504/*
505static void registerlib( lua_State *L, const char *name, lua_CFunction f ) {
506 lua_getglobal( L, "package" );
507 lua_getfield( L, -1, "preload" );
508 lua_pushcfunction( L, f );
509 lua_setfield( L, -2, name );
510 lua_pop( L, 2 );
511}
512*/
513static void openlibs( lua_State *L ) { 587static void openlibs( lua_State *L ) {
514/*
515 lua_cpcall( L, luaopen_base, NULL );
516 lua_cpcall( L, luaopen_package, NULL );
517 registerlib( L, "io", luaopen_io );
518 registerlib( L, "os", luaopen_os );
519 registerlib( L, "table", luaopen_table );
520 registerlib( L, "string", luaopen_string );
521 registerlib( L, "math", luaopen_math );
522 registerlib( L, "debug", luaopen_debug );
523*/
524 luaL_openlibs(L); 588 luaL_openlibs(L);
525} 589}
526 590
527/* return status (boolean) indicating if lua process should be recycled */
528luaproc luaproc_recycle_pop( void ) {
529
530 luaproc lp;
531
532 /* get exclusive access to operate on recycle list */
533 pthread_mutex_lock( &mutex_recycle_list );
534
535 /* check if there are any lua processes on recycle list */
536 if ( eina_clist_count( &recyclelp ) > 0 ) {
537 /* pop list head */
538 if ((lp = (luaproc) eina_clist_head(&recyclelp)))
539 eina_clist_remove(&(lp->node));
540 /* free access to operate on recycle list */
541 pthread_mutex_unlock( &mutex_recycle_list );
542 /* return associated luaproc */
543 return lp;
544 }
545
546 /* free access to operate on recycle list */
547 pthread_mutex_unlock( &mutex_recycle_list );
548
549 /* if no lua processes are available simply return null */
550 return NULL;
551}
552
553/* check if lua process should be recycled and, in case so, add it to the recycle list */
554int luaproc_recycle_push( luaproc lp ) {
555
556 /* get exclusive access to operate on recycle list */
557 pthread_mutex_lock( &mutex_recycle_list );
558
559 /* check if amount of lua processes currently on recycle list is greater than
560 or equal to the maximum amount of lua processes that should be recycled */
561 if ( eina_clist_count( &recyclelp ) >= recyclemax ) {
562 /* free access to operate on recycle list */
563 pthread_mutex_unlock( &mutex_recycle_list );
564 /* if so, lua process should NOT be recycled and should be destroyed */
565 return FALSE;
566 }
567 /* otherwise, lua process should be added to recycle list */
568 eina_clist_add_tail( &recyclelp, &(lp->node) );
569 /* free access to operate on recycle list */
570 pthread_mutex_unlock( &mutex_recycle_list );
571 /* since lua process will be recycled, it should not be destroyed */
572 return TRUE;
573}
574
575/* create new luaproc */ 591/* create new luaproc */
576static luaproc luaproc_new( const char *code, int destroyflag, int file) { 592static luaproc luaproc_new( const char *code, int destroyflag, int file) {
577 593
@@ -588,7 +604,6 @@ static luaproc luaproc_new( const char *code, int destroyflag, int file) {
588 lp->stat = LUAPROC_STAT_IDLE; 604 lp->stat = LUAPROC_STAT_IDLE;
589 lp->args = 0; 605 lp->args = 0;
590 lp->chan = NULL; 606 lp->chan = NULL;
591 lp->destroyworker = destroyflag;
592 607
593 /* load standard libraries */ 608 /* load standard libraries */
594 openlibs( lpst ); 609 openlibs( lpst );
@@ -611,99 +626,6 @@ static luaproc luaproc_new( const char *code, int destroyflag, int file) {
611 return lp; 626 return lp;
612} 627}
613 628
614/* synchronize worker threads and exit */
615static int luaproc_exit( lua_State *L ) {
616 sched_join_workerthreads();
617 return 0;
618}
619
620/* create a new worker pthread */
621static int luaproc_create_worker( lua_State *L ) {
622
623 if ( sched_create_worker( ) != LUAPROC_SCHED_OK ) {
624 lua_pushnil( L );
625 lua_pushstring( L, "error creating worker" );
626 return 2;
627 }
628
629 lua_pushboolean( L, TRUE );
630 return 1;
631}
632
633/* set amount of lua processes that should be recycled (ie, reused) */
634static int luaproc_recycle_set( lua_State *L ) {
635
636 luaproc lp;
637 int max = luaL_checkint( L, 1 );
638
639 /* check if function argument represents a reasonable value */
640 if ( max < 0 ) {
641 /* in case of errors return nil + error msg */
642 lua_pushnil( L );
643 lua_pushstring( L, "error setting recycle limit to negative value" );
644 return 2;
645 }
646
647 /* get exclusive access to operate on recycle list */
648 pthread_mutex_lock( &mutex_recycle_list );
649
650 /* set maximum lua processes that should be recycled */
651 recyclemax = max;
652
653 /* destroy recycle list excessive nodes (and corresponding lua processes) */
654 while ( eina_clist_count( &recyclelp ) > max ) {
655 if ((lp = (luaproc) eina_clist_head(&recyclelp)))
656 eina_clist_remove(&(lp->node));
657 /* close associated lua_State */
658 lua_close( lp->lstate );
659 }
660
661 /* free access to operate on recycle list */
662 pthread_mutex_unlock( &mutex_recycle_list );
663
664 lua_pushboolean( L, TRUE );
665 return 1;
666}
667
668
669/* destroy a worker pthread */
670static int luaproc_destroy_worker( lua_State *L ) {
671
672 /* new lua process pointer */
673 luaproc lp;
674
675 /* create new lua process with empty code and destroy worker flag set to true
676 (ie, conclusion of lua process WILL result in worker thread destruction */
677 lp = luaproc_new( "", TRUE, FALSE );
678
679 /* ensure process creation was successfull */
680 if ( lp == NULL ) {
681 /* in case of errors return nil + error msg */
682 lua_pushnil( L );
683 lua_pushstring( L, "error destroying worker" );
684 return 2;
685 }
686
687 /* increase active luaproc count */
688 sched_lpcount_inc();
689
690 /* schedule luaproc */
691 if ( sched_queue_proc( lp ) != LUAPROC_SCHED_QUEUE_PROC_OK ) {
692 printf( "[luaproc] error queueing Lua process\n" );
693 /* decrease active luaproc count */
694 sched_lpcount_dec();
695 /* close lua_State */
696 lua_close( lp->lstate );
697 /* return nil + error msg */
698 lua_pushnil( L );
699 lua_pushstring( L, "error destroying worker" );
700 return 2;
701 }
702
703 lua_pushboolean( L, TRUE );
704 return 1;
705}
706
707/* recycle a lua process */ 629/* recycle a lua process */
708static luaproc luaproc_recycle( luaproc lp, const char *code, int file ) { 630static luaproc luaproc_recycle( luaproc lp, const char *code, int file ) {
709 631
@@ -713,7 +635,6 @@ static luaproc luaproc_recycle( luaproc lp, const char *code, int file ) {
713 lp->stat = LUAPROC_STAT_IDLE; 635 lp->stat = LUAPROC_STAT_IDLE;
714 lp->args = 0; 636 lp->args = 0;
715 lp->chan = NULL; 637 lp->chan = NULL;
716 lp->destroyworker = FALSE;
717 638
718 /* load process' code */ 639 /* load process' code */
719 ret = luaL_loadstring( lp->lstate, code ); 640 ret = luaL_loadstring( lp->lstate, code );
@@ -728,8 +649,7 @@ static luaproc luaproc_recycle( luaproc lp, const char *code, int file ) {
728 return lp; 649 return lp;
729} 650}
730 651
731 652int newProc(const char *code, int file, void *data)
732int newProc(const char *code, int file, Ecore_Cb callback, void *data)
733{ 653{
734 /* new lua process pointer */ 654 /* new lua process pointer */
735 luaproc lp; 655 luaproc lp;
@@ -753,9 +673,8 @@ int newProc(const char *code, int file, Ecore_Cb callback, void *data)
753 return 1; 673 return 1;
754 } 674 }
755 675
756 /* Stash any data and callback given to us. */ 676 /* Stash any data given to us. */
757 lp->data = data; 677 lp->data = data;
758 lp->callback = callback;
759 678
760 /* increase active luaproc count */ 679 /* increase active luaproc count */
761 sched_lpcount_inc(); 680 sched_lpcount_inc();
@@ -773,76 +692,8 @@ int newProc(const char *code, int file, Ecore_Cb callback, void *data)
773 return 0; 692 return 0;
774} 693}
775 694
776/* create and schedule a new lua process (luaproc.newproc) */
777static int luaproc_create_newproc( lua_State *L ) {
778
779 /* check if first argument is a string (lua code) */
780 const char *code = luaL_checkstring( L, 1 );
781
782 switch (newProc(code, FALSE, NULL, NULL))
783 {
784 case 1 :
785 /* in case of errors return nil + error msg */
786 lua_pushnil( L );
787 lua_pushstring( L, "error loading code string" );
788 return 2;
789 case 2 :
790 /* return nil + error msg */
791 lua_pushnil( L );
792 lua_pushstring( L, "error queuing process" );
793 return 2;
794 }
795
796 lua_pushboolean( L, TRUE );
797 return 1;
798}
799
800/* queue a lua process sending a message without a matching receiver */
801void luaproc_queue_sender( luaproc lp ) {
802 /* add the sending process to this process' send queue */
803 eina_clist_add_tail( channel_get_sendq( lp->chan ), &(lp->node));
804}
805
806/* dequeue a lua process sending a message with a receiver match */
807luaproc luaproc_dequeue_sender( channel chan ) {
808
809 luaproc lp;
810
811 if ( eina_clist_count( channel_get_sendq( chan )) > 0 ) {
812 /* get first node from channel's send queue */
813 if ((lp = (luaproc) eina_clist_head(channel_get_sendq( chan ))))
814 eina_clist_remove(&(lp->node));
815 /* return associated luaproc */
816 return lp;
817 }
818
819 return NULL;
820}
821
822/* queue a luc process receiving a message without a matching sender */
823void luaproc_queue_receiver( luaproc lp ) {
824 /* add the receiving process to this process' receive queue */
825 eina_clist_add_tail( channel_get_recvq( lp->chan ), &(lp->node));
826}
827
828/* dequeue a lua process receiving a message with a sender match */
829luaproc luaproc_dequeue_receiver( channel chan ) {
830
831 luaproc lp;
832
833 if ( eina_clist_count( channel_get_recvq( chan )) > 0 ) {
834 /* get first node from channel's recv queue */
835 if ((lp = (luaproc) eina_clist_head(channel_get_recvq( chan ))))
836 eina_clist_remove(&(lp->node));
837 /* return associated luaproc */
838 return lp;
839 }
840
841 return NULL;
842}
843
844/* moves values between lua states' stacks */ 695/* moves values between lua states' stacks */
845void luaproc_movevalues( lua_State *Lfrom, lua_State *Lto ) { 696static void luaproc_movevalues( lua_State *Lfrom, lua_State *Lto ) {
846 697
847 int i; 698 int i;
848 int n = lua_gettop( Lfrom ); 699 int n = lua_gettop( Lfrom );
@@ -854,7 +705,7 @@ void luaproc_movevalues( lua_State *Lfrom, lua_State *Lto ) {
854} 705}
855 706
856/* return the lua process associated with a given lua state */ 707/* return the lua process associated with a given lua state */
857luaproc luaproc_getself( lua_State *L ) { 708static luaproc luaproc_getself( lua_State *L ) {
858 luaproc lp; 709 luaproc lp;
859 lua_getfield( L, LUA_REGISTRYINDEX, "_SELF" ); 710 lua_getfield( L, LUA_REGISTRYINDEX, "_SELF" );
860 lp = (luaproc )lua_touserdata( L, -1 ); 711 lp = (luaproc )lua_touserdata( L, -1 );
@@ -869,7 +720,7 @@ static int luaproc_send_back( lua_State *L ) {
869 const char *message = luaL_checkstring( L, 1 ); 720 const char *message = luaL_checkstring( L, 1 );
870 721
871 self = luaproc_getself( L ); 722 self = luaproc_getself( L );
872 if (self && self->callback && self->data) 723 if (self && self->data)
873 { 724 {
874 scriptMessage *sm = calloc(1, sizeof(scriptMessage)); 725 scriptMessage *sm = calloc(1, sizeof(scriptMessage));
875 726
@@ -877,7 +728,7 @@ static int luaproc_send_back( lua_State *L ) {
877 { 728 {
878 sm->script = self->data; 729 sm->script = self->data;
879 strcpy((char *) sm->message, message); 730 strcpy((char *) sm->message, message);
880 ecore_main_loop_thread_safe_call_async(self->callback, sm); 731 ecore_main_loop_thread_safe_call_async(scriptSendBack, sm);
881 } 732 }
882 } 733 }
883 734
@@ -1079,43 +930,6 @@ void luaprocInit(void)
1079 sched_init_local( LUAPROC_SCHED_DEFAULT_WORKER_THREADS ); 930 sched_init_local( LUAPROC_SCHED_DEFAULT_WORKER_THREADS );
1080} 931}
1081 932
1082void luaprocRegister(lua_State *L)
1083{
1084 /* register luaproc functions */
1085 luaL_register( L, "luaproc", luaproc_funcs_parent );
1086}
1087
1088LUALIB_API int luaopen_luaproc( lua_State *L ) {
1089 luaprocRegister(L);
1090 luaprocInit();
1091 return 0;
1092}
1093
1094/* return a process' status */
1095int luaproc_get_status( luaproc lp ) {
1096 return lp->stat;
1097}
1098
1099/* set a process' status */
1100void luaproc_set_status( luaproc lp, int status ) {
1101 lp->stat = status;
1102}
1103
1104/* return a process' state */
1105lua_State *luaproc_get_state( luaproc lp ) {
1106 return lp->lstate;
1107}
1108
1109/* return the number of arguments expected by a given process */
1110int luaproc_get_args( luaproc lp ) {
1111 return lp->args;
1112}
1113
1114/* set the number of arguments expected by a given process */
1115void luaproc_set_args( luaproc lp, int n ) {
1116 lp->args = n;
1117}
1118
1119/* create a new channel */ 933/* create a new channel */
1120static int luaproc_create_channel( lua_State *L ) { 934static int luaproc_create_channel( lua_State *L ) {
1121 935
@@ -1144,126 +958,3 @@ static int luaproc_create_channel( lua_State *L ) {
1144 return 1; 958 return 1;
1145 959
1146} 960}
1147
1148/* destroy a channel */
1149static int luaproc_destroy_channel( lua_State *L ) {
1150
1151 channel chan;
1152 luaproc lp;
1153 pthread_mutex_t *chmutex;
1154 pthread_cond_t *chcond;
1155 const char *chname = luaL_checkstring( L, 1 );
1156
1157
1158 /* get exclusive access to operate on channels */
1159 pthread_mutex_lock( &mutex_channel );
1160
1161 /* wait until channel is not in use */
1162 while((( chan = channel_search( chname )) != NULL ) && ( pthread_mutex_trylock( channel_get_mutex( chan )) != 0 )) {
1163 pthread_cond_wait( channel_get_cond( chan ), &mutex_channel );
1164 }
1165
1166 /* free access to operate on channels */
1167 pthread_mutex_unlock( &mutex_channel );
1168
1169 /* if channel is not found, return an error to Lua */
1170 if ( chan == NULL ) {
1171 lua_pushnil( L );
1172 lua_pushstring( L, "non-existent channel" );
1173 return 2;
1174 }
1175
1176 /* get channel's mutex and conditional pointers */
1177 chmutex = channel_get_mutex( chan );
1178 chcond = channel_get_cond( chan );
1179
1180 /* search for processes waiting to send a message on this channel */
1181 while (( lp = (luaproc) eina_clist_head( channel_get_sendq( chan ))) != NULL ) {
1182 eina_clist_remove(&(lp->node));
1183
1184 /* return an error so the processe knows the channel was destroyed before the message was sent */
1185 lua_settop( lp->lstate, 0 );
1186 lua_pushnil( lp->lstate );
1187 lua_pushstring( lp->lstate, "channel destroyed while waiting for receiver" );
1188 lp->args = 2;
1189
1190 /* schedule the process for execution */
1191 if ( sched_queue_proc( lp ) != LUAPROC_SCHED_QUEUE_PROC_OK ) {
1192
1193 /* decrease active luaproc count */
1194 sched_lpcount_dec();
1195
1196 /* close lua_State */
1197 lua_close( lp->lstate );
1198 }
1199 }
1200
1201 /* search for processes waiting to receive a message on this channel */
1202 while (( lp = (luaproc) eina_clist_head( channel_get_recvq( chan ))) != NULL ) {
1203 eina_clist_remove(&(lp->node));
1204
1205 /* return an error so the processe knows the channel was destroyed before the message was received */
1206 lua_settop( lp->lstate, 0 );
1207 lua_pushnil( lp->lstate );
1208 lua_pushstring( lp->lstate, "channel destroyed while waiting for sender" );
1209 lp->args = 2;
1210
1211 /* schedule the process for execution */
1212 if ( sched_queue_proc( lp ) != LUAPROC_SCHED_QUEUE_PROC_OK ) {
1213
1214 /* decrease active luaproc count */
1215 sched_lpcount_dec();
1216
1217 /* close lua_State */
1218 lua_close( lp->lstate );
1219 }
1220 }
1221
1222 /* get exclusive access to operate on channels */
1223 pthread_mutex_lock( &mutex_channel );
1224 /* destroy channel */
1225 channel_destroy( chan, chname );
1226 /* broadcast channel not in use */
1227 pthread_cond_broadcast( chcond );
1228 /* unlock channel access */
1229 pthread_mutex_unlock( chmutex );
1230 /* destroy channel mutex and conditional */
1231 pthread_mutex_destroy( chmutex );
1232 pthread_cond_destroy( chcond );
1233 /* free memory used by channel mutex and conditional */
1234 free( chmutex );
1235 free( chcond );
1236 /* free access to operate on channels */
1237 pthread_mutex_unlock( &mutex_channel );
1238
1239 lua_pushboolean( L, TRUE );
1240
1241 return 1;
1242}
1243
1244/* register luaproc's functions in a lua_State */
1245void luaproc_register_funcs( lua_State *L ) {
1246 luaL_register( L, "luaproc", luaproc_funcs_child );
1247}
1248
1249/* return the channel where the corresponding luaproc is blocked at */
1250channel luaproc_get_channel( luaproc lp ) {
1251 return lp->chan;
1252}
1253
1254/* unlock access to a channel */
1255void luaproc_unlock_channel( channel chan ) {
1256 /* get exclusive access to operate on channels */
1257 pthread_mutex_lock( &mutex_channel );
1258 /* unlock channel access */
1259 pthread_mutex_unlock( channel_get_mutex( chan ));
1260 /* signal channel not in use */
1261 pthread_cond_signal( channel_get_cond( chan ));
1262 /* free access to operate on channels */
1263 pthread_mutex_unlock( &mutex_channel );
1264}
1265
1266/* return status (boolean) indicating if worker thread should be destroyed after luaproc execution */
1267int luaproc_get_destroyworker( luaproc lp ) {
1268 return lp->destroyworker;
1269}