aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/libraries/luaproc
diff options
context:
space:
mode:
authorDavid Walter Seikel2012-01-23 23:36:30 +1000
committerDavid Walter Seikel2012-01-23 23:36:30 +1000
commit6523585c66c04cea54df50013df8886b589847d8 (patch)
tree0b22aee7064166d88595eda260ca2d17c0773da5 /libraries/luaproc
parentUpdate the EFL to what I'm actually using, coz I'm using some stuff not yet r... (diff)
downloadSledjHamr-6523585c66c04cea54df50013df8886b589847d8.zip
SledjHamr-6523585c66c04cea54df50013df8886b589847d8.tar.gz
SledjHamr-6523585c66c04cea54df50013df8886b589847d8.tar.bz2
SledjHamr-6523585c66c04cea54df50013df8886b589847d8.tar.xz
Add luaproc and LuaJIT libraries.
Two versions of LuaJIT, the stable release, and the dev version. Try the dev version first, until ih fails badly.
Diffstat (limited to 'libraries/luaproc')
-rw-r--r--libraries/luaproc/COPYRIGHT32
-rw-r--r--libraries/luaproc/Lua_multithreading_ry08-05.pdfbin0 -> 135164 bytes
-rw-r--r--libraries/luaproc/Makefile64
-rw-r--r--libraries/luaproc/README97
-rw-r--r--libraries/luaproc/channel.c151
-rw-r--r--libraries/luaproc/channel.h67
-rw-r--r--libraries/luaproc/list.c241
-rw-r--r--libraries/luaproc/list.h76
-rw-r--r--libraries/luaproc/luaproc.c837
-rw-r--r--libraries/luaproc/luaproc.h92
-rw-r--r--libraries/luaproc/luaproc.lua34
-rw-r--r--libraries/luaproc/sched.c314
-rw-r--r--libraries/luaproc/sched.h78
-rw-r--r--libraries/luaproc/test.lua39
14 files changed, 2122 insertions, 0 deletions
diff --git a/libraries/luaproc/COPYRIGHT b/libraries/luaproc/COPYRIGHT
new file mode 100644
index 0000000..5f3c3ab
--- /dev/null
+++ b/libraries/luaproc/COPYRIGHT
@@ -0,0 +1,32 @@
1luaproc License
2---------------
3
4luaproc is licensed under the terms of the MIT license reproduced below.
5This means that luaproc is free software and can be used for both academic
6and commercial purposes at absolutely no cost.
7
8===============================================================================
9
10Copyright (C) 2008 Alexandre Skyrme, Noemi Rodriguez, Roberto Ierusalimschy
11
12Permission is hereby granted, free of charge, to any person obtaining a copy
13of this software and associated documentation files (the "Software"), to deal
14in the Software without restriction, including without limitation the rights
15to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
16copies of the Software, and to permit persons to whom the Software is
17furnished to do so, subject to the following conditions:
18
19The above copyright notice and this permission notice shall be included in
20all copies or substantial portions of the Software.
21
22THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
25AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
28THE SOFTWARE.
29
30===============================================================================
31
32(end of COPYRIGHT)
diff --git a/libraries/luaproc/Lua_multithreading_ry08-05.pdf b/libraries/luaproc/Lua_multithreading_ry08-05.pdf
new file mode 100644
index 0000000..5caf694
--- /dev/null
+++ b/libraries/luaproc/Lua_multithreading_ry08-05.pdf
Binary files differ
diff --git a/libraries/luaproc/Makefile b/libraries/luaproc/Makefile
new file mode 100644
index 0000000..1efc2d5
--- /dev/null
+++ b/libraries/luaproc/Makefile
@@ -0,0 +1,64 @@
1####################################################
2#
3# Copyright 2008 Alexandre Skyrme, Noemi Rodriguez, Roberto Ierusalimschy
4#
5# Permission is hereby granted, free of charge, to any person obtaining a copy
6# of this software and associated documentation files (the "Software"), to deal
7# in the Software without restriction, including without limitation the rights
8# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9# copies of the Software, and to permit persons to whom the Software is
10# furnished to do so, subject to the following conditions:
11#
12# The above copyright notice and this permission notice shall be included in
13# all copies or substantial portions of the Software.
14#
15# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21# THE SOFTWARE.
22#
23######################################################
24#
25# [Makefile]
26#
27######################################################
28
29# path to lua header files
30LUA_INC_PATH=/usr/include/lua5.1
31# path to lua library
32LUA_LIB_PATH=/usr/lib/lua5.1
33
34# standard makefile variables
35CC=gcc
36CFLAGS=-c -Wall -fPIC -I${LUA_INC_PATH}
37LDFLAGS=-shared -L${LUA_LIB_PATH} -lpthread
38SOURCES=sched.c list.c luaproc.c channel.c
39OBJECTS=${SOURCES:.c=.o}
40LIB=luaproc.so
41
42all: ${SOURCES} ${LIB}
43
44${LIB}: ${OBJECTS}
45 ${CC} ${OBJECTS} -o $@ ${LDFLAGS}
46
47sched.o: sched.c sched.h list.h luaproc.h channel.h
48 ${CC} ${CFLAGS} sched.c
49
50list.o: list.c list.h
51 ${CC} ${CFLAGS} list.c
52
53luaproc.o: luaproc.c luaproc.h list.h sched.h channel.h
54 ${CC} ${CFLAGS} luaproc.c
55
56channel.o: channel.c channel.h list.h
57 ${CC} ${CFLAGS} channel.c
58
59clean:
60 rm -f ${OBJECTS} ${LIB}
61
62test:
63 lua test.lua
64
diff --git a/libraries/luaproc/README b/libraries/luaproc/README
new file mode 100644
index 0000000..bc37dfe
--- /dev/null
+++ b/libraries/luaproc/README
@@ -0,0 +1,97 @@
1***************************************************
2*
3* Copyright 2008 Alexandre Skyrme, Noemi Rodriguez, Roberto Ierusalimschy
4*
5* Permission is hereby granted, free of charge, to any person obtaining a copy
6* of this software and associated documentation files (the "Software"), to deal
7* in the Software without restriction, including without limitation the rights
8* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9* copies of the Software, and to permit persons to whom the Software is
10* furnished to do so, subject to the following conditions:
11*
12* The above copyright notice and this permission notice shall be included in
13* all copies or substantial portions of the Software.
14*
15* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21* THE SOFTWARE.
22*
23*****************************************************
24*
25* [README]
26*
27****************************************************
28
29
30**************
31* PARENT API *
32**************
33
34-- Create a new lua process
35-- Returns true if sucessful or nil, error_message if failed
36luaproc.newproc( <string lua_code> )
37
38-- Create a new worker (pthread)
39-- Returns true if sucessful or nil, error_message if failed
40luaproc.createworker( <void> )
41
42-- Destroy a worker (pthread)
43-- Returns true if sucessful or nil, error_message if failed
44luaproc.destroyworker( <void> )
45
46-- Synchronize workers (pthreads) and exit after all lua processes have ended
47-- No return, finishes execution.
48luaproc.exit( <void> )
49
50-- Set maximum lua processes that should be recycled (default = 0)
51-- Returns true if sucessful or nil, error_message if failed
52luaproc.recycle( <int maxrecycle> )
53
54************************************************************
55* CHILD API *
56* Available only to processes spawned *
57* with luaproc.newproc *
58************************************************************
59
60-- Create a new lua process
61-- Returns true if sucessful or nil, error_message if failed
62luaproc.newproc( <string lua_code> )
63
64-- Create a new worker (pthread)
65-- Returns true if sucessful or nil, error_message if failed
66luaproc.createworker( <void> )
67
68-- Destroy a worker (pthread)
69-- Returns true if sucessful or nil, error_message if failed
70luaproc.destroyworker( <void> )
71
72-- Send a message on a channel
73-- Returns true if sucessful or nil, error_message if failed
74-- Results in blocking if there is no matching receive
75luaproc.send( <string channel_name>, <string msg1>,
76 [string msg2], [string msg3], ... )
77
78-- Receive a message on a channel
79-- Returns message string(s) if sucessful or nil, error_message if failed
80-- Results in blocking if there is no matching send
81-- and the asynchronous flag is not set (nil) or set to false
82luaproc.receive( <string channel_name>, [boolean asynchronous] )
83
84-- Create a new channel
85-- Returns true if sucessful or nil, error_message if failed
86luaproc.newchannel( <string channel_name> )
87
88-- Destroy a channel
89-- Returns true if sucessful or nil, error_message if failed
90luaproc.delchannel( <string channel_name> )
91
92-- Set maximum lua processes that should be recycled (default = 0)
93-- Returns true if sucessful or nil, error_message if failed
94luaproc.recycle( <int maxrecycle> )
95
96<> = mandatory arguments
97[] = optional arguments
diff --git a/libraries/luaproc/channel.c b/libraries/luaproc/channel.c
new file mode 100644
index 0000000..ef4ab4b
--- /dev/null
+++ b/libraries/luaproc/channel.c
@@ -0,0 +1,151 @@
1/***************************************************
2
3Copyright 2008 Alexandre Skyrme, Noemi Rodriguez, Roberto Ierusalimschy
4
5Permission is hereby granted, free of charge, to any person obtaining a copy
6of this software and associated documentation files (the "Software"), to deal
7in the Software without restriction, including without limitation the rights
8to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9copies of the Software, and to permit persons to whom the Software is
10furnished to do so, subject to the following conditions:
11
12The above copyright notice and this permission notice shall be included in
13all copies or substantial portions of the Software.
14
15THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21THE SOFTWARE.
22
23*****************************************************
24
25[channel.c]
26
27****************************************************/
28
29#include <stdio.h>
30#include <stdlib.h>
31#include <string.h>
32#include <lua.h>
33#include <lauxlib.h>
34#include <lualib.h>
35
36#include "channel.h"
37#include "list.h"
38
39/* global channel lua_State mutex */
40pthread_mutex_t mutex_channel_lstate = PTHREAD_MUTEX_INITIALIZER;
41
42/* global lua_State where channel hash table will be stored */
43lua_State *chanls = NULL;
44
45/* message channel */
46struct stchannel {
47 list send;
48 list recv;
49 pthread_mutex_t *mutex;
50 pthread_cond_t *in_use;
51};
52
53/* initialize channel table */
54void channel_init( void ) {
55 chanls = luaL_newstate();
56 lua_newtable( chanls );
57 lua_setglobal( chanls, "channeltb" );
58}
59
60/* create new channel */
61channel channel_create( const char *cname ) {
62
63 channel chan;
64
65 /* get exclusive access to the channel table */
66 pthread_mutex_lock( &mutex_channel_lstate );
67
68 /* create a new channel */
69 lua_getglobal( chanls, "channeltb");
70 lua_pushstring( chanls, cname );
71 chan = (channel )lua_newuserdata( chanls, sizeof( struct stchannel ));
72 chan->send = list_new();
73 chan->recv = list_new();
74 chan->mutex = (pthread_mutex_t *)malloc( sizeof( pthread_mutex_t ));
75 pthread_mutex_init( chan->mutex, NULL );
76 chan->in_use = (pthread_cond_t *)malloc( sizeof( pthread_cond_t ));
77 pthread_cond_init( chan->in_use, NULL );
78 lua_settable( chanls, -3 );
79 lua_pop( chanls, 1 );
80
81 /* let others access the channel table */
82 pthread_mutex_unlock( &mutex_channel_lstate );
83
84 return chan;
85}
86
87/* destroy a channel */
88int channel_destroy( channel chan, const char *chname ) {
89
90 /* get exclusive access to the channel table */
91 pthread_mutex_lock( &mutex_channel_lstate );
92
93 list_destroy( chan->send );
94 list_destroy( chan->recv );
95
96 lua_getglobal( chanls, "channeltb");
97 lua_pushstring( chanls, chname );
98 lua_pushnil( chanls );
99 lua_settable( chanls, -3 );
100 lua_pop( chanls, 1 );
101
102 /* let others access the channel table */
103 pthread_mutex_unlock( &mutex_channel_lstate );
104
105 return CHANNEL_DESTROYED;
106}
107
108/* search for and return a channel with a given name */
109channel channel_search( const char *cname ) {
110
111 channel chan;
112
113 /* get exclusive access to the channel table */
114 pthread_mutex_lock( &mutex_channel_lstate );
115
116 /* search for channel */
117 lua_getglobal( chanls, "channeltb");
118 lua_getfield( chanls, -1, cname );
119 if (( lua_type( chanls, -1 )) == LUA_TUSERDATA ) {
120 chan = (channel )lua_touserdata( chanls, -1 );
121 } else {
122 chan = NULL;
123 }
124 lua_pop( chanls, 2 );
125
126 /* let others access channel table */
127 pthread_mutex_unlock( &mutex_channel_lstate );
128
129 return chan;
130}
131
132/* return a channel's send queue */
133list channel_get_sendq( channel chan ) {
134 return chan->send;
135}
136
137/* return a channel's receive queue */
138list channel_get_recvq( channel chan ) {
139 return chan->recv;
140}
141
142/* return a channel's mutex */
143pthread_mutex_t *channel_get_mutex( channel chan ) {
144 return chan->mutex;
145}
146
147/* return a channel's conditional variable */
148pthread_cond_t *channel_get_cond( channel chan ) {
149 return chan->in_use;
150}
151
diff --git a/libraries/luaproc/channel.h b/libraries/luaproc/channel.h
new file mode 100644
index 0000000..1cced9e
--- /dev/null
+++ b/libraries/luaproc/channel.h
@@ -0,0 +1,67 @@
1/***************************************************
2
3Copyright 2008 Alexandre Skyrme, Noemi Rodriguez, Roberto Ierusalimschy
4
5Permission is hereby granted, free of charge, to any person obtaining a copy
6of this software and associated documentation files (the "Software"), to deal
7in the Software without restriction, including without limitation the rights
8to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9copies of the Software, and to permit persons to whom the Software is
10furnished to do so, subject to the following conditions:
11
12The above copyright notice and this permission notice shall be included in
13all copies or substantial portions of the Software.
14
15THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21THE SOFTWARE.
22
23*****************************************************
24
25[channel.h]
26
27****************************************************/
28
29#ifndef _CHANNEL_H_
30#define _CHANNEL_H_
31
32#include <pthread.h>
33
34#include "list.h"
35
36#define CHANNEL_MAX_NAME_LENGTH 255
37
38#define CHANNEL_DESTROYED 0
39
40/* message channel pointer type */
41typedef struct stchannel *channel;
42
43/* initialize channels */
44void channel_init( void );
45
46/* create new channel */
47channel channel_create( const char *cname );
48
49/* destroy a channel */
50int channel_destroy( channel chan, const char *chname );
51
52/* search for and return a channel with a given name */
53channel channel_search( const char *cname );
54
55/* return a channel's send queue */
56list channel_get_sendq( channel chan );
57
58/* return a channel's receive queue */
59list channel_get_recvq( channel chan );
60
61/* return a channel's mutex */
62pthread_mutex_t *channel_get_mutex( channel chan );
63
64/* return a channel's conditional variable */
65pthread_cond_t *channel_get_cond( channel chan );
66
67#endif
diff --git a/libraries/luaproc/list.c b/libraries/luaproc/list.c
new file mode 100644
index 0000000..0088695
--- /dev/null
+++ b/libraries/luaproc/list.c
@@ -0,0 +1,241 @@
1/***************************************************
2
3Copyright 2008 Alexandre Skyrme, Noemi Rodriguez, Roberto Ierusalimschy
4
5Permission is hereby granted, free of charge, to any person obtaining a copy
6of this software and associated documentation files (the "Software"), to deal
7in the Software without restriction, including without limitation the rights
8to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9copies of the Software, and to permit persons to whom the Software is
10furnished to do so, subject to the following conditions:
11
12The above copyright notice and this permission notice shall be included in
13all copies or substantial portions of the Software.
14
15THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21THE SOFTWARE.
22
23*****************************************************
24
25[list.c]
26
27****************************************************/
28#include <stdio.h>
29#include <stdlib.h>
30
31#include "list.h"
32
33/* linked list node */
34struct stnode {
35 void *data;
36 struct stnode *next;
37 struct stnode *prev;
38};
39
40/* linked list */
41struct stlist {
42 node head;
43 node tail;
44 int nodes;
45};
46
47/* create new (empty) list */
48list list_new( void ) {
49 list lst;
50 lst = (list )malloc( sizeof( struct stlist ));
51 if ( lst == NULL ) {
52 return lst;
53 }
54 lst->head = NULL;
55 lst->tail = NULL;
56 lst->nodes = 0;
57 return lst;
58}
59
60/* create new node */
61node list_new_node( void *data ) {
62 node n;
63 n = (node )malloc( sizeof( struct stnode ));
64 if ( n == NULL ) {
65 return n;
66 }
67 n->data = data;
68 n->next = NULL;
69 n->prev = NULL;
70 return n;
71}
72
73/* add node to list */
74node list_add( list lst, node n ) {
75
76 /* void list or node */
77 if (( lst == NULL ) || ( n == NULL )) {
78 return NULL;
79 }
80
81 /* list is empty */
82 if ( lst->head == NULL ) {
83 lst->head = n;
84 lst->tail = n;
85 }
86
87 /* list is _not_ empty */
88 else {
89 lst->tail->next = n;
90 n->prev = lst->tail;
91 lst->tail = n;
92 }
93
94 lst->nodes++;
95 return n;
96}
97
98/* search for a node */
99node list_search( list lst, void *data ) {
100
101 node nitr;
102
103 /* check if list is null or empty */
104 if (( lst == NULL ) || ( lst->head == NULL )) {
105 return NULL;
106 }
107
108 /* look for node between first and last nodes (first and last are included) */
109 for ( nitr = lst->head; nitr != NULL; nitr = nitr->next ) {
110 if ( nitr->data == data ) {
111 /* node found, return it */
112 return nitr;
113 }
114 }
115
116 /* node not found */
117 return NULL;
118}
119
120/* remove node from list */
121void list_remove( list lst, node n ) {
122
123 node nitr;
124
125 /* check if list or node are null and if list is empty */
126 if (( lst == NULL ) || ( n == NULL ) || ( lst->head == NULL )) {
127 return;
128 }
129
130 /* check if node is list's head */
131 if ( lst->head == n ) {
132 lst->head = n->next;
133 /* if so, also check if it's the only node in the list */
134 if ( lst->tail == n ) {
135 lst->tail = n->next;
136 }
137 else {
138 lst->head->prev = NULL;
139 }
140 free( n );
141 lst->nodes--;
142 return;
143 }
144
145 /* look for node between first and last nodes (first and last are excluded) */
146 for ( nitr = lst->head->next; nitr != lst->tail; nitr = nitr->next ) {
147 if ( nitr == n ) {
148 n->prev->next = n->next;
149 n->next->prev = n->prev;
150 free( n );
151 lst->nodes--;
152 return;
153 }
154 }
155
156 /* check if node is list's tail */
157 if ( lst->tail == n ) {
158 lst->tail = n->prev;
159 n->prev->next = n->next;
160 free( n );
161 lst->nodes--;
162 return;
163 }
164
165 return;
166}
167
168/* list_destroy */
169void list_destroy( list lst ) {
170
171 /* empty list */
172 if ( lst == NULL ) {
173 return;
174 }
175
176 /* non-empty list */
177 while ( lst->head != NULL ) {
178 list_remove( lst, lst->head );
179 }
180
181 free( lst );
182}
183
184/* return list's first node */
185node list_head( list lst ) {
186 if ( lst != NULL ) {
187 return lst->head;
188 }
189 return NULL;
190}
191
192/* return node's next node */
193node list_next( node n ) {
194 if ( n != NULL ) {
195 return n->next;
196 }
197 return NULL;
198}
199
200/* return a node's data */
201void *list_data( node n ) {
202 if ( n != NULL ) {
203 return n->data;
204 }
205 return NULL;
206}
207
208/* pop the head node from the list */
209node list_pop_head( list lst ) {
210 node ntmp;
211 if (( lst == NULL ) || ( lst->head == NULL )) {
212 return NULL;
213 }
214
215 ntmp = lst->head;
216 if ( lst->head == lst->tail ) {
217 lst->head = NULL;
218 lst->tail = NULL;
219 } else {
220 lst->head = ntmp->next;
221 ntmp->next->prev = NULL;
222 }
223 ntmp->next = NULL;
224 ntmp->prev = NULL;
225 lst->nodes--;
226 return ntmp;
227}
228
229/* destroy a node */
230void list_destroy_node( node n ) {
231 free( n );
232}
233
234/* return a list's node count */
235int list_node_count( list lst ) {
236 if ( lst != NULL ) {
237 return lst->nodes;
238 }
239 return LIST_COUNT_ERROR;
240}
241
diff --git a/libraries/luaproc/list.h b/libraries/luaproc/list.h
new file mode 100644
index 0000000..6aa21c0
--- /dev/null
+++ b/libraries/luaproc/list.h
@@ -0,0 +1,76 @@
1/***************************************************
2
3Copyright 2008 Alexandre Skyrme, Noemi Rodriguez, Roberto Ierusalimschy
4
5Permission is hereby granted, free of charge, to any person obtaining a copy
6of this software and associated documentation files (the "Software"), to deal
7in the Software without restriction, including without limitation the rights
8to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9copies of the Software, and to permit persons to whom the Software is
10furnished to do so, subject to the following conditions:
11
12The above copyright notice and this permission notice shall be included in
13all copies or substantial portions of the Software.
14
15THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21THE SOFTWARE.
22
23*****************************************************
24
25[list.h]
26
27****************************************************/
28
29#ifndef _LIST_H_
30#define _LIST_H_
31
32#define LIST_COUNT_ERROR -1
33
34/* node pointer type */
35typedef struct stnode *node;
36
37/* list pointer type */
38typedef struct stlist *list;
39
40/* create new (empty) list */
41list list_new( void );
42
43/* create new node */
44node list_new_node( void *data );
45
46/* add node to list */
47node list_add( list lst, node n );
48
49/* search for a node */
50node list_search( list lst, void *data );
51
52/* remove node from list */
53void list_remove( list lst, node n );
54
55/* destroy list */
56void list_destroy( list lst );
57
58/* return list's first node */
59node list_head( list lst );
60
61/* return node's next node */
62node list_next( node n );
63
64/* return a node's data */
65void *list_data( node n );
66
67/* pop the head node from the list */
68node list_pop_head( list lst );
69
70/* destroy a node */
71void list_destroy_node( node n );
72
73/* return a list's node count */
74int list_node_count( list lst );
75
76#endif
diff --git a/libraries/luaproc/luaproc.c b/libraries/luaproc/luaproc.c
new file mode 100644
index 0000000..2ec5b31
--- /dev/null
+++ b/libraries/luaproc/luaproc.c
@@ -0,0 +1,837 @@
1/***************************************************
2
3Copyright 2008 Alexandre Skyrme, Noemi Rodriguez, Roberto Ierusalimschy
4
5Permission is hereby granted, free of charge, to any person obtaining a copy
6of this software and associated documentation files (the "Software"), to deal
7in the Software without restriction, including without limitation the rights
8to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9copies of the Software, and to permit persons to whom the Software is
10furnished to do so, subject to the following conditions:
11
12The above copyright notice and this permission notice shall be included in
13all copies or substantial portions of the Software.
14
15THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21THE SOFTWARE.
22
23*****************************************************
24
25[luaproc.c]
26
27****************************************************/
28
29#include <netdb.h>
30#include <pthread.h>
31#include <stdio.h>
32#include <stdlib.h>
33#include <string.h>
34#include <unistd.h>
35#include <lua.h>
36#include <lauxlib.h>
37#include <lualib.h>
38
39#include "luaproc.h"
40#include "list.h"
41#include "sched.h"
42#include "channel.h"
43
44#define FALSE 0
45#define TRUE 1
46
47/*********
48* globals
49*********/
50
51/* channel operations mutex */
52pthread_mutex_t mutex_channel = PTHREAD_MUTEX_INITIALIZER;
53
54/* recycle list mutex */
55pthread_mutex_t mutex_recycle_list = PTHREAD_MUTEX_INITIALIZER;
56
57/* recycled lua process list */
58list recyclelp = NULL;
59
60/* maximum lua processes to recycle */
61int recyclemax = 0;
62
63/* lua process */
64struct stluaproc {
65 lua_State *lstate;
66 int stat;
67 int args;
68 channel chan;
69 int destroyworker;
70};
71
72/******************************
73* library functions prototypes
74******************************/
75/* create a new lua process */
76static int luaproc_create_newproc( lua_State *L );
77/* send a message to a lua process */
78static int luaproc_send( lua_State *L );
79/* receive a message from a lua process */
80static int luaproc_receive( lua_State *L );
81/* create a new channel */
82static int luaproc_create_channel( lua_State *L );
83/* destroy a channel */
84static int luaproc_destroy_channel( lua_State *L );
85/* wait until all luaprocs have finished and exit */
86static int luaproc_exit( lua_State *L );
87/* create a new worker */
88static int luaproc_create_worker( lua_State *L );
89/* destroy a worker */
90static int luaproc_destroy_worker( lua_State *L );
91/* set amount of lua processes that should be recycled (ie, reused) */
92static int luaproc_recycle_set( lua_State *L );
93
94/* luaproc function registration array - main (parent) functions */
95static const struct luaL_reg luaproc_funcs_parent[] = {
96 { "newproc", luaproc_create_newproc },
97 { "exit", luaproc_exit },
98 { "createworker", luaproc_create_worker },
99 { "destroyworker", luaproc_destroy_worker },
100 { "recycle", luaproc_recycle_set },
101 { NULL, NULL }
102};
103
104/* luaproc function registration array - newproc (child) functions */
105static const struct luaL_reg luaproc_funcs_child[] = {
106 { "newproc", luaproc_create_newproc },
107 { "send", luaproc_send },
108 { "receive", luaproc_receive },
109 { "newchannel", luaproc_create_channel },
110 { "delchannel", luaproc_destroy_channel },
111 { "createworker", luaproc_create_worker },
112 { "destroyworker", luaproc_destroy_worker },
113 { "recycle", luaproc_recycle_set },
114 { NULL, NULL }
115};
116
117static void registerlib( lua_State *L, const char *name, lua_CFunction f ) {
118 lua_getglobal( L, "package" );
119 lua_getfield( L, -1, "preload" );
120 lua_pushcfunction( L, f );
121 lua_setfield( L, -2, name );
122 lua_pop( L, 2 );
123}
124
125static void openlibs( lua_State *L ) {
126 lua_cpcall( L, luaopen_base, NULL );
127 lua_cpcall( L, luaopen_package, NULL );
128 registerlib( L, "io", luaopen_io );
129 registerlib( L, "os", luaopen_os );
130 registerlib( L, "table", luaopen_table );
131 registerlib( L, "string", luaopen_string );
132 registerlib( L, "math", luaopen_math );
133 registerlib( L, "debug", luaopen_debug );
134}
135
136/* return status (boolean) indicating if lua process should be recycled */
137luaproc luaproc_recycle_pop( void ) {
138
139 luaproc lp;
140 node n;
141
142 /* get exclusive access to operate on recycle list */
143 pthread_mutex_lock( &mutex_recycle_list );
144
145 /* check if there are any lua processes on recycle list */
146 if ( list_node_count( recyclelp ) > 0 ) {
147 /* pop list head */
148 n = list_pop_head( recyclelp );
149 /* free access to operate on recycle list */
150 pthread_mutex_unlock( &mutex_recycle_list );
151 /* find associated luaproc */
152 lp = (luaproc )list_data( n );
153 /* destroy node (but not associated luaproc) */
154 list_destroy_node( n );
155 /* return associated luaproc */
156 return lp;
157 }
158
159 /* free access to operate on recycle list */
160 pthread_mutex_unlock( &mutex_recycle_list );
161
162 /* if no lua processes are available simply return null */
163 return NULL;
164}
165
166/* check if lua process should be recycled and, in case so, add it to the recycle list */
167int luaproc_recycle_push( luaproc lp ) {
168
169 node n;
170
171 /* get exclusive access to operate on recycle list */
172 pthread_mutex_lock( &mutex_recycle_list );
173
174 /* check if amount of lua processes currently on recycle list is greater than
175 or equal to the maximum amount of lua processes that should be recycled */
176 if ( list_node_count( recyclelp ) >= recyclemax ) {
177 /* free access to operate on recycle list */
178 pthread_mutex_unlock( &mutex_recycle_list );
179 /* if so, lua process should NOT be recycled and should be destroyed */
180 return FALSE;
181 }
182 /* otherwise, lua process should be added to recycle list */
183 n = list_new_node( lp );
184 if ( n == NULL ) {
185 /* free access to operate on recycle list */
186 pthread_mutex_unlock( &mutex_recycle_list );
187 /* in case of errors, lua process should be destroyed */
188 return FALSE;
189 }
190 list_add( recyclelp, n );
191 /* free access to operate on recycle list */
192 pthread_mutex_unlock( &mutex_recycle_list );
193 /* since lua process will be recycled, it should not be destroyed */
194 return TRUE;
195}
196
197/* create new luaproc */
198luaproc luaproc_new( const char *code, int destroyflag ) {
199
200 luaproc lp;
201 int ret;
202 /* create new lua state */
203 lua_State *lpst = luaL_newstate( );
204 /* store the luaproc struct in its own lua state */
205 lp = (luaproc )lua_newuserdata( lpst, sizeof( struct stluaproc ));
206 lua_setfield( lpst, LUA_REGISTRYINDEX, "_SELF" );
207
208 lp->lstate = lpst;
209 lp->stat = LUAPROC_STAT_IDLE;
210 lp->args = 0;
211 lp->chan = NULL;
212 lp->destroyworker = destroyflag;
213
214 /* load standard libraries */
215 openlibs( lpst );
216
217 /* register luaproc's own functions */
218 luaL_register( lpst, "luaproc", luaproc_funcs_child );
219
220 /* load process' code */
221 ret = luaL_loadstring( lpst, code );
222 /* in case of errors, destroy recently created lua process */
223 if ( ret != 0 ) {
224 lua_close( lpst );
225 return NULL;
226 }
227
228 /* return recently created lua process */
229 return lp;
230}
231
232/* synchronize worker threads and exit */
233static int luaproc_exit( lua_State *L ) {
234 sched_join_workerthreads( );
235 return 0;
236}
237
238/* create a new worker pthread */
239static int luaproc_create_worker( lua_State *L ) {
240
241 if ( sched_create_worker( ) != LUAPROC_SCHED_OK ) {
242 lua_pushnil( L );
243 lua_pushstring( L, "error creating worker" );
244 return 2;
245 }
246
247 lua_pushboolean( L, TRUE );
248 return 1;
249}
250
251/* set amount of lua processes that should be recycled (ie, reused) */
252static int luaproc_recycle_set( lua_State *L ) {
253
254 node n;
255 luaproc lp;
256 int max = luaL_checkint( L, 1 );
257
258 /* check if function argument represents a reasonable value */
259 if ( max < 0 ) {
260 /* in case of errors return nil + error msg */
261 lua_pushnil( L );
262 lua_pushstring( L, "error setting recycle limit to negative value" );
263 return 2;
264 }
265
266 /* get exclusive access to operate on recycle list */
267 pthread_mutex_lock( &mutex_recycle_list );
268
269 /* set maximum lua processes that should be recycled */
270 recyclemax = max;
271
272 /* destroy recycle list excessive nodes (and corresponding lua processes) */
273 while ( list_node_count( recyclelp ) > max ) {
274 /* get first node from recycle list */
275 n = list_pop_head( recyclelp );
276 /* find associated luaproc */
277 lp = (luaproc )list_data( n );
278 /* destroy node */
279 list_destroy_node( n );
280 /* close associated lua_State */
281 lua_close( lp->lstate );
282 }
283
284 /* free access to operate on recycle list */
285 pthread_mutex_unlock( &mutex_recycle_list );
286
287 lua_pushboolean( L, TRUE );
288 return 1;
289}
290
291
292/* destroy a worker pthread */
293static int luaproc_destroy_worker( lua_State *L ) {
294
295 /* new lua process pointer */
296 luaproc lp;
297
298 /* create new lua process with empty code and destroy worker flag set to true
299 (ie, conclusion of lua process WILL result in worker thread destruction */
300 lp = luaproc_new( "", TRUE );
301
302 /* ensure process creation was successfull */
303 if ( lp == NULL ) {
304 /* in case of errors return nil + error msg */
305 lua_pushnil( L );
306 lua_pushstring( L, "error destroying worker" );
307 return 2;
308 }
309
310 /* increase active luaproc count */
311 sched_lpcount_inc();
312
313 /* schedule luaproc */
314 if ( sched_queue_proc( lp ) != LUAPROC_SCHED_QUEUE_PROC_OK ) {
315 printf( "[luaproc] error queueing Lua process\n" );
316 /* decrease active luaproc count */
317 sched_lpcount_dec();
318 /* close lua_State */
319 lua_close( lp->lstate );
320 /* return nil + error msg */
321 lua_pushnil( L );
322 lua_pushstring( L, "error destroying worker" );
323 return 2;
324 }
325
326 lua_pushboolean( L, TRUE );
327 return 1;
328}
329
330/* recycle a lua process */
331luaproc luaproc_recycle( luaproc lp, const char *code ) {
332
333 int ret;
334
335 /* reset struct members */
336 lp->stat = LUAPROC_STAT_IDLE;
337 lp->args = 0;
338 lp->chan = NULL;
339 lp->destroyworker = FALSE;
340
341 /* load process' code */
342 ret = luaL_loadstring( lp->lstate, code );
343
344 /* in case of errors, destroy lua process */
345 if ( ret != 0 ) {
346 lua_close( lp->lstate );
347 return NULL;
348 }
349
350 /* return recycled lua process */
351 return lp;
352}
353
354/* create and schedule a new lua process (luaproc.newproc) */
355static int luaproc_create_newproc( lua_State *L ) {
356
357 /* check if first argument is a string (lua code) */
358 const char *code = luaL_checkstring( L, 1 );
359
360 /* new lua process pointer */
361 luaproc lp;
362
363 /* check if existing lua process should be recycled to avoid new creation */
364 lp = luaproc_recycle_pop( );
365
366 /* if there is a lua process available on the recycle queue, recycle it */
367 if ( lp != NULL ) {
368 lp = luaproc_recycle( lp, code );
369 }
370 /* otherwise create a new one from scratch */
371 else {
372 /* create new lua process with destroy worker flag set to false
373 (ie, conclusion of lua process will NOT result in worker thread destruction */
374 lp = luaproc_new( code, FALSE );
375 }
376
377 /* ensure process creation was successfull */
378 if ( lp == NULL ) {
379 /* in case of errors return nil + error msg */
380 lua_pushnil( L );
381 lua_pushstring( L, "error loading code string" );
382 return 2;
383 }
384
385 /* increase active luaproc count */
386 sched_lpcount_inc();
387
388 /* schedule luaproc */
389 if ( sched_queue_proc( lp ) != LUAPROC_SCHED_QUEUE_PROC_OK ) {
390 printf( "[luaproc] error queueing Lua process\n" );
391 /* decrease active luaproc count */
392 sched_lpcount_dec();
393 /* close lua_State */
394 lua_close( lp->lstate );
395 /* return nil + error msg */
396 lua_pushnil( L );
397 lua_pushstring( L, "error queuing process" );
398 return 2;
399 }
400
401 lua_pushboolean( L, TRUE );
402 return 1;
403}
404
405/* queue a lua process sending a message without a matching receiver */
406void luaproc_queue_sender( luaproc lp ) {
407 /* add the sending process to this process' send queue */
408 list_add( channel_get_sendq( lp->chan ), list_new_node( lp ));
409}
410
411/* dequeue a lua process sending a message with a receiver match */
412luaproc luaproc_dequeue_sender( channel chan ) {
413
414 node n;
415 luaproc lp;
416
417 if ( list_node_count( channel_get_sendq( chan )) > 0 ) {
418 /* get first node from channel's send queue */
419 n = list_pop_head( channel_get_sendq( chan ));
420 /* find associated luaproc */
421 lp = (luaproc )list_data( n );
422 /* destroy node (but not associated luaproc) */
423 list_destroy_node( n );
424 /* return associated luaproc */
425 return lp;
426 }
427
428 return NULL;
429}
430
431/* queue a luc process receiving a message without a matching sender */
432void luaproc_queue_receiver( luaproc lp ) {
433 /* add the receiving process to this process' receive queue */
434 list_add( channel_get_recvq( lp->chan ), list_new_node( lp ));
435}
436
437/* dequeue a lua process receiving a message with a sender match */
438luaproc luaproc_dequeue_receiver( channel chan ) {
439
440 node n;
441 luaproc lp;
442
443 if ( list_node_count( channel_get_recvq( chan )) > 0 ) {
444 /* get first node from channel's recv queue */
445 n = list_pop_head( channel_get_recvq( chan ));
446 /* find associated luaproc */
447 lp = (luaproc )list_data( n );
448 /* destroy node (but not associated luaproc) */
449 list_destroy_node( n );
450 /* return associated luaproc */
451 return lp;
452 }
453
454 return NULL;
455}
456
457/* moves values between lua states' stacks */
458void luaproc_movevalues( lua_State *Lfrom, lua_State *Lto ) {
459
460 int i;
461 int n = lua_gettop( Lfrom );
462
463 /* move values between lua states' stacks */
464 for ( i = 2; i <= n; i++ ) {
465 lua_pushstring( Lto, lua_tostring( Lfrom, i ));
466 }
467}
468
469/* return the lua process associated with a given lua state */
470luaproc luaproc_getself( lua_State *L ) {
471 luaproc lp;
472 lua_getfield( L, LUA_REGISTRYINDEX, "_SELF" );
473 lp = (luaproc )lua_touserdata( L, -1 );
474 lua_pop( L, 1 );
475 return lp;
476}
477
478/* send a message to a lua process */
479static int luaproc_send( lua_State *L ) {
480
481 channel chan;
482 luaproc dstlp, self;
483 const char *chname = luaL_checkstring( L, 1 );
484
485 /* get exclusive access to operate on channels */
486 pthread_mutex_lock( &mutex_channel );
487
488 /* wait until channel is not in use */
489 while((( chan = channel_search( chname )) != NULL ) && ( pthread_mutex_trylock( channel_get_mutex( chan )) != 0 )) {
490 pthread_cond_wait( channel_get_cond( chan ), &mutex_channel );
491 }
492
493 /* free access to operate on channels */
494 pthread_mutex_unlock( &mutex_channel );
495
496 /* if channel is not found, return an error to Lua */
497 if ( chan == NULL ) {
498 lua_pushnil( L );
499 lua_pushstring( L, "non-existent channel" );
500 return 2;
501 }
502
503 /* try to find a matching receiver */
504 dstlp = luaproc_dequeue_receiver( chan );
505
506 /* if a match is found, move values to it and (queue) wake it */
507 if ( dstlp != NULL ) {
508
509 /* move values between Lua states' stacks */
510 luaproc_movevalues( L, dstlp->lstate );
511
512 dstlp->args = lua_gettop( dstlp->lstate ) - 1;
513
514 if ( sched_queue_proc( dstlp ) != LUAPROC_SCHED_QUEUE_PROC_OK ) {
515
516 /* unlock channel access */
517 luaproc_unlock_channel( chan );
518
519 /* decrease active luaproc count */
520 sched_lpcount_dec();
521
522 /* close lua_State */
523 lua_close( dstlp->lstate );
524 lua_pushnil( L );
525 lua_pushstring( L, "error scheduling process" );
526 return 2;
527 }
528
529 /* unlock channel access */
530 luaproc_unlock_channel( chan );
531 }
532
533 /* otherwise queue (block) the sending process */
534 else {
535
536 self = luaproc_getself( L );
537
538 if ( self != NULL ) {
539 self->stat = LUAPROC_STAT_BLOCKED_SEND;
540 self->chan = chan;
541 }
542
543 /* just yield the lua process, channel unlocking will be done by the scheduler */
544 return lua_yield( L, lua_gettop( L ));
545 }
546
547 lua_pushboolean( L, TRUE );
548 return 1;
549}
550
551/* receive a message from a lua process */
552static int luaproc_receive( lua_State *L ) {
553
554 channel chan;
555 luaproc srclp, self;
556 const char *chname = luaL_checkstring( L, 1 );
557
558 /* get exclusive access to operate on channels */
559 pthread_mutex_lock( &mutex_channel );
560
561 /* wait until channel is not in use */
562 while((( chan = channel_search( chname )) != NULL ) && ( pthread_mutex_trylock( channel_get_mutex( chan )) != 0 )) {
563 pthread_cond_wait( channel_get_cond( chan ), &mutex_channel );
564 }
565
566 /* free access to operate on channels */
567 pthread_mutex_unlock( &mutex_channel );
568
569 /* if channel is not found, free access to operate on channels and return an error to Lua */
570 if ( chan == NULL ) {
571 lua_pushnil( L );
572 lua_pushstring( L, "non-existent channel" );
573 return 2;
574 }
575
576 /* try to find a matching sender */
577 srclp = luaproc_dequeue_sender( chan );
578
579 /* if a match is found, get values from it and (queue) wake it */
580 if ( srclp != NULL ) {
581
582 /* move values between Lua states' stacks */
583 luaproc_movevalues( srclp->lstate, L );
584
585 /* return to sender indicanting message was sent */
586 lua_pushboolean( srclp->lstate, TRUE );
587 srclp->args = 1;
588
589 if ( sched_queue_proc( srclp ) != LUAPROC_SCHED_QUEUE_PROC_OK ) {
590
591 /* unlock channel access */
592 luaproc_unlock_channel( chan );
593
594 /* decrease active luaproc count */
595 sched_lpcount_dec();
596
597 /* close lua_State */
598 lua_close( srclp->lstate );
599 lua_pushnil( L );
600 lua_pushstring( L, "error scheduling process" );
601 return 2;
602 }
603
604 /* unlock channel access */
605 luaproc_unlock_channel( chan );
606
607 return lua_gettop( L ) - 1;
608 }
609
610 /* otherwise queue (block) the receiving process (sync) or return immediatly (async) */
611 else {
612
613 /* if trying an asynchronous receive, unlock channel access and return an error */
614 if ( lua_toboolean( L, 2 )) {
615 /* unlock channel access */
616 luaproc_unlock_channel( chan );
617 /* return an error */
618 lua_pushnil( L );
619 lua_pushfstring( L, "no senders waiting on channel %s", chname );
620 return 2;
621 }
622
623 /* otherwise (synchronous receive) simply block process */
624 else {
625 self = luaproc_getself( L );
626
627 if ( self != NULL ) {
628 self->stat = LUAPROC_STAT_BLOCKED_RECV;
629 self->chan = chan;
630 }
631
632 /* just yield the lua process, channel unlocking will be done by the scheduler */
633 return lua_yield( L, lua_gettop( L ));
634 }
635 }
636}
637
638LUALIB_API int luaopen_luaproc( lua_State *L ) {
639
640 /* register luaproc functions */
641 luaL_register( L, "luaproc", luaproc_funcs_parent );
642
643 /* initialize recycle list */
644 recyclelp = list_new();
645
646 /* initialize local scheduler */
647 sched_init_local( LUAPROC_SCHED_DEFAULT_WORKER_THREADS );
648
649 return 0;
650}
651
652/* return a process' status */
653int luaproc_get_status( luaproc lp ) {
654 return lp->stat;
655}
656
657/* set a process' status */
658void luaproc_set_status( luaproc lp, int status ) {
659 lp->stat = status;
660}
661
662/* return a process' state */
663lua_State *luaproc_get_state( luaproc lp ) {
664 return lp->lstate;
665}
666
667/* return the number of arguments expected by a given process */
668int luaproc_get_args( luaproc lp ) {
669 return lp->args;
670}
671
672/* set the number of arguments expected by a given process */
673void luaproc_set_args( luaproc lp, int n ) {
674 lp->args = n;
675}
676
677/* create a new channel */
678static int luaproc_create_channel( lua_State *L ) {
679
680 const char *chname = luaL_checkstring( L, 1 );
681
682 /* get exclusive access to operate on channels */
683 pthread_mutex_lock( &mutex_channel );
684
685 /* check if channel exists */
686 if ( channel_search( chname ) != NULL ) {
687 /* free access to operate on channels */
688 pthread_mutex_unlock( &mutex_channel );
689 /* return an error to lua */
690 lua_pushnil( L );
691 lua_pushstring( L, "channel already exists" );
692 return 2;
693 }
694
695 channel_create( chname );
696
697 /* free access to operate on channels */
698 pthread_mutex_unlock( &mutex_channel );
699
700 lua_pushboolean( L, TRUE );
701
702 return 1;
703
704}
705
706/* destroy a channel */
707static int luaproc_destroy_channel( lua_State *L ) {
708
709 channel chan;
710 luaproc lp;
711 node nitr;
712 pthread_mutex_t *chmutex;
713 pthread_cond_t *chcond;
714 const char *chname = luaL_checkstring( L, 1 );
715
716
717 /* get exclusive access to operate on channels */
718 pthread_mutex_lock( &mutex_channel );
719
720 /* wait until channel is not in use */
721 while((( chan = channel_search( chname )) != NULL ) && ( pthread_mutex_trylock( channel_get_mutex( chan )) != 0 )) {
722 pthread_cond_wait( channel_get_cond( chan ), &mutex_channel );
723 }
724
725 /* free access to operate on channels */
726 pthread_mutex_unlock( &mutex_channel );
727
728 /* if channel is not found, return an error to Lua */
729 if ( chan == NULL ) {
730 lua_pushnil( L );
731 lua_pushstring( L, "non-existent channel" );
732 return 2;
733 }
734
735 /* get channel's mutex and conditional pointers */
736 chmutex = channel_get_mutex( chan );
737 chcond = channel_get_cond( chan );
738
739 /* search for processes waiting to send a message on this channel */
740 while (( nitr = list_pop_head( channel_get_sendq( chan ))) != NULL ) {
741
742 lp = (luaproc )list_data( nitr );
743
744 /* destroy node (but not associated luaproc) */
745 list_destroy_node( nitr );
746
747 /* return an error so the processe knows the channel was destroyed before the message was sent */
748 lua_settop( lp->lstate, 0 );
749 lua_pushnil( lp->lstate );
750 lua_pushstring( lp->lstate, "channel destroyed while waiting for receiver" );
751 lp->args = 2;
752
753 /* schedule the process for execution */
754 if ( sched_queue_proc( lp ) != LUAPROC_SCHED_QUEUE_PROC_OK ) {
755
756 /* decrease active luaproc count */
757 sched_lpcount_dec();
758
759 /* close lua_State */
760 lua_close( lp->lstate );
761 }
762 }
763
764 /* search for processes waiting to receive a message on this channel */
765 while (( nitr = list_pop_head( channel_get_recvq( chan ))) != NULL ) {
766
767 lp = (luaproc )list_data( nitr );
768
769 /* destroy node (but not associated luaproc) */
770 list_destroy_node( nitr );
771
772 /* return an error so the processe knows the channel was destroyed before the message was received */
773 lua_settop( lp->lstate, 0 );
774 lua_pushnil( lp->lstate );
775 lua_pushstring( lp->lstate, "channel destroyed while waiting for sender" );
776 lp->args = 2;
777
778 /* schedule the process for execution */
779 if ( sched_queue_proc( lp ) != LUAPROC_SCHED_QUEUE_PROC_OK ) {
780
781 /* decrease active luaproc count */
782 sched_lpcount_dec();
783
784 /* close lua_State */
785 lua_close( lp->lstate );
786 }
787 }
788
789 /* get exclusive access to operate on channels */
790 pthread_mutex_lock( &mutex_channel );
791 /* destroy channel */
792 channel_destroy( chan, chname );
793 /* broadcast channel not in use */
794 pthread_cond_broadcast( chcond );
795 /* unlock channel access */
796 pthread_mutex_unlock( chmutex );
797 /* destroy channel mutex and conditional */
798 pthread_mutex_destroy( chmutex );
799 pthread_cond_destroy( chcond );
800 /* free memory used by channel mutex and conditional */
801 free( chmutex );
802 free( chcond );
803 /* free access to operate on channels */
804 pthread_mutex_unlock( &mutex_channel );
805
806 lua_pushboolean( L, TRUE );
807
808 return 1;
809}
810
811/* register luaproc's functions in a lua_State */
812void luaproc_register_funcs( lua_State *L ) {
813 luaL_register( L, "luaproc", luaproc_funcs_child );
814}
815
816/* return the channel where the corresponding luaproc is blocked at */
817channel luaproc_get_channel( luaproc lp ) {
818 return lp->chan;
819}
820
821/* unlock access to a channel */
822void luaproc_unlock_channel( channel chan ) {
823 /* get exclusive access to operate on channels */
824 pthread_mutex_lock( &mutex_channel );
825 /* unlock channel access */
826 pthread_mutex_unlock( channel_get_mutex( chan ));
827 /* signal channel not in use */
828 pthread_cond_signal( channel_get_cond( chan ));
829 /* free access to operate on channels */
830 pthread_mutex_unlock( &mutex_channel );
831}
832
833/* return status (boolean) indicating if worker thread should be destroyed after luaproc execution */
834int luaproc_get_destroyworker( luaproc lp ) {
835 return lp->destroyworker;
836}
837
diff --git a/libraries/luaproc/luaproc.h b/libraries/luaproc/luaproc.h
new file mode 100644
index 0000000..86617a9
--- /dev/null
+++ b/libraries/luaproc/luaproc.h
@@ -0,0 +1,92 @@
1/***************************************************
2
3Copyright 2008 Alexandre Skyrme, Noemi Rodriguez, Roberto Ierusalimschy
4
5Permission is hereby granted, free of charge, to any person obtaining a copy
6of this software and associated documentation files (the "Software"), to deal
7in the Software without restriction, including without limitation the rights
8to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9copies of the Software, and to permit persons to whom the Software is
10furnished to do so, subject to the following conditions:
11
12The above copyright notice and this permission notice shall be included in
13all copies or substantial portions of the Software.
14
15THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21THE SOFTWARE.
22
23*****************************************************
24
25[luaproc.h]
26
27****************************************************/
28#ifndef _LUAPROC_H_
29#define _LUAPROC_H_
30
31#include "channel.h"
32
33/* process is idle */
34#define LUAPROC_STAT_IDLE 0
35/* process is ready to run */
36#define LUAPROC_STAT_READY 1
37/* process is blocked on send */
38#define LUAPROC_STAT_BLOCKED_SEND 2
39/* process is blocked on receive */
40#define LUAPROC_STAT_BLOCKED_RECV 3
41/* process is finished */
42#define LUAPROC_STAT_FINISHED 4
43
44/* lua process pointer type */
45typedef struct stluaproc *luaproc;
46
47/* return a process' status */
48int luaproc_get_status( luaproc lp );
49
50/* set a process' status */
51void luaproc_set_status( luaproc lp, int status );
52
53/* return a process' state */
54lua_State *luaproc_get_state( luaproc lp );
55
56/* return the number of arguments expected by a given a process */
57int luaproc_get_args( luaproc lp );
58
59/* set the number of arguments expected by a given process */
60void luaproc_set_args( luaproc lp, int n );
61
62/* create luaproc (from scheduler) */
63luaproc luaproc_create_sched( char *code );
64
65/* register luaproc's functions in a lua_State */
66void luaproc_register_funcs( lua_State *L );
67
68/* allow registering of luaproc's functions in c main prog */
69void luaproc_register_lib( lua_State *L );
70
71/* queue a luaproc that tried to send a message */
72void luaproc_queue_sender( luaproc lp );
73
74/* queue a luaproc that tried to receive a message */
75void luaproc_queue_receiver( luaproc lp );
76
77/* unlock a channel's access */
78void luaproc_unlock_channel( channel chan );
79
80/* return a luaproc's channel */
81channel luaproc_get_channel( luaproc lp );
82
83/* return status (boolean) indicating if worker thread should be destroyed after luaproc execution */
84int luaproc_get_destroyworker( luaproc lp );
85
86/* return status (boolean) indicating if lua process should be recycled */
87luaproc luaproc_recycle_pop( void );
88
89/* add a lua process to the recycle list */
90int luaproc_recycle_push( luaproc lp );
91
92#endif
diff --git a/libraries/luaproc/luaproc.lua b/libraries/luaproc/luaproc.lua
new file mode 100644
index 0000000..a1a73e4
--- /dev/null
+++ b/libraries/luaproc/luaproc.lua
@@ -0,0 +1,34 @@
1----------------------------------------------------
2--
3-- Copyright 2008 Alexandre Skyrme, Noemi Rodriguez, Roberto Ierusalimschy
4--
5-- Permission is hereby granted, free of charge, to any person obtaining a copy
6-- of this software and associated documentation files (the "Software"), to deal
7-- in the Software without restriction, including without limitation the rights
8-- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9-- copies of the Software, and to permit persons to whom the Software is
10-- furnished to do so, subject to the following conditions:
11--
12-- The above copyright notice and this permission notice shall be included in
13-- all copies or substantial portions of the Software.
14--
15-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21-- THE SOFTWARE.
22--
23-----------------------------------------------------
24--
25-- luaproc.lua
26--
27-----------------------------------------------------
28
29local function so( objname )
30 local SOPATH = os.getenv( "LUA_SOPATH" ) or "./"
31 assert( package.loadlib( SOPATH .. objname .. ".so" , "luaopen_" .. objname ))( )
32end
33
34so( "luaproc" )
diff --git a/libraries/luaproc/sched.c b/libraries/luaproc/sched.c
new file mode 100644
index 0000000..f19beeb
--- /dev/null
+++ b/libraries/luaproc/sched.c
@@ -0,0 +1,314 @@
1/***************************************************
2
3Copyright 2008 Alexandre Skyrme, Noemi Rodriguez, Roberto Ierusalimschy
4
5Permission is hereby granted, free of charge, to any person obtaining a copy
6of this software and associated documentation files (the "Software"), to deal
7in the Software without restriction, including without limitation the rights
8to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9copies of the Software, and to permit persons to whom the Software is
10furnished to do so, subject to the following conditions:
11
12The above copyright notice and this permission notice shall be included in
13all copies or substantial portions of the Software.
14
15THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21THE SOFTWARE.
22
23*****************************************************
24
25[sched.c]
26
27****************************************************/
28
29#include <pthread.h>
30#include <stdio.h>
31#include <stdlib.h>
32#include <string.h>
33#include <unistd.h>
34#include <arpa/inet.h>
35#include <sys/select.h>
36#include <sys/socket.h>
37#include <sys/stat.h>
38#include <lua.h>
39#include <lauxlib.h>
40#include <lualib.h>
41
42#include "list.h"
43#include "sched.h"
44#include "luaproc.h"
45#include "channel.h"
46
47#define TRUE 1
48#define FALSE 0
49
50/*********
51* globals
52*********/
53
54/* ready process list */
55list lpready = NULL;
56
57/* ready process queue access mutex */
58pthread_mutex_t mutex_queue_access = PTHREAD_MUTEX_INITIALIZER;
59
60/* wake worker up conditional variable */
61pthread_cond_t cond_wakeup_worker = PTHREAD_COND_INITIALIZER;
62
63/* active luaproc count access mutex */
64pthread_mutex_t mutex_lp_count = PTHREAD_MUTEX_INITIALIZER;
65
66/* no active luaproc conditional variable */
67pthread_cond_t cond_no_active_lp = PTHREAD_COND_INITIALIZER;
68
69/* number of active luaprocs */
70int lpcount = 0;
71
72/* no more lua processes flag */
73int no_more_processes = FALSE;
74
75/* worker thread main function */
76void *workermain( void *args ) {
77
78 node n;
79 luaproc lp;
80 int procstat;
81 int destroyworker;
82
83 /* detach thread so resources are freed as soon as thread exits (no further joining) */
84 pthread_detach( pthread_self( ));
85
86 /* main worker loop */
87 while ( 1 ) {
88
89 /* get exclusive access to the ready process queue */
90 pthread_mutex_lock( &mutex_queue_access );
91
92 /* wait until instructed to wake up (because there's work to do or because its time to finish) */
93 while (( list_node_count( lpready ) == 0 ) && ( no_more_processes == FALSE )) {
94 pthread_cond_wait( &cond_wakeup_worker, &mutex_queue_access );
95 }
96
97 /* pop the first node from the ready process queue */
98 n = list_pop_head( lpready );
99
100 /* ensure list pop succeeded before proceeding */
101 if ( n != NULL ) {
102 /* get the popped node's data content (ie, the lua process struct) */
103 lp = (luaproc )list_data( n );
104 }
105 else {
106 /* free access to the process ready queue */
107 pthread_mutex_unlock( &mutex_queue_access );
108 /* finished thread */
109 pthread_exit( NULL );
110 }
111
112 /* free access to the process ready queue */
113 pthread_mutex_unlock( &mutex_queue_access );
114
115 /* execute the lua code specified in the lua process struct */
116 procstat = lua_resume( luaproc_get_state( lp ), luaproc_get_args( lp ));
117
118 /* reset the process argument count */
119 luaproc_set_args( lp, 0 );
120
121 /* check if process finished its whole execution */
122 if ( procstat == 0 ) {
123
124 /* destroy the corresponding list node */
125 list_destroy_node( n );
126
127 /* check if worker thread should be destroyed */
128 destroyworker = luaproc_get_destroyworker( lp );
129
130 /* set process status to finished */
131 luaproc_set_status( lp, LUAPROC_STAT_FINISHED );
132
133 /* check if lua process should be recycled and, if not, destroy it */
134 if ( luaproc_recycle_push( lp ) == FALSE ) {
135 lua_close( luaproc_get_state( lp ));
136 }
137
138 /* decrease active lua process count */
139 sched_lpcount_dec();
140
141 /* check if thread should be finished after lua process conclusion */
142 if ( destroyworker ) {
143 /* if so, finish thread */
144 pthread_exit( NULL );
145 }
146 }
147
148 /* check if process yielded */
149 else if ( procstat == LUA_YIELD ) {
150
151 /* if so, further check if yield originated from an unmatched send/recv operation */
152 if ( luaproc_get_status( lp ) == LUAPROC_STAT_BLOCKED_SEND ) {
153 /* queue blocked lua process on corresponding channel */
154 luaproc_queue_sender( lp );
155 /* unlock channel access */
156 luaproc_unlock_channel( luaproc_get_channel( lp ));
157 /* destroy node (but not the associated Lua process) */
158 list_destroy_node( n );
159 }
160
161 else if ( luaproc_get_status( lp ) == LUAPROC_STAT_BLOCKED_RECV ) {
162 /* queue blocked lua process on corresponding channel */
163 luaproc_queue_receiver( lp );
164 /* unlock channel access */
165 luaproc_unlock_channel( luaproc_get_channel( lp ));
166 /* destroy node (but not the associated Lua process) */
167 list_destroy_node( n );
168 }
169
170 /* or if yield resulted from an explicit call to coroutine.yield in the lua code being executed */
171 else {
172 /* get exclusive access to the ready process queue */
173 pthread_mutex_lock( &mutex_queue_access );
174 /* re-insert the job at the end of the ready process queue */
175 list_add( lpready, n );
176 /* free access to the process ready queue */
177 pthread_mutex_unlock( &mutex_queue_access );
178 }
179 }
180
181 /* check if there was any execution error (LUA_ERRRUN, LUA_ERRSYNTAX, LUA_ERRMEM or LUA_ERRERR) */
182 else {
183 /* destroy the corresponding node */
184 list_destroy_node( n );
185 /* print error message */
186 fprintf( stderr, "close lua_State (error: %s)\n", luaL_checkstring( luaproc_get_state( lp ), -1 ));
187 /* close lua state */
188 lua_close( luaproc_get_state( lp ));
189 /* decrease active lua process count */
190 sched_lpcount_dec();
191 }
192 }
193}
194
195/* local scheduler initialization */
196int sched_init_local( int numworkers ) {
197
198 int tid;
199 int workercount = 0;
200 pthread_t worker;
201
202 /* initialize ready process list */
203 lpready = list_new();
204
205 /* initialize channels */
206 channel_init();
207
208 /* create initial worker threads */
209 for ( tid = 0; tid < numworkers; tid++ ) {
210 if ( pthread_create( &worker, NULL, workermain, NULL ) == 0 ) {
211 workercount++;
212 }
213 }
214
215 if ( workercount != numworkers ) {
216 return LUAPROC_SCHED_INIT_ERROR;
217 }
218
219 return LUAPROC_SCHED_OK;
220}
221
222/* exit scheduler */
223void sched_exit( void ) {
224
225 /* get exclusive access to the ready process queue */
226 pthread_mutex_lock( &mutex_queue_access );
227 /* destroy the ready process list */
228 list_destroy( lpready );
229 /* free access to the process ready queue */
230 pthread_mutex_unlock( &mutex_queue_access );
231}
232
233/* move process to ready queue (ie, schedule process) */
234int sched_queue_proc( luaproc lp ) {
235
236 /* get exclusive access to the ready process queue */
237 pthread_mutex_lock( &mutex_queue_access );
238
239 /* add process to ready queue */
240 if ( list_add( lpready, list_new_node( lp )) != NULL ) {
241
242 /* set process status to ready */
243 luaproc_set_status( lp, LUAPROC_STAT_READY );
244
245 /* wake worker up */
246 pthread_cond_signal( &cond_wakeup_worker );
247 /* free access to the process ready queue */
248 pthread_mutex_unlock( &mutex_queue_access );
249
250 return LUAPROC_SCHED_QUEUE_PROC_OK;
251 }
252 else {
253 /* free access to the process ready queue */
254 pthread_mutex_unlock( &mutex_queue_access );
255
256 return LUAPROC_SCHED_QUEUE_PROC_ERR;
257 }
258}
259
260/* synchronize worker threads */
261void sched_join_workerthreads( void ) {
262
263 pthread_mutex_lock( &mutex_lp_count );
264
265 /* wait until there is no more active lua processes */
266 while( lpcount != 0 ) {
267 pthread_cond_wait( &cond_no_active_lp, &mutex_lp_count );
268 }
269 /* get exclusive access to the ready process queue */
270 pthread_mutex_lock( &mutex_queue_access );
271 /* set the no more active lua processes flag to true */
272 no_more_processes = TRUE;
273 /* wake ALL workers up */
274 pthread_cond_broadcast( &cond_wakeup_worker );
275 /* free access to the process ready queue */
276 pthread_mutex_unlock( &mutex_queue_access );
277 /* wait for (join) worker threads */
278 pthread_exit( NULL );
279
280 pthread_mutex_unlock( &mutex_lp_count );
281
282}
283
284/* increase active lua process count */
285void sched_lpcount_inc( void ) {
286 pthread_mutex_lock( &mutex_lp_count );
287 lpcount++;
288 pthread_mutex_unlock( &mutex_lp_count );
289}
290
291/* decrease active lua process count */
292void sched_lpcount_dec( void ) {
293 pthread_mutex_lock( &mutex_lp_count );
294 lpcount--;
295 /* if count reaches zero, signal there are no more active processes */
296 if ( lpcount == 0 ) {
297 pthread_cond_signal( &cond_no_active_lp );
298 }
299 pthread_mutex_unlock( &mutex_lp_count );
300}
301
302/* create a new worker pthread */
303int sched_create_worker( void ) {
304
305 pthread_t worker;
306
307 /* create a new pthread */
308 if ( pthread_create( &worker, NULL, workermain, NULL ) != 0 ) {
309 return LUAPROC_SCHED_PTHREAD_ERROR;
310 }
311
312 return LUAPROC_SCHED_OK;
313}
314
diff --git a/libraries/luaproc/sched.h b/libraries/luaproc/sched.h
new file mode 100644
index 0000000..c03e6ea
--- /dev/null
+++ b/libraries/luaproc/sched.h
@@ -0,0 +1,78 @@
1/***************************************************
2
3Copyright 2008 Alexandre Skyrme, Noemi Rodriguez, Roberto Ierusalimschy
4
5Permission is hereby granted, free of charge, to any person obtaining a copy
6of this software and associated documentation files (the "Software"), to deal
7in the Software without restriction, including without limitation the rights
8to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9copies of the Software, and to permit persons to whom the Software is
10furnished to do so, subject to the following conditions:
11
12The above copyright notice and this permission notice shall be included in
13all copies or substantial portions of the Software.
14
15THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21THE SOFTWARE.
22
23*****************************************************
24
25[sched.h]
26
27****************************************************/
28#ifndef _SCHED_H_
29#define _SCHED_H_
30
31#include "luaproc.h"
32
33/* scheduler function return constants */
34#define LUAPROC_SCHED_OK 0
35#define LUAPROC_SCHED_SOCKET_ERROR -1
36#define LUAPROC_SCHED_SETSOCKOPT_ERROR -2
37#define LUAPROC_SCHED_BIND_ERROR -3
38#define LUAPROC_SCHED_LISTEN_ERROR -4
39#define LUAPROC_SCHED_FORK_ERROR -5
40#define LUAPROC_SCHED_PTHREAD_ERROR -6
41#define LUAPROC_SCHED_INIT_ERROR -7
42
43/* ready process queue insertion status */
44#define LUAPROC_SCHED_QUEUE_PROC_OK 0
45#define LUAPROC_SCHED_QUEUE_PROC_ERR -1
46
47/* scheduler listener service default hostname and port */
48#define LUAPROC_SCHED_DEFAULT_HOST "127.0.0.1"
49#define LUAPROC_SCHED_DEFAULT_PORT 3133
50
51/* scheduler default number of worker threads */
52#define LUAPROC_SCHED_DEFAULT_WORKER_THREADS 1
53
54/* initialize local scheduler */
55int sched_init_local( int numworkers );
56
57/* initialize socket enabled scheduler */
58int sched_init_socket( int numworkers, const char *host, int port );
59
60/* exit scheduler */
61void sched_exit( void );
62
63/* move process to ready queue (ie, schedule process) */
64int sched_queue_proc( luaproc lp );
65
66/* join all worker threads and exit */
67void sched_join_workerthreads( void );
68
69/* increase active luaproc count */
70void sched_lpcount_inc( void );
71
72/* decrease active luaproc count */
73void sched_lpcount_dec( void );
74
75/* create a new worker pthread */
76int sched_create_worker( void );
77
78#endif
diff --git a/libraries/luaproc/test.lua b/libraries/luaproc/test.lua
new file mode 100644
index 0000000..5868d6f
--- /dev/null
+++ b/libraries/luaproc/test.lua
@@ -0,0 +1,39 @@
1----------------------------------------------------
2--
3-- Copyright 2008 Alexandre Skyrme, Noemi Rodriguez, Roberto Ierusalimschy
4--
5-- Permission is hereby granted, free of charge, to any person obtaining a copy
6-- of this software and associated documentation files (the "Software"), to deal
7-- in the Software without restriction, including without limitation the rights
8-- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9-- copies of the Software, and to permit persons to whom the Software is
10-- furnished to do so, subject to the following conditions:
11--
12-- The above copyright notice and this permission notice shall be included in
13-- all copies or substantial portions of the Software.
14--
15-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21-- THE SOFTWARE.
22--
23-----------------------------------------------------
24--
25-- test.lua
26--
27-----------------------------------------------------
28
29require "luaproc"
30
31luaproc.createworker()
32
33luaproc.newproc( [=[
34 luaproc.newchannel( "testchannel" )
35 luaproc.newproc( "luaproc.send( 'testchannel', 'luaproc is working fine!' )" )
36 luaproc.newproc( "print( luaproc.receive( 'testchannel' ))" )
37]=] )
38
39luaproc.exit()