aboutsummaryrefslogtreecommitdiff
path: root/src/keeper.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/keeper.c')
-rw-r--r--src/keeper.c1208
1 files changed, 604 insertions, 604 deletions
diff --git a/src/keeper.c b/src/keeper.c
index c777866..eea017f 100644
--- a/src/keeper.c
+++ b/src/keeper.c
@@ -61,9 +61,9 @@
61 61
62typedef struct 62typedef struct
63{ 63{
64 lua_Integer first; 64 lua_Integer first;
65 lua_Integer count; 65 lua_Integer count;
66 lua_Integer limit; 66 lua_Integer limit;
67} keeper_fifo; 67} keeper_fifo;
68 68
69static int const CONTENTS_TABLE = 1; 69static int const CONTENTS_TABLE = 1;
@@ -71,47 +71,47 @@ static int const CONTENTS_TABLE = 1;
71// replaces the fifo ud by its uservalue on the stack 71// replaces the fifo ud by its uservalue on the stack
72static keeper_fifo* prepare_fifo_access( lua_State* L, int idx_) 72static keeper_fifo* prepare_fifo_access( lua_State* L, int idx_)
73{ 73{
74 keeper_fifo* fifo = (keeper_fifo*) lua_touserdata( L, idx_); 74 keeper_fifo* fifo = (keeper_fifo*) lua_touserdata( L, idx_);
75 if( fifo != NULL) 75 if( fifo != NULL)
76 { 76 {
77 idx_ = lua_absindex( L, idx_); 77 idx_ = lua_absindex( L, idx_);
78 STACK_GROW( L, 1); 78 STACK_GROW( L, 1);
79 // we can replace the fifo userdata in the stack without fear of it being GCed, there are other references around 79 // we can replace the fifo userdata in the stack without fear of it being GCed, there are other references around
80 lua_getiuservalue( L, idx_, CONTENTS_TABLE); 80 lua_getiuservalue( L, idx_, CONTENTS_TABLE);
81 lua_replace( L, idx_); 81 lua_replace( L, idx_);
82 } 82 }
83 return fifo; 83 return fifo;
84} 84}
85 85
86// in: nothing 86// in: nothing
87// out: { first = 1, count = 0, limit = -1} 87// out: { first = 1, count = 0, limit = -1}
88static void fifo_new( lua_State* L) 88static void fifo_new( lua_State* L)
89{ 89{
90 keeper_fifo* fifo; 90 keeper_fifo* fifo;
91 STACK_GROW( L, 2); 91 STACK_GROW( L, 2);
92 // a fifo full userdata has one uservalue, the table that holds the actual fifo contents 92 // a fifo full userdata has one uservalue, the table that holds the actual fifo contents
93 fifo = (keeper_fifo*)lua_newuserdatauv( L, sizeof( keeper_fifo), 1); 93 fifo = (keeper_fifo*)lua_newuserdatauv( L, sizeof( keeper_fifo), 1);
94 fifo->first = 1; 94 fifo->first = 1;
95 fifo->count = 0; 95 fifo->count = 0;
96 fifo->limit = -1; 96 fifo->limit = -1;
97 lua_newtable( L); 97 lua_newtable( L);
98 lua_setiuservalue( L, -2, CONTENTS_TABLE); 98 lua_setiuservalue( L, -2, CONTENTS_TABLE);
99} 99}
100 100
101// in: expect fifo ... on top of the stack 101// in: expect fifo ... on top of the stack
102// out: nothing, removes all pushed values from the stack 102// out: nothing, removes all pushed values from the stack
103static void fifo_push( lua_State* L, keeper_fifo* fifo_, lua_Integer count_) 103static void fifo_push( lua_State* L, keeper_fifo* fifo_, lua_Integer count_)
104{ 104{
105 int const idx = lua_gettop( L) - (int) count_; 105 int const idx = lua_gettop( L) - (int) count_;
106 lua_Integer start = fifo_->first + fifo_->count - 1; 106 lua_Integer start = fifo_->first + fifo_->count - 1;
107 lua_Integer i; 107 lua_Integer i;
108 // pop all additional arguments, storing them in the fifo 108 // pop all additional arguments, storing them in the fifo
109 for( i = count_; i >= 1; -- i) 109 for( i = count_; i >= 1; -- i)
110 { 110 {
111 // store in the fifo the value at the top of the stack at the specified index, popping it from the stack 111 // store in the fifo the value at the top of the stack at the specified index, popping it from the stack
112 lua_rawseti( L, idx, (int)(start + i)); 112 lua_rawseti( L, idx, (int)(start + i));
113 } 113 }
114 fifo_->count += count_; 114 fifo_->count += count_;
115} 115}
116 116
117// in: fifo 117// in: fifo
@@ -121,46 +121,46 @@ static void fifo_push( lua_State* L, keeper_fifo* fifo_, lua_Integer count_)
121// function assumes that there is enough data in the fifo to satisfy the request 121// function assumes that there is enough data in the fifo to satisfy the request
122static void fifo_peek( lua_State* L, keeper_fifo* fifo_, lua_Integer count_) 122static void fifo_peek( lua_State* L, keeper_fifo* fifo_, lua_Integer count_)
123{ 123{
124 lua_Integer i; 124 lua_Integer i;
125 STACK_GROW( L, count_); 125 STACK_GROW( L, count_);
126 for( i = 0; i < count_; ++ i) 126 for( i = 0; i < count_; ++ i)
127 { 127 {
128 lua_rawgeti( L, 1, (int)( fifo_->first + i)); 128 lua_rawgeti( L, 1, (int)( fifo_->first + i));
129 } 129 }
130} 130}
131 131
132// in: fifo 132// in: fifo
133// out: remove the fifo from the stack, push as many items as required on the stack (function assumes they exist in sufficient number) 133// out: remove the fifo from the stack, push as many items as required on the stack (function assumes they exist in sufficient number)
134static void fifo_pop( lua_State* L, keeper_fifo* fifo_, lua_Integer count_) 134static void fifo_pop( lua_State* L, keeper_fifo* fifo_, lua_Integer count_)
135{ 135{
136 int const fifo_idx = lua_gettop( L); // ... fifo 136 int const fifo_idx = lua_gettop( L); // ... fifo
137 int i; 137 int i;
138 // each iteration pushes a value on the stack! 138 // each iteration pushes a value on the stack!
139 STACK_GROW( L, count_ + 2); 139 STACK_GROW( L, count_ + 2);
140 // skip first item, we will push it last 140 // skip first item, we will push it last
141 for( i = 1; i < count_; ++ i) 141 for( i = 1; i < count_; ++ i)
142 { 142 {
143 int const at = (int)( fifo_->first + i); 143 int const at = (int)( fifo_->first + i);
144 // push item on the stack 144 // push item on the stack
145 lua_rawgeti( L, fifo_idx, at); // ... fifo val 145 lua_rawgeti( L, fifo_idx, at); // ... fifo val
146 // remove item from the fifo 146 // remove item from the fifo
147 lua_pushnil( L); // ... fifo val nil 147 lua_pushnil( L); // ... fifo val nil
148 lua_rawseti( L, fifo_idx, at); // ... fifo val 148 lua_rawseti( L, fifo_idx, at); // ... fifo val
149 } 149 }
150 // now process first item 150 // now process first item
151 { 151 {
152 int const at = (int)( fifo_->first); 152 int const at = (int)( fifo_->first);
153 lua_rawgeti( L, fifo_idx, at); // ... fifo vals val 153 lua_rawgeti( L, fifo_idx, at); // ... fifo vals val
154 lua_pushnil( L); // ... fifo vals val nil 154 lua_pushnil( L); // ... fifo vals val nil
155 lua_rawseti( L, fifo_idx, at); // ... fifo vals val 155 lua_rawseti( L, fifo_idx, at); // ... fifo vals val
156 lua_replace( L, fifo_idx); // ... vals 156 lua_replace( L, fifo_idx); // ... vals
157 } 157 }
158 { 158 {
159 // avoid ever-growing indexes by resetting each time we detect the fifo is empty 159 // avoid ever-growing indexes by resetting each time we detect the fifo is empty
160 lua_Integer const new_count = fifo_->count - count_; 160 lua_Integer const new_count = fifo_->count - count_;
161 fifo_->first = (new_count == 0) ? 1 : (fifo_->first + count_); 161 fifo_->first = (new_count == 0) ? 1 : (fifo_->first + count_);
162 fifo_->count = new_count; 162 fifo_->count = new_count;
163 } 163 }
164} 164}
165 165
166// in: linda_ud expected at *absolute* stack slot idx 166// in: linda_ud expected at *absolute* stack slot idx
@@ -169,87 +169,87 @@ static void fifo_pop( lua_State* L, keeper_fifo* fifo_, lua_Integer count_)
169static DECLARE_CONST_UNIQUE_KEY( FIFOS_KEY, 0xdce50bbc351cd465); 169static DECLARE_CONST_UNIQUE_KEY( FIFOS_KEY, 0xdce50bbc351cd465);
170static void push_table( lua_State* L, int idx_) 170static void push_table( lua_State* L, int idx_)
171{ 171{
172 STACK_GROW( L, 4); 172 STACK_GROW( L, 4);
173 STACK_CHECK( L, 0); 173 STACK_CHECK( L, 0);
174 idx_ = lua_absindex( L, idx_); 174 idx_ = lua_absindex( L, idx_);
175 REGISTRY_GET( L, FIFOS_KEY); // ud fifos 175 REGISTRY_GET( L, FIFOS_KEY); // ud fifos
176 lua_pushvalue( L, idx_); // ud fifos ud 176 lua_pushvalue( L, idx_); // ud fifos ud
177 lua_rawget( L, -2); // ud fifos fifos[ud] 177 lua_rawget( L, -2); // ud fifos fifos[ud]
178 STACK_MID( L, 2); 178 STACK_MID( L, 2);
179 if( lua_isnil( L, -1)) 179 if( lua_isnil( L, -1))
180 { 180 {
181 lua_pop( L, 1); // ud fifos 181 lua_pop( L, 1); // ud fifos
182 // add a new fifos table for this linda 182 // add a new fifos table for this linda
183 lua_newtable( L); // ud fifos fifos[ud] 183 lua_newtable( L); // ud fifos fifos[ud]
184 lua_pushvalue( L, idx_); // ud fifos fifos[ud] ud 184 lua_pushvalue( L, idx_); // ud fifos fifos[ud] ud
185 lua_pushvalue( L, -2); // ud fifos fifos[ud] ud fifos[ud] 185 lua_pushvalue( L, -2); // ud fifos fifos[ud] ud fifos[ud]
186 lua_rawset( L, -4); // ud fifos fifos[ud] 186 lua_rawset( L, -4); // ud fifos fifos[ud]
187 } 187 }
188 lua_remove( L, -2); // ud fifos[ud] 188 lua_remove( L, -2); // ud fifos[ud]
189 STACK_END( L, 1); 189 STACK_END( L, 1);
190} 190}
191 191
192int keeper_push_linda_storage( Universe* U, lua_State* L, void* ptr_, ptrdiff_t magic_) 192int keeper_push_linda_storage( Universe* U, lua_State* L, void* ptr_, ptrdiff_t magic_)
193{ 193{
194 Keeper* const K = which_keeper( U->keepers, magic_); 194 Keeper* const K = which_keeper( U->keepers, magic_);
195 lua_State* const KL = K ? K->L : NULL; 195 lua_State* const KL = K ? K->L : NULL;
196 if( KL == NULL) return 0; 196 if( KL == NULL) return 0;
197 STACK_GROW( KL, 4); 197 STACK_GROW( KL, 4);
198 STACK_CHECK( KL, 0); 198 STACK_CHECK( KL, 0);
199 REGISTRY_GET( KL, FIFOS_KEY); // fifos 199 REGISTRY_GET( KL, FIFOS_KEY); // fifos
200 lua_pushlightuserdata( KL, ptr_); // fifos ud 200 lua_pushlightuserdata( KL, ptr_); // fifos ud
201 lua_rawget( KL, -2); // fifos storage 201 lua_rawget( KL, -2); // fifos storage
202 lua_remove( KL, -2); // storage 202 lua_remove( KL, -2); // storage
203 if( !lua_istable( KL, -1)) 203 if( !lua_istable( KL, -1))
204 { 204 {
205 lua_pop( KL, 1); // 205 lua_pop( KL, 1); //
206 STACK_MID( KL, 0); 206 STACK_MID( KL, 0);
207 return 0; 207 return 0;
208 } 208 }
209 // move data from keeper to destination state KEEPER MAIN 209 // move data from keeper to destination state KEEPER MAIN
210 lua_pushnil( KL); // storage nil 210 lua_pushnil( KL); // storage nil
211 STACK_GROW( L, 5); 211 STACK_GROW( L, 5);
212 STACK_CHECK( L, 0); 212 STACK_CHECK( L, 0);
213 lua_newtable( L); // out 213 lua_newtable( L); // out
214 while( lua_next( KL, -2)) // storage key fifo 214 while( lua_next( KL, -2)) // storage key fifo
215 { 215 {
216 keeper_fifo* fifo = prepare_fifo_access( KL, -1); // storage key fifo 216 keeper_fifo* fifo = prepare_fifo_access( KL, -1); // storage key fifo
217 lua_pushvalue( KL, -2); // storage key fifo key 217 lua_pushvalue( KL, -2); // storage key fifo key
218 luaG_inter_move( U, KL, L, 1, eLM_FromKeeper); // storage key fifo // out key 218 luaG_inter_move( U, KL, L, 1, eLM_FromKeeper); // storage key fifo // out key
219 STACK_MID( L, 2); 219 STACK_MID( L, 2);
220 lua_newtable( L); // out key keyout 220 lua_newtable( L); // out key keyout
221 luaG_inter_move( U, KL, L, 1, eLM_FromKeeper); // storage key // out key keyout fifo 221 luaG_inter_move( U, KL, L, 1, eLM_FromKeeper); // storage key // out key keyout fifo
222 lua_pushinteger( L, fifo->first); // out key keyout fifo first 222 lua_pushinteger( L, fifo->first); // out key keyout fifo first
223 STACK_MID( L, 5); 223 STACK_MID( L, 5);
224 lua_setfield( L, -3, "first"); // out key keyout fifo 224 lua_setfield( L, -3, "first"); // out key keyout fifo
225 lua_pushinteger( L, fifo->count); // out key keyout fifo count 225 lua_pushinteger( L, fifo->count); // out key keyout fifo count
226 STACK_MID( L, 5); 226 STACK_MID( L, 5);
227 lua_setfield( L, -3, "count"); // out key keyout fifo 227 lua_setfield( L, -3, "count"); // out key keyout fifo
228 lua_pushinteger( L, fifo->limit); // out key keyout fifo limit 228 lua_pushinteger( L, fifo->limit); // out key keyout fifo limit
229 STACK_MID( L, 5); 229 STACK_MID( L, 5);
230 lua_setfield( L, -3, "limit"); // out key keyout fifo 230 lua_setfield( L, -3, "limit"); // out key keyout fifo
231 lua_setfield( L, -2, "fifo"); // out key keyout 231 lua_setfield( L, -2, "fifo"); // out key keyout
232 lua_rawset( L, -3); // out 232 lua_rawset( L, -3); // out
233 STACK_MID( L, 1); 233 STACK_MID( L, 1);
234 } 234 }
235 STACK_END( L, 1); 235 STACK_END( L, 1);
236 lua_pop( KL, 1); // 236 lua_pop( KL, 1); //
237 STACK_END( KL, 0); 237 STACK_END( KL, 0);
238 return 1; 238 return 1;
239} 239}
240 240
241// in: linda_ud 241// in: linda_ud
242int keepercall_clear( lua_State* L) 242int keepercall_clear( lua_State* L)
243{ 243{
244 STACK_GROW( L, 3); 244 STACK_GROW( L, 3);
245 STACK_CHECK( L, 0); 245 STACK_CHECK( L, 0);
246 REGISTRY_GET( L, FIFOS_KEY); // ud fifos 246 REGISTRY_GET( L, FIFOS_KEY); // ud fifos
247 lua_pushvalue( L, 1); // ud fifos ud 247 lua_pushvalue( L, 1); // ud fifos ud
248 lua_pushnil( L); // ud fifos ud nil 248 lua_pushnil( L); // ud fifos ud nil
249 lua_rawset( L, -3); // ud fifos 249 lua_rawset( L, -3); // ud fifos
250 lua_pop( L, 1); // ud 250 lua_pop( L, 1); // ud
251 STACK_END( L, 0); 251 STACK_END( L, 0);
252 return 0; 252 return 0;
253} 253}
254 254
255 255
@@ -257,311 +257,311 @@ int keepercall_clear( lua_State* L)
257// out: true|false 257// out: true|false
258int keepercall_send( lua_State* L) 258int keepercall_send( lua_State* L)
259{ 259{
260 keeper_fifo* fifo; 260 keeper_fifo* fifo;
261 int n = lua_gettop( L) - 2; 261 int n = lua_gettop( L) - 2;
262 push_table( L, 1); // ud key ... fifos 262 push_table( L, 1); // ud key ... fifos
263 // get the fifo associated to this key in this linda, create it if it doesn't exist 263 // get the fifo associated to this key in this linda, create it if it doesn't exist
264 lua_pushvalue( L, 2); // ud key ... fifos key 264 lua_pushvalue( L, 2); // ud key ... fifos key
265 lua_rawget( L, -2); // ud key ... fifos fifo 265 lua_rawget( L, -2); // ud key ... fifos fifo
266 if( lua_isnil( L, -1)) 266 if( lua_isnil( L, -1))
267 { 267 {
268 lua_pop( L, 1); // ud key ... fifos 268 lua_pop( L, 1); // ud key ... fifos
269 fifo_new( L); // ud key ... fifos fifo 269 fifo_new( L); // ud key ... fifos fifo
270 lua_pushvalue( L, 2); // ud key ... fifos fifo key 270 lua_pushvalue( L, 2); // ud key ... fifos fifo key
271 lua_pushvalue( L, -2); // ud key ... fifos fifo key fifo 271 lua_pushvalue( L, -2); // ud key ... fifos fifo key fifo
272 lua_rawset( L, -4); // ud key ... fifos fifo 272 lua_rawset( L, -4); // ud key ... fifos fifo
273 } 273 }
274 lua_remove( L, -2); // ud key ... fifo 274 lua_remove( L, -2); // ud key ... fifo
275 fifo = (keeper_fifo*) lua_touserdata( L, -1); 275 fifo = (keeper_fifo*) lua_touserdata( L, -1);
276 if( fifo->limit >= 0 && fifo->count + n > fifo->limit) 276 if( fifo->limit >= 0 && fifo->count + n > fifo->limit)
277 { 277 {
278 lua_settop( L, 0); // 278 lua_settop( L, 0); //
279 lua_pushboolean( L, 0); // false 279 lua_pushboolean( L, 0); // false
280 } 280 }
281 else 281 else
282 { 282 {
283 fifo = prepare_fifo_access( L, -1); 283 fifo = prepare_fifo_access( L, -1);
284 lua_replace( L, 2); // ud fifo ... 284 lua_replace( L, 2); // ud fifo ...
285 fifo_push( L, fifo, n); // ud fifo 285 fifo_push( L, fifo, n); // ud fifo
286 lua_settop( L, 0); // 286 lua_settop( L, 0); //
287 lua_pushboolean( L, 1); // true 287 lua_pushboolean( L, 1); // true
288 } 288 }
289 return 1; 289 return 1;
290} 290}
291 291
292// in: linda_ud, key [, key]? 292// in: linda_ud, key [, key]?
293// out: (key, val) or nothing 293// out: (key, val) or nothing
294int keepercall_receive( lua_State* L) 294int keepercall_receive( lua_State* L)
295{ 295{
296 int top = lua_gettop( L); 296 int top = lua_gettop( L);
297 int i; 297 int i;
298 push_table( L, 1); // ud keys fifos 298 push_table( L, 1); // ud keys fifos
299 lua_replace( L, 1); // fifos keys 299 lua_replace( L, 1); // fifos keys
300 for( i = 2; i <= top; ++ i) 300 for( i = 2; i <= top; ++ i)
301 { 301 {
302 keeper_fifo* fifo; 302 keeper_fifo* fifo;
303 lua_pushvalue( L, i); // fifos keys key[i] 303 lua_pushvalue( L, i); // fifos keys key[i]
304 lua_rawget( L, 1); // fifos keys fifo 304 lua_rawget( L, 1); // fifos keys fifo
305 fifo = prepare_fifo_access( L, -1); // fifos keys fifo 305 fifo = prepare_fifo_access( L, -1); // fifos keys fifo
306 if( fifo != NULL && fifo->count > 0) 306 if( fifo != NULL && fifo->count > 0)
307 { 307 {
308 fifo_pop( L, fifo, 1); // fifos keys val 308 fifo_pop( L, fifo, 1); // fifos keys val
309 if( !lua_isnil( L, -1)) 309 if( !lua_isnil( L, -1))
310 { 310 {
311 lua_replace( L, 1); // val keys 311 lua_replace( L, 1); // val keys
312 lua_settop( L, i); // val keys key[i] 312 lua_settop( L, i); // val keys key[i]
313 if( i != 2) 313 if( i != 2)
314 { 314 {
315 lua_replace( L, 2); // val key keys 315 lua_replace( L, 2); // val key keys
316 lua_settop( L, 2); // val key 316 lua_settop( L, 2); // val key
317 } 317 }
318 lua_insert( L, 1); // key, val 318 lua_insert( L, 1); // key, val
319 return 2; 319 return 2;
320 } 320 }
321 } 321 }
322 lua_settop( L, top); // data keys 322 lua_settop( L, top); // data keys
323 } 323 }
324 // nothing to receive 324 // nothing to receive
325 return 0; 325 return 0;
326} 326}
327 327
328//in: linda_ud key mincount [maxcount] 328//in: linda_ud key mincount [maxcount]
329int keepercall_receive_batched( lua_State* L) 329int keepercall_receive_batched( lua_State* L)
330{ 330{
331 lua_Integer const min_count = lua_tointeger( L, 3); 331 lua_Integer const min_count = lua_tointeger( L, 3);
332 if( min_count > 0) 332 if( min_count > 0)
333 { 333 {
334 keeper_fifo* fifo; 334 keeper_fifo* fifo;
335 lua_Integer const max_count = luaL_optinteger( L, 4, min_count); 335 lua_Integer const max_count = luaL_optinteger( L, 4, min_count);
336 lua_settop( L, 2); // ud key 336 lua_settop( L, 2); // ud key
337 lua_insert( L, 1); // key ud 337 lua_insert( L, 1); // key ud
338 push_table( L, 2); // key ud fifos 338 push_table( L, 2); // key ud fifos
339 lua_remove( L, 2); // key fifos 339 lua_remove( L, 2); // key fifos
340 lua_pushvalue( L, 1); // key fifos key 340 lua_pushvalue( L, 1); // key fifos key
341 lua_rawget( L, 2); // key fifos fifo 341 lua_rawget( L, 2); // key fifos fifo
342 lua_remove( L, 2); // key fifo 342 lua_remove( L, 2); // key fifo
343 fifo = prepare_fifo_access( L, 2); // key fifo 343 fifo = prepare_fifo_access( L, 2); // key fifo
344 if( fifo != NULL && fifo->count >= min_count) 344 if( fifo != NULL && fifo->count >= min_count)
345 { 345 {
346 fifo_pop( L, fifo, __min( max_count, fifo->count)); // key ... 346 fifo_pop( L, fifo, __min( max_count, fifo->count)); // key ...
347 } 347 }
348 else 348 else
349 { 349 {
350 lua_settop( L, 0); 350 lua_settop( L, 0);
351 } 351 }
352 return lua_gettop( L); 352 return lua_gettop( L);
353 } 353 }
354 else 354 else
355 { 355 {
356 return 0; 356 return 0;
357 } 357 }
358} 358}
359 359
360// in: linda_ud key n 360// in: linda_ud key n
361// out: true or nil 361// out: true or nil
362int keepercall_limit( lua_State* L) 362int keepercall_limit( lua_State* L)
363{ 363{
364 keeper_fifo* fifo; 364 keeper_fifo* fifo;
365 lua_Integer limit = lua_tointeger( L, 3); 365 lua_Integer limit = lua_tointeger( L, 3);
366 push_table( L, 1); // ud key n fifos 366 push_table( L, 1); // ud key n fifos
367 lua_replace( L, 1); // fifos key n 367 lua_replace( L, 1); // fifos key n
368 lua_pop( L, 1); // fifos key 368 lua_pop( L, 1); // fifos key
369 lua_pushvalue( L, -1); // fifos key key 369 lua_pushvalue( L, -1); // fifos key key
370 lua_rawget( L, -3); // fifos key fifo|nil 370 lua_rawget( L, -3); // fifos key fifo|nil
371 fifo = (keeper_fifo*) lua_touserdata( L, -1); 371 fifo = (keeper_fifo*) lua_touserdata( L, -1);
372 if( fifo == NULL) 372 if( fifo == NULL)
373 { // fifos key nil 373 { // fifos key nil
374 lua_pop( L, 1); // fifos key 374 lua_pop( L, 1); // fifos key
375 fifo_new( L); // fifos key fifo 375 fifo_new( L); // fifos key fifo
376 fifo = (keeper_fifo*) lua_touserdata( L, -1); 376 fifo = (keeper_fifo*) lua_touserdata( L, -1);
377 lua_rawset( L, -3); // fifos 377 lua_rawset( L, -3); // fifos
378 } 378 }
379 // remove any clutter on the stack 379 // remove any clutter on the stack
380 lua_settop( L, 0); 380 lua_settop( L, 0);
381 // return true if we decide that blocked threads waiting to write on that key should be awakened 381 // return true if we decide that blocked threads waiting to write on that key should be awakened
382 // this is the case if we detect the key was full but it is no longer the case 382 // this is the case if we detect the key was full but it is no longer the case
383 if( 383 if(
384 ((fifo->limit >= 0) && (fifo->count >= fifo->limit)) // the key was full if limited and count exceeded the previous limit 384 ((fifo->limit >= 0) && (fifo->count >= fifo->limit)) // the key was full if limited and count exceeded the previous limit
385 && ((limit < 0) || (fifo->count < limit)) // the key is not full if unlimited or count is lower than the new limit 385 && ((limit < 0) || (fifo->count < limit)) // the key is not full if unlimited or count is lower than the new limit
386 ) 386 )
387 { 387 {
388 lua_pushboolean( L, 1); 388 lua_pushboolean( L, 1);
389 } 389 }
390 // set the new limit 390 // set the new limit
391 fifo->limit = limit; 391 fifo->limit = limit;
392 // return 0 or 1 value 392 // return 0 or 1 value
393 return lua_gettop( L); 393 return lua_gettop( L);
394} 394}
395 395
396//in: linda_ud key [[val] ...] 396//in: linda_ud key [[val] ...]
397//out: true or nil 397//out: true or nil
398int keepercall_set( lua_State* L) 398int keepercall_set( lua_State* L)
399{ 399{
400 bool_t should_wake_writers = FALSE; 400 bool_t should_wake_writers = FALSE;
401 STACK_GROW( L, 6); 401 STACK_GROW( L, 6);
402 402
403 // retrieve fifos associated with the linda 403 // retrieve fifos associated with the linda
404 push_table( L, 1); // ud key [val [, ...]] fifos 404 push_table( L, 1); // ud key [val [, ...]] fifos
405 lua_replace( L, 1); // fifos key [val [, ...]] 405 lua_replace( L, 1); // fifos key [val [, ...]]
406 406
407 // make sure we have a value on the stack 407 // make sure we have a value on the stack
408 if( lua_gettop( L) == 2) // fifos key 408 if( lua_gettop( L) == 2) // fifos key
409 { 409 {
410 keeper_fifo* fifo; 410 keeper_fifo* fifo;
411 lua_pushvalue( L, -1); // fifos key key 411 lua_pushvalue( L, -1); // fifos key key
412 lua_rawget( L, 1); // fifos key fifo|nil 412 lua_rawget( L, 1); // fifos key fifo|nil
413 // empty the fifo for the specified key: replace uservalue with a virgin table, reset counters, but leave limit unchanged! 413 // empty the fifo for the specified key: replace uservalue with a virgin table, reset counters, but leave limit unchanged!
414 fifo = (keeper_fifo*) lua_touserdata( L, -1); 414 fifo = (keeper_fifo*) lua_touserdata( L, -1);
415 if( fifo != NULL) // might be NULL if we set a nonexistent key to nil 415 if( fifo != NULL) // might be NULL if we set a nonexistent key to nil
416 { // fifos key fifo 416 { // fifos key fifo
417 if( fifo->limit < 0) // fifo limit value is the default (unlimited): we can totally remove it 417 if( fifo->limit < 0) // fifo limit value is the default (unlimited): we can totally remove it
418 { 418 {
419 lua_pop( L, 1); // fifos key 419 lua_pop( L, 1); // fifos key
420 lua_pushnil( L); // fifos key nil 420 lua_pushnil( L); // fifos key nil
421 lua_rawset( L, -3); // fifos 421 lua_rawset( L, -3); // fifos
422 } 422 }
423 else 423 else
424 { 424 {
425 // we create room if the fifo was full but it is no longer the case 425 // we create room if the fifo was full but it is no longer the case
426 should_wake_writers = (fifo->limit > 0) && (fifo->count >= fifo->limit); 426 should_wake_writers = (fifo->limit > 0) && (fifo->count >= fifo->limit);
427 lua_remove( L, -2); // fifos fifo 427 lua_remove( L, -2); // fifos fifo
428 lua_newtable( L); // fifos fifo {} 428 lua_newtable( L); // fifos fifo {}
429 lua_setiuservalue( L, -2, CONTENTS_TABLE); // fifos fifo 429 lua_setiuservalue( L, -2, CONTENTS_TABLE); // fifos fifo
430 fifo->first = 1; 430 fifo->first = 1;
431 fifo->count = 0; 431 fifo->count = 0;
432 } 432 }
433 } 433 }
434 } 434 }
435 else // set/replace contents stored at the specified key? 435 else // set/replace contents stored at the specified key?
436 { 436 {
437 lua_Integer count = lua_gettop( L) - 2; // number of items we want to store 437 lua_Integer count = lua_gettop( L) - 2; // number of items we want to store
438 keeper_fifo* fifo; // fifos key [val [, ...]] 438 keeper_fifo* fifo; // fifos key [val [, ...]]
439 lua_pushvalue( L, 2); // fifos key [val [, ...]] key 439 lua_pushvalue( L, 2); // fifos key [val [, ...]] key
440 lua_rawget( L, 1); // fifos key [val [, ...]] fifo|nil 440 lua_rawget( L, 1); // fifos key [val [, ...]] fifo|nil
441 fifo = (keeper_fifo*) lua_touserdata( L, -1); 441 fifo = (keeper_fifo*) lua_touserdata( L, -1);
442 if( fifo == NULL) // can be NULL if we store a value at a new key 442 if( fifo == NULL) // can be NULL if we store a value at a new key
443 { // fifos key [val [, ...]] nil 443 { // fifos key [val [, ...]] nil
444 // no need to wake writers in that case, because a writer can't wait on an inexistent key 444 // no need to wake writers in that case, because a writer can't wait on an inexistent key
445 lua_pop( L, 1); // fifos key [val [, ...]] 445 lua_pop( L, 1); // fifos key [val [, ...]]
446 fifo_new( L); // fifos key [val [, ...]] fifo 446 fifo_new( L); // fifos key [val [, ...]] fifo
447 lua_pushvalue( L, 2); // fifos key [val [, ...]] fifo key 447 lua_pushvalue( L, 2); // fifos key [val [, ...]] fifo key
448 lua_pushvalue( L, -2); // fifos key [val [, ...]] fifo key fifo 448 lua_pushvalue( L, -2); // fifos key [val [, ...]] fifo key fifo
449 lua_rawset( L, 1); // fifos key [val [, ...]] fifo 449 lua_rawset( L, 1); // fifos key [val [, ...]] fifo
450 } 450 }
451 else // the fifo exists, we just want to update its contents 451 else // the fifo exists, we just want to update its contents
452 { // fifos key [val [, ...]] fifo 452 { // fifos key [val [, ...]] fifo
453 // we create room if the fifo was full but it is no longer the case 453 // we create room if the fifo was full but it is no longer the case
454 should_wake_writers = (fifo->limit > 0) && (fifo->count >= fifo->limit) && (count < fifo->limit); 454 should_wake_writers = (fifo->limit > 0) && (fifo->count >= fifo->limit) && (count < fifo->limit);
455 // empty the fifo for the specified key: replace uservalue with a virgin table, reset counters, but leave limit unchanged! 455 // empty the fifo for the specified key: replace uservalue with a virgin table, reset counters, but leave limit unchanged!
456 lua_newtable( L); // fifos key [val [, ...]] fifo {} 456 lua_newtable( L); // fifos key [val [, ...]] fifo {}
457 lua_setiuservalue( L, -2, CONTENTS_TABLE); // fifos key [val [, ...]] fifo 457 lua_setiuservalue( L, -2, CONTENTS_TABLE); // fifos key [val [, ...]] fifo
458 fifo->first = 1; 458 fifo->first = 1;
459 fifo->count = 0; 459 fifo->count = 0;
460 } 460 }
461 fifo = prepare_fifo_access( L, -1); 461 fifo = prepare_fifo_access( L, -1);
462 // move the fifo below the values we want to store 462 // move the fifo below the values we want to store
463 lua_insert( L, 3); // fifos key fifo [val [, ...]] 463 lua_insert( L, 3); // fifos key fifo [val [, ...]]
464 fifo_push( L, fifo, count); // fifos key fifo 464 fifo_push( L, fifo, count); // fifos key fifo
465 } 465 }
466 return should_wake_writers ? (lua_pushboolean( L, 1), 1) : 0; 466 return should_wake_writers ? (lua_pushboolean( L, 1), 1) : 0;
467} 467}
468 468
469// in: linda_ud key [count] 469// in: linda_ud key [count]
470// out: at most <count> values 470// out: at most <count> values
471int keepercall_get( lua_State* L) 471int keepercall_get( lua_State* L)
472{ 472{
473 keeper_fifo* fifo; 473 keeper_fifo* fifo;
474 lua_Integer count = 1; 474 lua_Integer count = 1;
475 if( lua_gettop( L) == 3) // ud key count 475 if( lua_gettop( L) == 3) // ud key count
476 { 476 {
477 count = lua_tointeger( L, 3); 477 count = lua_tointeger( L, 3);
478 lua_pop( L, 1); // ud key 478 lua_pop( L, 1); // ud key
479 } 479 }
480 push_table( L, 1); // ud key fifos 480 push_table( L, 1); // ud key fifos
481 lua_replace( L, 1); // fifos key 481 lua_replace( L, 1); // fifos key
482 lua_rawget( L, 1); // fifos fifo 482 lua_rawget( L, 1); // fifos fifo
483 fifo = prepare_fifo_access( L, -1); // fifos fifo 483 fifo = prepare_fifo_access( L, -1); // fifos fifo
484 if( fifo != NULL && fifo->count > 0) 484 if( fifo != NULL && fifo->count > 0)
485 { 485 {
486 lua_remove( L, 1); // fifo 486 lua_remove( L, 1); // fifo
487 count = __min( count, fifo->count); 487 count = __min( count, fifo->count);
488 // read <count> value off the fifo 488 // read <count> value off the fifo
489 fifo_peek( L, fifo, count); // fifo ... 489 fifo_peek( L, fifo, count); // fifo ...
490 return (int) count; 490 return (int) count;
491 } 491 }
492 // no fifo was ever registered for this key, or it is empty 492 // no fifo was ever registered for this key, or it is empty
493 return 0; 493 return 0;
494} 494}
495 495
496// in: linda_ud [, key [, ...]] 496// in: linda_ud [, key [, ...]]
497int keepercall_count( lua_State* L) 497int keepercall_count( lua_State* L)
498{ 498{
499 push_table( L, 1); // ud keys fifos 499 push_table( L, 1); // ud keys fifos
500 switch( lua_gettop( L)) 500 switch( lua_gettop( L))
501 { 501 {
502 // no key is specified: return a table giving the count of all known keys 502 // no key is specified: return a table giving the count of all known keys
503 case 2: // ud fifos 503 case 2: // ud fifos
504 lua_newtable( L); // ud fifos out 504 lua_newtable( L); // ud fifos out
505 lua_replace( L, 1); // out fifos 505 lua_replace( L, 1); // out fifos
506 lua_pushnil( L); // out fifos nil 506 lua_pushnil( L); // out fifos nil
507 while( lua_next( L, 2)) // out fifos key fifo 507 while( lua_next( L, 2)) // out fifos key fifo
508 { 508 {
509 keeper_fifo* fifo = prepare_fifo_access( L, -1); // out fifos key fifo 509 keeper_fifo* fifo = prepare_fifo_access( L, -1); // out fifos key fifo
510 lua_pop( L, 1); // out fifos key 510 lua_pop( L, 1); // out fifos key
511 lua_pushvalue( L, -1); // out fifos key key 511 lua_pushvalue( L, -1); // out fifos key key
512 lua_pushinteger( L, fifo->count); // out fifos key key count 512 lua_pushinteger( L, fifo->count); // out fifos key key count
513 lua_rawset( L, -5); // out fifos key 513 lua_rawset( L, -5); // out fifos key
514 } 514 }
515 lua_pop( L, 1); // out 515 lua_pop( L, 1); // out
516 break; 516 break;
517 517
518 // 1 key is specified: return its count 518 // 1 key is specified: return its count
519 case 3: // ud key fifos 519 case 3: // ud key fifos
520 { 520 {
521 keeper_fifo* fifo; 521 keeper_fifo* fifo;
522 lua_replace( L, 1); // fifos key 522 lua_replace( L, 1); // fifos key
523 lua_rawget( L, -2); // fifos fifo|nil 523 lua_rawget( L, -2); // fifos fifo|nil
524 if( lua_isnil( L, -1)) // the key is unknown 524 if( lua_isnil( L, -1)) // the key is unknown
525 { // fifos nil 525 { // fifos nil
526 lua_remove( L, -2); // nil 526 lua_remove( L, -2); // nil
527 } 527 }
528 else // the key is known 528 else // the key is known
529 { // fifos fifo 529 { // fifos fifo
530 fifo = prepare_fifo_access( L, -1); // fifos fifo 530 fifo = prepare_fifo_access( L, -1); // fifos fifo
531 lua_pushinteger( L, fifo->count); // fifos fifo count 531 lua_pushinteger( L, fifo->count); // fifos fifo count
532 lua_replace( L, -3); // count fifo 532 lua_replace( L, -3); // count fifo
533 lua_pop( L, 1); // count 533 lua_pop( L, 1); // count
534 } 534 }
535 } 535 }
536 break; 536 break;
537 537
538 // a variable number of keys is specified: return a table of their counts 538 // a variable number of keys is specified: return a table of their counts
539 default: // ud keys fifos 539 default: // ud keys fifos
540 lua_newtable( L); // ud keys fifos out 540 lua_newtable( L); // ud keys fifos out
541 lua_replace( L, 1); // out keys fifos 541 lua_replace( L, 1); // out keys fifos
542 // shifts all keys up in the stack. potentially slow if there are a lot of them, but then it should be bearable 542 // shifts all keys up in the stack. potentially slow if there are a lot of them, but then it should be bearable
543 lua_insert( L, 2); // out fifos keys 543 lua_insert( L, 2); // out fifos keys
544 while( lua_gettop( L) > 2) 544 while( lua_gettop( L) > 2)
545 { 545 {
546 keeper_fifo* fifo; 546 keeper_fifo* fifo;
547 lua_pushvalue( L, -1); // out fifos keys key 547 lua_pushvalue( L, -1); // out fifos keys key
548 lua_rawget( L, 2); // out fifos keys fifo|nil 548 lua_rawget( L, 2); // out fifos keys fifo|nil
549 fifo = prepare_fifo_access( L, -1); // out fifos keys fifo|nil 549 fifo = prepare_fifo_access( L, -1); // out fifos keys fifo|nil
550 lua_pop( L, 1); // out fifos keys 550 lua_pop( L, 1); // out fifos keys
551 if( fifo != NULL) // the key is known 551 if( fifo != NULL) // the key is known
552 { 552 {
553 lua_pushinteger( L, fifo->count); // out fifos keys count 553 lua_pushinteger( L, fifo->count); // out fifos keys count
554 lua_rawset( L, 1); // out fifos keys 554 lua_rawset( L, 1); // out fifos keys
555 } 555 }
556 else // the key is unknown 556 else // the key is unknown
557 { 557 {
558 lua_pop( L, 1); // out fifos keys 558 lua_pop( L, 1); // out fifos keys
559 } 559 }
560 } 560 }
561 lua_pop( L, 1); // out 561 lua_pop( L, 1); // out
562 } 562 }
563 ASSERT_L( lua_gettop( L) == 1); 563 ASSERT_L( lua_gettop( L) == 1);
564 return 1; 564 return 1;
565} 565}
566 566
567//################################################################################### 567//###################################################################################
@@ -582,41 +582,41 @@ int keepercall_count( lua_State* L)
582// called as __gc for the keepers array userdata 582// called as __gc for the keepers array userdata
583void close_keepers( Universe* U, lua_State* L) 583void close_keepers( Universe* U, lua_State* L)
584{ 584{
585 if( U->keepers != NULL) 585 if( U->keepers != NULL)
586 { 586 {
587 int i; 587 int i;
588 int nbKeepers = U->keepers->nb_keepers; 588 int nbKeepers = U->keepers->nb_keepers;
589 // NOTE: imagine some keeper state N+1 currently holds a linda that uses another keeper N, and a _gc that will make use of it 589 // NOTE: imagine some keeper state N+1 currently holds a linda that uses another keeper N, and a _gc that will make use of it
590 // when keeper N+1 is closed, object is GCed, linda operation is called, which attempts to acquire keeper N, whose Lua state no longer exists 590 // when keeper N+1 is closed, object is GCed, linda operation is called, which attempts to acquire keeper N, whose Lua state no longer exists
591 // in that case, the linda operation should do nothing. which means that these operations must check for keeper acquisition success 591 // in that case, the linda operation should do nothing. which means that these operations must check for keeper acquisition success
592 // which is early-outed with a U->keepers->nbKeepers null-check 592 // which is early-outed with a U->keepers->nbKeepers null-check
593 U->keepers->nb_keepers = 0; 593 U->keepers->nb_keepers = 0;
594 for( i = 0; i < nbKeepers; ++ i) 594 for( i = 0; i < nbKeepers; ++ i)
595 { 595 {
596 lua_State* K = U->keepers->keeper_array[i].L; 596 lua_State* K = U->keepers->keeper_array[i].L;
597 U->keepers->keeper_array[i].L = NULL; 597 U->keepers->keeper_array[i].L = NULL;
598 if( K != NULL) 598 if( K != NULL)
599 { 599 {
600 lua_close( K); 600 lua_close( K);
601 } 601 }
602 else 602 else
603 { 603 {
604 // detected partial init: destroy only the mutexes that got initialized properly 604 // detected partial init: destroy only the mutexes that got initialized properly
605 nbKeepers = i; 605 nbKeepers = i;
606 } 606 }
607 } 607 }
608 for( i = 0; i < nbKeepers; ++ i) 608 for( i = 0; i < nbKeepers; ++ i)
609 { 609 {
610 MUTEX_FREE( &U->keepers->keeper_array[i].keeper_cs); 610 MUTEX_FREE( &U->keepers->keeper_array[i].keeper_cs);
611 } 611 }
612 // free the keeper bookkeeping structure 612 // free the keeper bookkeeping structure
613 { 613 {
614 void* allocUD; 614 void* allocUD;
615 lua_Alloc allocF = lua_getallocf( L, &allocUD); 615 lua_Alloc allocF = lua_getallocf( L, &allocUD);
616 allocF( allocUD, U->keepers, sizeof( Keepers) + (nbKeepers - 1) * sizeof( Keeper), 0); 616 allocF( allocUD, U->keepers, sizeof( Keepers) + (nbKeepers - 1) * sizeof( Keeper), 0);
617 U->keepers = NULL; 617 U->keepers = NULL;
618 } 618 }
619 } 619 }
620} 620}
621 621
622/* 622/*
@@ -632,156 +632,156 @@ void close_keepers( Universe* U, lua_State* L)
632 */ 632 */
633void init_keepers( Universe* U, lua_State* L) 633void init_keepers( Universe* U, lua_State* L)
634{ 634{
635 int i; 635 int i;
636 int nb_keepers; 636 int nb_keepers;
637 void* allocUD; 637 void* allocUD;
638 lua_Alloc allocF = lua_getallocf( L, &allocUD); 638 lua_Alloc allocF = lua_getallocf( L, &allocUD);
639 639
640 STACK_CHECK( L, 0); // L K 640 STACK_CHECK( L, 0); // L K
641 lua_getfield( L, 1, "nb_keepers"); // nb_keepers 641 lua_getfield( L, 1, "nb_keepers"); // nb_keepers
642 nb_keepers = (int) lua_tointeger( L, -1); 642 nb_keepers = (int) lua_tointeger( L, -1);
643 lua_pop( L, 1); // 643 lua_pop( L, 1); //
644 if( nb_keepers < 1) 644 if( nb_keepers < 1)
645 { 645 {
646 (void) luaL_error( L, "Bad number of keepers (%d)", nb_keepers); 646 (void) luaL_error( L, "Bad number of keepers (%d)", nb_keepers);
647 } 647 }
648 648
649 // Keepers contains an array of 1 s_Keeper, adjust for the actual number of keeper states 649 // Keepers contains an array of 1 s_Keeper, adjust for the actual number of keeper states
650 { 650 {
651 size_t const bytes = sizeof( Keepers) + (nb_keepers - 1) * sizeof( Keeper); 651 size_t const bytes = sizeof( Keepers) + (nb_keepers - 1) * sizeof( Keeper);
652 U->keepers = (Keepers*) allocF( allocUD, NULL, 0, bytes); 652 U->keepers = (Keepers*) allocF( allocUD, NULL, 0, bytes);
653 if( U->keepers == NULL) 653 if( U->keepers == NULL)
654 { 654 {
655 (void) luaL_error( L, "init_keepers() failed while creating keeper array; out of memory"); 655 (void) luaL_error( L, "init_keepers() failed while creating keeper array; out of memory");
656 return; 656 return;
657 } 657 }
658 memset( U->keepers, 0, bytes); 658 memset( U->keepers, 0, bytes);
659 U->keepers->nb_keepers = nb_keepers; 659 U->keepers->nb_keepers = nb_keepers;
660 } 660 }
661 for( i = 0; i < nb_keepers; ++ i) // keepersUD 661 for( i = 0; i < nb_keepers; ++ i) // keepersUD
662 { 662 {
663 // note that we will leak K if we raise an error later 663 // note that we will leak K if we raise an error later
664 lua_State* K = create_state( U, L); 664 lua_State* K = create_state( U, L);
665 if( K == NULL) 665 if( K == NULL)
666 { 666 {
667 (void) luaL_error( L, "init_keepers() failed while creating keeper states; out of memory"); 667 (void) luaL_error( L, "init_keepers() failed while creating keeper states; out of memory");
668 return; 668 return;
669 } 669 }
670 670
671 U->keepers->keeper_array[i].L = K; 671 U->keepers->keeper_array[i].L = K;
672 // we can trigger a GC from inside keeper_call(), where a keeper is acquired 672 // we can trigger a GC from inside keeper_call(), where a keeper is acquired
673 // from there, GC can collect a linda, which would acquire the keeper again, and deadlock the thread. 673 // from there, GC can collect a linda, which would acquire the keeper again, and deadlock the thread.
674 // therefore, we need a recursive mutex. 674 // therefore, we need a recursive mutex.
675 MUTEX_RECURSIVE_INIT( &U->keepers->keeper_array[i].keeper_cs); 675 MUTEX_RECURSIVE_INIT( &U->keepers->keeper_array[i].keeper_cs);
676 676
677 STACK_CHECK( K, 0); 677 STACK_CHECK( K, 0);
678 678
679 // copy the universe pointer in the keeper itself 679 // copy the universe pointer in the keeper itself
680 universe_store( K, U); 680 universe_store( K, U);
681 STACK_MID( K, 0); 681 STACK_MID( K, 0);
682 682
683 // make sure 'package' is initialized in keeper states, so that we have require() 683 // make sure 'package' is initialized in keeper states, so that we have require()
684 // this because this is needed when transferring deep userdata object 684 // this because this is needed when transferring deep userdata object
685 luaL_requiref( K, "package", luaopen_package, 1); // package 685 luaL_requiref( K, "package", luaopen_package, 1); // package
686 lua_pop( K, 1); // 686 lua_pop( K, 1); //
687 STACK_MID( K, 0); 687 STACK_MID( K, 0);
688 serialize_require( DEBUGSPEW_PARAM_COMMA( U) K); 688 serialize_require( DEBUGSPEW_PARAM_COMMA( U) K);
689 STACK_MID( K, 0); 689 STACK_MID( K, 0);
690 690
691 // copy package.path and package.cpath from the source state 691 // copy package.path and package.cpath from the source state
692 lua_getglobal( L, "package"); // "..." keepersUD package 692 lua_getglobal( L, "package"); // "..." keepersUD package
693 if( !lua_isnil( L, -1)) 693 if( !lua_isnil( L, -1))
694 { 694 {
695 // when copying with mode eLM_ToKeeper, error message is pushed at the top of the stack, not raised immediately 695 // when copying with mode eLM_ToKeeper, error message is pushed at the top of the stack, not raised immediately
696 if( luaG_inter_copy_package( U, L, K, -1, eLM_ToKeeper)) 696 if( luaG_inter_copy_package( U, L, K, -1, eLM_ToKeeper))
697 { 697 {
698 // if something went wrong, the error message is at the top of the stack 698 // if something went wrong, the error message is at the top of the stack
699 lua_remove( L, -2); // error_msg 699 lua_remove( L, -2); // error_msg
700 (void) lua_error( L); 700 (void) lua_error( L);
701 return; 701 return;
702 } 702 }
703 } 703 }
704 lua_pop( L, 1); // 704 lua_pop( L, 1); //
705 STACK_MID( L, 0); 705 STACK_MID( L, 0);
706 706
707 // attempt to call on_state_create(), if we have one and it is a C function 707 // attempt to call on_state_create(), if we have one and it is a C function
708 // (only support a C function because we can't transfer executable Lua code in keepers) 708 // (only support a C function because we can't transfer executable Lua code in keepers)
709 // will raise an error in L in case of problem 709 // will raise an error in L in case of problem
710 call_on_state_create( U, K, L, eLM_ToKeeper); 710 call_on_state_create( U, K, L, eLM_ToKeeper);
711 711
712 // to see VM name in Decoda debugger 712 // to see VM name in Decoda debugger
713 lua_pushfstring( K, "Keeper #%d", i + 1); // "Keeper #n" 713 lua_pushfstring( K, "Keeper #%d", i + 1); // "Keeper #n"
714 lua_setglobal( K, "decoda_name"); // 714 lua_setglobal( K, "decoda_name"); //
715 715
716 // create the fifos table in the keeper state 716 // create the fifos table in the keeper state
717 REGISTRY_SET( K, FIFOS_KEY, lua_newtable( K)); 717 REGISTRY_SET( K, FIFOS_KEY, lua_newtable( K));
718 STACK_END( K, 0); 718 STACK_END( K, 0);
719 } 719 }
720 STACK_END( L, 0); 720 STACK_END( L, 0);
721} 721}
722 722
723// should be called only when inside a keeper_acquire/keeper_release pair (see linda_protected_call) 723// should be called only when inside a keeper_acquire/keeper_release pair (see linda_protected_call)
724Keeper* which_keeper(Keepers* keepers_, ptrdiff_t magic_) 724Keeper* which_keeper(Keepers* keepers_, ptrdiff_t magic_)
725{ 725{
726 int const nbKeepers = keepers_->nb_keepers; 726 int const nbKeepers = keepers_->nb_keepers;
727 unsigned int i = (unsigned int)((magic_ >> KEEPER_MAGIC_SHIFT) % nbKeepers); 727 unsigned int i = (unsigned int)((magic_ >> KEEPER_MAGIC_SHIFT) % nbKeepers);
728 return &keepers_->keeper_array[i]; 728 return &keepers_->keeper_array[i];
729} 729}
730 730
731Keeper* keeper_acquire( Keepers* keepers_, ptrdiff_t magic_) 731Keeper* keeper_acquire( Keepers* keepers_, ptrdiff_t magic_)
732{ 732{
733 int const nbKeepers = keepers_->nb_keepers; 733 int const nbKeepers = keepers_->nb_keepers;
734 // can be 0 if this happens during main state shutdown (lanes is being GC'ed -> no keepers) 734 // can be 0 if this happens during main state shutdown (lanes is being GC'ed -> no keepers)
735 if( nbKeepers == 0) 735 if( nbKeepers == 0)
736 { 736 {
737 return NULL; 737 return NULL;
738 } 738 }
739 else 739 else
740 { 740 {
741 /* 741 /*
742 * Any hashing will do that maps pointers to 0..GNbKeepers-1 742 * Any hashing will do that maps pointers to 0..GNbKeepers-1
743 * consistently. 743 * consistently.
744 * 744 *
745 * Pointers are often aligned by 8 or so - ignore the low order bits 745 * Pointers are often aligned by 8 or so - ignore the low order bits
746 * have to cast to unsigned long to avoid compilation warnings about loss of data when converting pointer-to-integer 746 * have to cast to unsigned long to avoid compilation warnings about loss of data when converting pointer-to-integer
747 */ 747 */
748 unsigned int i = (unsigned int)((magic_ >> KEEPER_MAGIC_SHIFT) % nbKeepers); 748 unsigned int i = (unsigned int)((magic_ >> KEEPER_MAGIC_SHIFT) % nbKeepers);
749 Keeper* K = &keepers_->keeper_array[i]; 749 Keeper* K = &keepers_->keeper_array[i];
750 750
751 MUTEX_LOCK( &K->keeper_cs); 751 MUTEX_LOCK( &K->keeper_cs);
752 //++ K->count; 752 //++ K->count;
753 return K; 753 return K;
754 } 754 }
755} 755}
756 756
757void keeper_release( Keeper* K) 757void keeper_release( Keeper* K)
758{ 758{
759 //-- K->count; 759 //-- K->count;
760 if( K) MUTEX_UNLOCK( &K->keeper_cs); 760 if( K) MUTEX_UNLOCK( &K->keeper_cs);
761} 761}
762 762
763void keeper_toggle_nil_sentinels( lua_State* L, int val_i_, LookupMode const mode_) 763void keeper_toggle_nil_sentinels( lua_State* L, int val_i_, LookupMode const mode_)
764{ 764{
765 int i, n = lua_gettop( L); 765 int i, n = lua_gettop( L);
766 for( i = val_i_; i <= n; ++ i) 766 for( i = val_i_; i <= n; ++ i)
767 { 767 {
768 if( mode_ == eLM_ToKeeper) 768 if( mode_ == eLM_ToKeeper)
769 { 769 {
770 if( lua_isnil( L, i)) 770 if( lua_isnil( L, i))
771 { 771 {
772 push_unique_key( L, NIL_SENTINEL); 772 push_unique_key( L, NIL_SENTINEL);
773 lua_replace( L, i); 773 lua_replace( L, i);
774 } 774 }
775 } 775 }
776 else 776 else
777 { 777 {
778 if( equal_unique_key( L, i, NIL_SENTINEL)) 778 if( equal_unique_key( L, i, NIL_SENTINEL))
779 { 779 {
780 lua_pushnil( L); 780 lua_pushnil( L);
781 lua_replace( L, i); 781 lua_replace( L, i);
782 } 782 }
783 } 783 }
784 } 784 }
785} 785}
786 786
787/* 787/*
@@ -795,31 +795,31 @@ void keeper_toggle_nil_sentinels( lua_State* L, int val_i_, LookupMode const mod
795*/ 795*/
796int keeper_call( Universe* U, lua_State* K, keeper_api_t func_, lua_State* L, void* linda, uint_t starting_index) 796int keeper_call( Universe* U, lua_State* K, keeper_api_t func_, lua_State* L, void* linda, uint_t starting_index)
797{ 797{
798 int const args = starting_index ? (lua_gettop( L) - starting_index + 1) : 0; 798 int const args = starting_index ? (lua_gettop( L) - starting_index + 1) : 0;
799 int const Ktos = lua_gettop( K); 799 int const Ktos = lua_gettop( K);
800 int retvals = -1; 800 int retvals = -1;
801 801
802 STACK_GROW( K, 2); 802 STACK_GROW( K, 2);
803 803
804 PUSH_KEEPER_FUNC( K, func_); 804 PUSH_KEEPER_FUNC( K, func_);
805 805
806 lua_pushlightuserdata( K, linda); 806 lua_pushlightuserdata( K, linda);
807 807
808 if( (args == 0) || luaG_inter_copy( U, L, K, args, eLM_ToKeeper) == 0) // L->K 808 if( (args == 0) || luaG_inter_copy( U, L, K, args, eLM_ToKeeper) == 0) // L->K
809 { 809 {
810 lua_call( K, 1 + args, LUA_MULTRET); 810 lua_call( K, 1 + args, LUA_MULTRET);
811 811
812 retvals = lua_gettop( K) - Ktos; 812 retvals = lua_gettop( K) - Ktos;
813 // note that this can raise a luaL_error while the keeper state (and its mutex) is acquired 813 // note that this can raise a luaL_error while the keeper state (and its mutex) is acquired
814 // this may interrupt a lane, causing the destruction of the underlying OS thread 814 // this may interrupt a lane, causing the destruction of the underlying OS thread
815 // after this, another lane making use of this keeper can get an error code from the mutex-locking function 815 // after this, another lane making use of this keeper can get an error code from the mutex-locking function
816 // when attempting to grab the mutex again (WINVER <= 0x400 does this, but locks just fine, I don't know about pthread) 816 // when attempting to grab the mutex again (WINVER <= 0x400 does this, but locks just fine, I don't know about pthread)
817 if( (retvals > 0) && luaG_inter_move( U, K, L, retvals, eLM_FromKeeper) != 0) // K->L 817 if( (retvals > 0) && luaG_inter_move( U, K, L, retvals, eLM_FromKeeper) != 0) // K->L
818 { 818 {
819 retvals = -1; 819 retvals = -1;
820 } 820 }
821 } 821 }
822 // whatever happens, restore the stack to where it was at the origin 822 // whatever happens, restore the stack to where it was at the origin
823 lua_settop( K, Ktos); 823 lua_settop( K, Ktos);
824 return retvals; 824 return retvals;
825} 825}