diff options
Diffstat (limited to '')
-rw-r--r-- | LuaSL/src/LuaSL_threads.c | 733 |
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 */ |
67 | pthread_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 */ | ||
70 | lua_State *chanls = NULL; | ||
71 | 76 | ||
72 | /* message channel */ | 77 | /* message channel */ |
73 | struct stchannel { | 78 | struct 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 */ | ||
86 | struct 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 */ | ||
101 | pthread_mutex_t mutex_channel_lstate = PTHREAD_MUTEX_INITIALIZER; | ||
80 | 102 | ||
103 | /* global lua_State where channel hash table will be stored */ | ||
104 | lua_State *chanls = NULL; | ||
81 | 105 | ||
82 | /* ready process list */ | 106 | /* ready process list */ |
83 | Eina_Clist lpready; | 107 | Eina_Clist lpready; |
@@ -100,8 +124,6 @@ int lpcount = 0; | |||
100 | /* no more lua processes flag */ | 124 | /* no more lua processes flag */ |
101 | int no_more_processes = FALSE; | 125 | int no_more_processes = FALSE; |
102 | 126 | ||
103 | |||
104 | |||
105 | /* channel operations mutex */ | 127 | /* channel operations mutex */ |
106 | pthread_mutex_t mutex_channel = PTHREAD_MUTEX_INITIALIZER; | 128 | pthread_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 */ |
115 | int recyclemax = 0; | 137 | int recyclemax = 0; |
116 | 138 | ||
117 | /* lua process */ | ||
118 | struct 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 */ | ||
135 | static int luaproc_create_newproc( lua_State *L ); | ||
136 | /* send a message to a lua process */ | 143 | /* send a message to a lua process */ |
137 | static int luaproc_send( lua_State *L ); | 144 | static int luaproc_send( lua_State *L ); |
138 | /* receive a message from a lua process */ | 145 | /* receive a message from a lua process */ |
139 | static int luaproc_receive( lua_State *L ); | 146 | static int luaproc_receive( lua_State *L ); |
140 | /* create a new channel */ | 147 | /* create a new channel */ |
141 | static int luaproc_create_channel( lua_State *L ); | 148 | static int luaproc_create_channel( lua_State *L ); |
142 | /* destroy a channel */ | ||
143 | static int luaproc_destroy_channel( lua_State *L ); | ||
144 | /* wait until all luaprocs have finished and exit */ | ||
145 | static int luaproc_exit( lua_State *L ); | ||
146 | /* create a new worker */ | ||
147 | static int luaproc_create_worker( lua_State *L ); | ||
148 | /* destroy a worker */ | ||
149 | static int luaproc_destroy_worker( lua_State *L ); | ||
150 | /* set amount of lua processes that should be recycled (ie, reused) */ | ||
151 | static 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 */ |
153 | static int luaproc_send_back( lua_State *L ); | 150 | static 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 */ |
156 | static const struct luaL_reg luaproc_funcs_parent[] = { | 153 | static 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 */ |
167 | static const struct luaL_reg luaproc_funcs_child[] = { | 159 | static 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 */ |
184 | void channel_init( void ) { | 171 | static 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 */ |
191 | channel channel_create( const char *cname ) { | 178 | static 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 */ | ||
218 | int 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 */ |
236 | channel channel_search( const char *cname ) { | 205 | static 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 */ |
260 | Eina_Clist *channel_get_sendq( channel chan ) { | 229 | static 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 */ |
265 | Eina_Clist *channel_get_recvq( channel chan ) { | 234 | static 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 */ |
270 | pthread_mutex_t *channel_get_mutex( channel chan ) { | 239 | static 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 */ |
275 | pthread_cond_t *channel_get_cond( channel chan ) { | 244 | static 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 */ | ||
251 | static 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 */ | ||
277 | static 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 */ | ||
299 | static 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 */ | ||
305 | static 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 */ | ||
321 | static 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 */ | ||
327 | static 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 */ | ||
343 | static int luaproc_get_status( luaproc lp ) { | ||
344 | return lp->stat; | ||
345 | } | ||
346 | |||
347 | /* set a process' status */ | ||
348 | static void luaproc_set_status( luaproc lp, int status ) { | ||
349 | lp->stat = status; | ||
350 | } | ||
351 | |||
352 | /* return a process' state */ | ||
353 | static lua_State *luaproc_get_state( luaproc lp ) { | ||
354 | return lp->lstate; | ||
355 | } | ||
356 | |||
357 | /* return the number of arguments expected by a given process */ | ||
358 | static int luaproc_get_args( luaproc lp ) { | ||
359 | return lp->args; | ||
360 | } | ||
361 | |||
362 | /* set the number of arguments expected by a given process */ | ||
363 | static 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 */ | ||
369 | static channel luaproc_get_channel( luaproc lp ) { | ||
370 | return lp->chan; | ||
371 | } | ||
372 | |||
373 | /* unlock access to a channel */ | ||
374 | static 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 */ | ||
388 | static 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 */ | ||
395 | static 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 */ |
283 | void *workermain( void *args ) { | 406 | static 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 */ |
388 | int sched_init_local( int numworkers ) { | 502 | static 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 */ | ||
416 | void 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) */ |
425 | int sched_queue_proc( luaproc lp ) { | 529 | static 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 */ | ||
471 | void 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 */ | ||
478 | void 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 */ |
489 | int sched_create_worker( void ) { | 575 | int 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 | /* | ||
505 | static 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 | */ | ||
513 | static void openlibs( lua_State *L ) { | 587 | static 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 */ | ||
528 | luaproc 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 */ | ||
554 | int 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 */ |
576 | static luaproc luaproc_new( const char *code, int destroyflag, int file) { | 592 | static 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 */ | ||
615 | static int luaproc_exit( lua_State *L ) { | ||
616 | sched_join_workerthreads(); | ||
617 | return 0; | ||
618 | } | ||
619 | |||
620 | /* create a new worker pthread */ | ||
621 | static 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) */ | ||
634 | static 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 */ | ||
670 | static 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 */ |
708 | static luaproc luaproc_recycle( luaproc lp, const char *code, int file ) { | 630 | static 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 | 652 | int newProc(const char *code, int file, void *data) | |
732 | int 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) */ | ||
777 | static 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 */ | ||
801 | void 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 */ | ||
807 | luaproc 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 */ | ||
823 | void 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 */ | ||
829 | luaproc 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 */ |
845 | void luaproc_movevalues( lua_State *Lfrom, lua_State *Lto ) { | 696 | static 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 */ |
857 | luaproc luaproc_getself( lua_State *L ) { | 708 | static 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 | ||
1082 | void luaprocRegister(lua_State *L) | ||
1083 | { | ||
1084 | /* register luaproc functions */ | ||
1085 | luaL_register( L, "luaproc", luaproc_funcs_parent ); | ||
1086 | } | ||
1087 | |||
1088 | LUALIB_API int luaopen_luaproc( lua_State *L ) { | ||
1089 | luaprocRegister(L); | ||
1090 | luaprocInit(); | ||
1091 | return 0; | ||
1092 | } | ||
1093 | |||
1094 | /* return a process' status */ | ||
1095 | int luaproc_get_status( luaproc lp ) { | ||
1096 | return lp->stat; | ||
1097 | } | ||
1098 | |||
1099 | /* set a process' status */ | ||
1100 | void luaproc_set_status( luaproc lp, int status ) { | ||
1101 | lp->stat = status; | ||
1102 | } | ||
1103 | |||
1104 | /* return a process' state */ | ||
1105 | lua_State *luaproc_get_state( luaproc lp ) { | ||
1106 | return lp->lstate; | ||
1107 | } | ||
1108 | |||
1109 | /* return the number of arguments expected by a given process */ | ||
1110 | int luaproc_get_args( luaproc lp ) { | ||
1111 | return lp->args; | ||
1112 | } | ||
1113 | |||
1114 | /* set the number of arguments expected by a given process */ | ||
1115 | void luaproc_set_args( luaproc lp, int n ) { | ||
1116 | lp->args = n; | ||
1117 | } | ||
1118 | |||
1119 | /* create a new channel */ | 933 | /* create a new channel */ |
1120 | static int luaproc_create_channel( lua_State *L ) { | 934 | static 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 */ | ||
1149 | static 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 */ | ||
1245 | void 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 */ | ||
1250 | channel luaproc_get_channel( luaproc lp ) { | ||
1251 | return lp->chan; | ||
1252 | } | ||
1253 | |||
1254 | /* unlock access to a channel */ | ||
1255 | void 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 */ | ||
1267 | int luaproc_get_destroyworker( luaproc lp ) { | ||
1268 | return lp->destroyworker; | ||
1269 | } | ||