aboutsummaryrefslogtreecommitdiff
path: root/src/linda.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/linda.c')
-rw-r--r--src/linda.c1380
1 files changed, 690 insertions, 690 deletions
diff --git a/src/linda.c b/src/linda.c
index d3ed8a0..a9c9710 100644
--- a/src/linda.c
+++ b/src/linda.c
@@ -48,13 +48,13 @@ THE SOFTWARE.
48*/ 48*/
49struct s_Linda 49struct s_Linda
50{ 50{
51 DeepPrelude prelude; // Deep userdata MUST start with this header 51 DeepPrelude prelude; // Deep userdata MUST start with this header
52 SIGNAL_T read_happened; 52 SIGNAL_T read_happened;
53 SIGNAL_T write_happened; 53 SIGNAL_T write_happened;
54 Universe* U; // the universe this linda belongs to 54 Universe* U; // the universe this linda belongs to
55 ptrdiff_t group; // a group to control keeper allocation between lindas 55 ptrdiff_t group; // a group to control keeper allocation between lindas
56 enum e_cancel_request simulate_cancel; 56 enum e_cancel_request simulate_cancel;
57 char name[1]; 57 char name[1];
58}; 58};
59#define LINDA_KEEPER_HASHSEED( linda) (linda->group ? linda->group : (ptrdiff_t)linda) 59#define LINDA_KEEPER_HASHSEED( linda) (linda->group ? linda->group : (ptrdiff_t)linda)
60 60
@@ -62,51 +62,51 @@ static void* linda_id( lua_State*, DeepOp);
62 62
63static inline struct s_Linda* lua_toLinda( lua_State* L, int idx_) 63static inline struct s_Linda* lua_toLinda( lua_State* L, int idx_)
64{ 64{
65 struct s_Linda* linda = (struct s_Linda*) luaG_todeep( L, linda_id, idx_); 65 struct s_Linda* linda = (struct s_Linda*) luaG_todeep( L, linda_id, idx_);
66 luaL_argcheck( L, linda != NULL, idx_, "expecting a linda object"); 66 luaL_argcheck( L, linda != NULL, idx_, "expecting a linda object");
67 return linda; 67 return linda;
68} 68}
69 69
70static void check_key_types( lua_State* L, int start_, int end_) 70static void check_key_types( lua_State* L, int start_, int end_)
71{ 71{
72 int i; 72 int i;
73 for( i = start_; i <= end_; ++ i) 73 for( i = start_; i <= end_; ++ i)
74 { 74 {
75 int t = lua_type( L, i); 75 int t = lua_type( L, i);
76 if( t == LUA_TBOOLEAN || t == LUA_TNUMBER || t == LUA_TSTRING || t == LUA_TLIGHTUSERDATA) 76 if( t == LUA_TBOOLEAN || t == LUA_TNUMBER || t == LUA_TSTRING || t == LUA_TLIGHTUSERDATA)
77 { 77 {
78 continue; 78 continue;
79 } 79 }
80 (void) luaL_error( L, "argument #%d: invalid key type (not a boolean, string, number or light userdata)", i); 80 (void) luaL_error( L, "argument #%d: invalid key type (not a boolean, string, number or light userdata)", i);
81 } 81 }
82} 82}
83 83
84LUAG_FUNC( linda_protected_call) 84LUAG_FUNC( linda_protected_call)
85{ 85{
86 int rc = LUA_OK; 86 int rc = LUA_OK;
87 struct s_Linda* linda = lua_toLinda( L, 1); 87 struct s_Linda* linda = lua_toLinda( L, 1);
88 88
89 // acquire the keeper 89 // acquire the keeper
90 Keeper* K = keeper_acquire( linda->U->keepers, LINDA_KEEPER_HASHSEED(linda)); 90 Keeper* K = keeper_acquire( linda->U->keepers, LINDA_KEEPER_HASHSEED(linda));
91 lua_State* KL = K ? K->L : NULL; // need to do this for 'STACK_CHECK' 91 lua_State* KL = K ? K->L : NULL; // need to do this for 'STACK_CHECK'
92 if( KL == NULL) return 0; 92 if( KL == NULL) return 0;
93 93
94 // retrieve the actual function to be called and move it before the arguments 94 // retrieve the actual function to be called and move it before the arguments
95 lua_pushvalue( L, lua_upvalueindex( 1)); 95 lua_pushvalue( L, lua_upvalueindex( 1));
96 lua_insert( L, 1); 96 lua_insert( L, 1);
97 // do a protected call 97 // do a protected call
98 rc = lua_pcall( L, lua_gettop( L) - 1, LUA_MULTRET, 0); 98 rc = lua_pcall( L, lua_gettop( L) - 1, LUA_MULTRET, 0);
99 99
100 // release the keeper 100 // release the keeper
101 keeper_release( K); 101 keeper_release( K);
102 102
103 // if there was an error, forward it 103 // if there was an error, forward it
104 if( rc != LUA_OK) 104 if( rc != LUA_OK)
105 { 105 {
106 return lua_error( L); 106 return lua_error( L);
107 } 107 }
108 // return whatever the actual operation provided 108 // return whatever the actual operation provided
109 return lua_gettop( L); 109 return lua_gettop( L);
110} 110}
111 111
112/* 112/*
@@ -120,142 +120,142 @@ LUAG_FUNC( linda_protected_call)
120*/ 120*/
121LUAG_FUNC( linda_send) 121LUAG_FUNC( linda_send)
122{ 122{
123 struct s_Linda* linda = lua_toLinda( L, 1); 123 struct s_Linda* linda = lua_toLinda( L, 1);
124 bool_t ret = FALSE; 124 bool_t ret = FALSE;
125 enum e_cancel_request cancel = CANCEL_NONE; 125 enum e_cancel_request cancel = CANCEL_NONE;
126 int pushed; 126 int pushed;
127 time_d timeout = -1.0; 127 time_d timeout = -1.0;
128 uint_t key_i = 2; // index of first key, if timeout not there 128 uint_t key_i = 2; // index of first key, if timeout not there
129 bool_t as_nil_sentinel; // if not NULL, send() will silently send a single nil if nothing is provided 129 bool_t as_nil_sentinel; // if not NULL, send() will silently send a single nil if nothing is provided
130 130
131 if( lua_type( L, 2) == LUA_TNUMBER) // we don't want to use lua_isnumber() because of autocoercion 131 if( lua_type( L, 2) == LUA_TNUMBER) // we don't want to use lua_isnumber() because of autocoercion
132 { 132 {
133 timeout = SIGNAL_TIMEOUT_PREPARE( lua_tonumber( L, 2)); 133 timeout = SIGNAL_TIMEOUT_PREPARE( lua_tonumber( L, 2));
134 ++ key_i; 134 ++ key_i;
135 } 135 }
136 else if( lua_isnil( L, 2)) // alternate explicit "no timeout" by passing nil before the key 136 else if( lua_isnil( L, 2)) // alternate explicit "no timeout" by passing nil before the key
137 { 137 {
138 ++ key_i; 138 ++ key_i;
139 } 139 }
140 140
141 as_nil_sentinel = equal_unique_key( L, key_i, NIL_SENTINEL); 141 as_nil_sentinel = equal_unique_key( L, key_i, NIL_SENTINEL);
142 if( as_nil_sentinel) 142 if( as_nil_sentinel)
143 { 143 {
144 // the real key to send data to is after the NIL_SENTINEL marker 144 // the real key to send data to is after the NIL_SENTINEL marker
145 ++ key_i; 145 ++ key_i;
146 } 146 }
147 147
148 // make sure the key is of a valid type 148 // make sure the key is of a valid type
149 check_key_types( L, key_i, key_i); 149 check_key_types( L, key_i, key_i);
150 150
151 STACK_GROW( L, 1); 151 STACK_GROW( L, 1);
152 152
153 // make sure there is something to send 153 // make sure there is something to send
154 if( (uint_t)lua_gettop( L) == key_i) 154 if( (uint_t)lua_gettop( L) == key_i)
155 { 155 {
156 if( as_nil_sentinel) 156 if( as_nil_sentinel)
157 { 157 {
158 // send a single nil if nothing is provided 158 // send a single nil if nothing is provided
159 push_unique_key( L, NIL_SENTINEL); 159 push_unique_key( L, NIL_SENTINEL);
160 } 160 }
161 else 161 else
162 { 162 {
163 return luaL_error( L, "no data to send"); 163 return luaL_error( L, "no data to send");
164 } 164 }
165 } 165 }
166 166
167 // convert nils to some special non-nil sentinel in sent values 167 // convert nils to some special non-nil sentinel in sent values
168 keeper_toggle_nil_sentinels( L, key_i + 1, eLM_ToKeeper); 168 keeper_toggle_nil_sentinels( L, key_i + 1, eLM_ToKeeper);
169 169
170 { 170 {
171 bool_t try_again = TRUE; 171 bool_t try_again = TRUE;
172 Lane* const s = get_lane_from_registry( L); 172 Lane* const s = get_lane_from_registry( L);
173 Keeper* K = which_keeper( linda->U->keepers, LINDA_KEEPER_HASHSEED( linda)); 173 Keeper* K = which_keeper( linda->U->keepers, LINDA_KEEPER_HASHSEED( linda));
174 lua_State* KL = K ? K->L : NULL; // need to do this for 'STACK_CHECK' 174 lua_State* KL = K ? K->L : NULL; // need to do this for 'STACK_CHECK'
175 if( KL == NULL) return 0; 175 if( KL == NULL) return 0;
176 STACK_CHECK( KL, 0); 176 STACK_CHECK( KL, 0);
177 for( ;;) 177 for( ;;)
178 { 178 {
179 if( s != NULL) 179 if( s != NULL)
180 { 180 {
181 cancel = s->cancel_request; 181 cancel = s->cancel_request;
182 } 182 }
183 cancel = (cancel != CANCEL_NONE) ? cancel : linda->simulate_cancel; 183 cancel = (cancel != CANCEL_NONE) ? cancel : linda->simulate_cancel;
184 // if user wants to cancel, or looped because of a timeout, the call returns without sending anything 184 // if user wants to cancel, or looped because of a timeout, the call returns without sending anything
185 if( !try_again || cancel != CANCEL_NONE) 185 if( !try_again || cancel != CANCEL_NONE)
186 { 186 {
187 pushed = 0; 187 pushed = 0;
188 break; 188 break;
189 } 189 }
190 190
191 STACK_MID( KL, 0); 191 STACK_MID( KL, 0);
192 pushed = keeper_call( linda->U, KL, KEEPER_API( send), L, linda, key_i); 192 pushed = keeper_call( linda->U, KL, KEEPER_API( send), L, linda, key_i);
193 if( pushed < 0) 193 if( pushed < 0)
194 { 194 {
195 break; 195 break;
196 } 196 }
197 ASSERT_L( pushed == 1); 197 ASSERT_L( pushed == 1);
198 198
199 ret = lua_toboolean( L, -1); 199 ret = lua_toboolean( L, -1);
200 lua_pop( L, 1); 200 lua_pop( L, 1);
201 201
202 if( ret) 202 if( ret)
203 { 203 {
204 // Wake up ALL waiting threads 204 // Wake up ALL waiting threads
205 SIGNAL_ALL( &linda->write_happened); 205 SIGNAL_ALL( &linda->write_happened);
206 break; 206 break;
207 } 207 }
208 208
209 // instant timout to bypass the wait syscall 209 // instant timout to bypass the wait syscall
210 if( timeout == 0.0) 210 if( timeout == 0.0)
211 { 211 {
212 break; /* no wait; instant timeout */ 212 break; /* no wait; instant timeout */
213 } 213 }
214 214
215 // storage limit hit, wait until timeout or signalled that we should try again 215 // storage limit hit, wait until timeout or signalled that we should try again
216 { 216 {
217 enum e_status prev_status = ERROR_ST; // prevent 'might be used uninitialized' warnings 217 enum e_status prev_status = ERROR_ST; // prevent 'might be used uninitialized' warnings
218 if( s != NULL) 218 if( s != NULL)
219 { 219 {
220 // change status of lane to "waiting" 220 // change status of lane to "waiting"
221 prev_status = s->status; // RUNNING, most likely 221 prev_status = s->status; // RUNNING, most likely
222 ASSERT_L( prev_status == RUNNING); // but check, just in case 222 ASSERT_L( prev_status == RUNNING); // but check, just in case
223 s->status = WAITING; 223 s->status = WAITING;
224 ASSERT_L( s->waiting_on == NULL); 224 ASSERT_L( s->waiting_on == NULL);
225 s->waiting_on = &linda->read_happened; 225 s->waiting_on = &linda->read_happened;
226 } 226 }
227 // could not send because no room: wait until some data was read before trying again, or until timeout is reached 227 // could not send because no room: wait until some data was read before trying again, or until timeout is reached
228 try_again = SIGNAL_WAIT( &linda->read_happened, &K->keeper_cs, timeout); 228 try_again = SIGNAL_WAIT( &linda->read_happened, &K->keeper_cs, timeout);
229 if( s != NULL) 229 if( s != NULL)
230 { 230 {
231 s->waiting_on = NULL; 231 s->waiting_on = NULL;
232 s->status = prev_status; 232 s->status = prev_status;
233 } 233 }
234 } 234 }
235 } 235 }
236 STACK_END( KL, 0); 236 STACK_END( KL, 0);
237 } 237 }
238 238
239 if( pushed < 0) 239 if( pushed < 0)
240 { 240 {
241 return luaL_error( L, "tried to copy unsupported types"); 241 return luaL_error( L, "tried to copy unsupported types");
242 } 242 }
243 243
244 switch( cancel) 244 switch( cancel)
245 { 245 {
246 case CANCEL_SOFT: 246 case CANCEL_SOFT:
247 // if user wants to soft-cancel, the call returns lanes.cancel_error 247 // if user wants to soft-cancel, the call returns lanes.cancel_error
248 push_unique_key( L, CANCEL_ERROR); 248 push_unique_key( L, CANCEL_ERROR);
249 return 1; 249 return 1;
250 250
251 case CANCEL_HARD: 251 case CANCEL_HARD:
252 // raise an error interrupting execution only in case of hard cancel 252 // raise an error interrupting execution only in case of hard cancel
253 return cancel_error( L); // raises an error and doesn't return 253 return cancel_error( L); // raises an error and doesn't return
254 254
255 default: 255 default:
256 lua_pushboolean( L, ret); // true (success) or false (timeout) 256 lua_pushboolean( L, ret); // true (success) or false (timeout)
257 return 1; 257 return 1;
258 } 258 }
259} 259}
260 260
261 261
@@ -273,143 +273,143 @@ LUAG_FUNC( linda_send)
273#define BATCH_SENTINEL "270e6c9d-280f-4983-8fee-a7ecdda01475" 273#define BATCH_SENTINEL "270e6c9d-280f-4983-8fee-a7ecdda01475"
274LUAG_FUNC( linda_receive) 274LUAG_FUNC( linda_receive)
275{ 275{
276 struct s_Linda* linda = lua_toLinda( L, 1); 276 struct s_Linda* linda = lua_toLinda( L, 1);
277 int pushed, expected_pushed_min, expected_pushed_max; 277 int pushed, expected_pushed_min, expected_pushed_max;
278 enum e_cancel_request cancel = CANCEL_NONE; 278 enum e_cancel_request cancel = CANCEL_NONE;
279 keeper_api_t keeper_receive; 279 keeper_api_t keeper_receive;
280 280
281 time_d timeout = -1.0; 281 time_d timeout = -1.0;
282 uint_t key_i = 2; 282 uint_t key_i = 2;
283 283
284 if( lua_type( L, 2) == LUA_TNUMBER) // we don't want to use lua_isnumber() because of autocoercion 284 if( lua_type( L, 2) == LUA_TNUMBER) // we don't want to use lua_isnumber() because of autocoercion
285 { 285 {
286 timeout = SIGNAL_TIMEOUT_PREPARE( lua_tonumber( L, 2)); 286 timeout = SIGNAL_TIMEOUT_PREPARE( lua_tonumber( L, 2));
287 ++ key_i; 287 ++ key_i;
288 } 288 }
289 else if( lua_isnil( L, 2)) // alternate explicit "no timeout" by passing nil before the key 289 else if( lua_isnil( L, 2)) // alternate explicit "no timeout" by passing nil before the key
290 { 290 {
291 ++ key_i; 291 ++ key_i;
292 } 292 }
293 293
294 // are we in batched mode? 294 // are we in batched mode?
295 { 295 {
296 int is_batched; 296 int is_batched;
297 lua_pushliteral( L, BATCH_SENTINEL); 297 lua_pushliteral( L, BATCH_SENTINEL);
298 is_batched = lua501_equal( L, key_i, -1); 298 is_batched = lua501_equal( L, key_i, -1);
299 lua_pop( L, 1); 299 lua_pop( L, 1);
300 if( is_batched) 300 if( is_batched)
301 { 301 {
302 // no need to pass linda.batched in the keeper state 302 // no need to pass linda.batched in the keeper state
303 ++ key_i; 303 ++ key_i;
304 // make sure the keys are of a valid type 304 // make sure the keys are of a valid type
305 check_key_types( L, key_i, key_i); 305 check_key_types( L, key_i, key_i);
306 // receive multiple values from a single slot 306 // receive multiple values from a single slot
307 keeper_receive = KEEPER_API( receive_batched); 307 keeper_receive = KEEPER_API( receive_batched);
308 // we expect a user-defined amount of return value 308 // we expect a user-defined amount of return value
309 expected_pushed_min = (int)luaL_checkinteger( L, key_i + 1); 309 expected_pushed_min = (int)luaL_checkinteger( L, key_i + 1);
310 expected_pushed_max = (int)luaL_optinteger( L, key_i + 2, expected_pushed_min); 310 expected_pushed_max = (int)luaL_optinteger( L, key_i + 2, expected_pushed_min);
311 // don't forget to count the key in addition to the values 311 // don't forget to count the key in addition to the values
312 ++ expected_pushed_min; 312 ++ expected_pushed_min;
313 ++ expected_pushed_max; 313 ++ expected_pushed_max;
314 if( expected_pushed_min > expected_pushed_max) 314 if( expected_pushed_min > expected_pushed_max)
315 { 315 {
316 return luaL_error( L, "batched min/max error"); 316 return luaL_error( L, "batched min/max error");
317 } 317 }
318 } 318 }
319 else 319 else
320 { 320 {
321 // make sure the keys are of a valid type 321 // make sure the keys are of a valid type
322 check_key_types( L, key_i, lua_gettop( L)); 322 check_key_types( L, key_i, lua_gettop( L));
323 // receive a single value, checking multiple slots 323 // receive a single value, checking multiple slots
324 keeper_receive = KEEPER_API( receive); 324 keeper_receive = KEEPER_API( receive);
325 // we expect a single (value, key) pair of returned values 325 // we expect a single (value, key) pair of returned values
326 expected_pushed_min = expected_pushed_max = 2; 326 expected_pushed_min = expected_pushed_max = 2;
327 } 327 }
328 } 328 }
329 329
330 { 330 {
331 bool_t try_again = TRUE; 331 bool_t try_again = TRUE;
332 Lane* const s = get_lane_from_registry( L); 332 Lane* const s = get_lane_from_registry( L);
333 Keeper* K = which_keeper( linda->U->keepers, LINDA_KEEPER_HASHSEED( linda)); 333 Keeper* K = which_keeper( linda->U->keepers, LINDA_KEEPER_HASHSEED( linda));
334 if( K == NULL) return 0; 334 if( K == NULL) return 0;
335 for( ;;) 335 for( ;;)
336 { 336 {
337 if( s != NULL) 337 if( s != NULL)
338 { 338 {
339 cancel = s->cancel_request; 339 cancel = s->cancel_request;
340 } 340 }
341 cancel = (cancel != CANCEL_NONE) ? cancel : linda->simulate_cancel; 341 cancel = (cancel != CANCEL_NONE) ? cancel : linda->simulate_cancel;
342 // if user wants to cancel, or looped because of a timeout, the call returns without sending anything 342 // if user wants to cancel, or looped because of a timeout, the call returns without sending anything
343 if( !try_again || cancel != CANCEL_NONE) 343 if( !try_again || cancel != CANCEL_NONE)
344 { 344 {
345 pushed = 0; 345 pushed = 0;
346 break; 346 break;
347 } 347 }
348 348
349 // all arguments of receive() but the first are passed to the keeper's receive function 349 // all arguments of receive() but the first are passed to the keeper's receive function
350 pushed = keeper_call( linda->U, K->L, keeper_receive, L, linda, key_i); 350 pushed = keeper_call( linda->U, K->L, keeper_receive, L, linda, key_i);
351 if( pushed < 0) 351 if( pushed < 0)
352 { 352 {
353 break; 353 break;
354 } 354 }
355 if( pushed > 0) 355 if( pushed > 0)
356 { 356 {
357 ASSERT_L( pushed >= expected_pushed_min && pushed <= expected_pushed_max); 357 ASSERT_L( pushed >= expected_pushed_min && pushed <= expected_pushed_max);
358 // replace sentinels with real nils 358 // replace sentinels with real nils
359 keeper_toggle_nil_sentinels( L, lua_gettop( L) - pushed, eLM_FromKeeper); 359 keeper_toggle_nil_sentinels( L, lua_gettop( L) - pushed, eLM_FromKeeper);
360 // To be done from within the 'K' locking area 360 // To be done from within the 'K' locking area
361 // 361 //
362 SIGNAL_ALL( &linda->read_happened); 362 SIGNAL_ALL( &linda->read_happened);
363 break; 363 break;
364 } 364 }
365 365
366 if( timeout == 0.0) 366 if( timeout == 0.0)
367 { 367 {
368 break; /* instant timeout */ 368 break; /* instant timeout */
369 } 369 }
370 370
371 // nothing received, wait until timeout or signalled that we should try again 371 // nothing received, wait until timeout or signalled that we should try again
372 { 372 {
373 enum e_status prev_status = ERROR_ST; // prevent 'might be used uninitialized' warnings 373 enum e_status prev_status = ERROR_ST; // prevent 'might be used uninitialized' warnings
374 if( s != NULL) 374 if( s != NULL)
375 { 375 {
376 // change status of lane to "waiting" 376 // change status of lane to "waiting"
377 prev_status = s->status; // RUNNING, most likely 377 prev_status = s->status; // RUNNING, most likely
378 ASSERT_L( prev_status == RUNNING); // but check, just in case 378 ASSERT_L( prev_status == RUNNING); // but check, just in case
379 s->status = WAITING; 379 s->status = WAITING;
380 ASSERT_L( s->waiting_on == NULL); 380 ASSERT_L( s->waiting_on == NULL);
381 s->waiting_on = &linda->write_happened; 381 s->waiting_on = &linda->write_happened;
382 } 382 }
383 // not enough data to read: wakeup when data was sent, or when timeout is reached 383 // not enough data to read: wakeup when data was sent, or when timeout is reached
384 try_again = SIGNAL_WAIT( &linda->write_happened, &K->keeper_cs, timeout); 384 try_again = SIGNAL_WAIT( &linda->write_happened, &K->keeper_cs, timeout);
385 if( s != NULL) 385 if( s != NULL)
386 { 386 {
387 s->waiting_on = NULL; 387 s->waiting_on = NULL;
388 s->status = prev_status; 388 s->status = prev_status;
389 } 389 }
390 } 390 }
391 } 391 }
392 } 392 }
393 393
394 if( pushed < 0) 394 if( pushed < 0)
395 { 395 {
396 return luaL_error( L, "tried to copy unsupported types"); 396 return luaL_error( L, "tried to copy unsupported types");
397 } 397 }
398 398
399 switch( cancel) 399 switch( cancel)
400 { 400 {
401 case CANCEL_SOFT: 401 case CANCEL_SOFT:
402 // if user wants to soft-cancel, the call returns CANCEL_ERROR 402 // if user wants to soft-cancel, the call returns CANCEL_ERROR
403 push_unique_key( L, CANCEL_ERROR); 403 push_unique_key( L, CANCEL_ERROR);
404 return 1; 404 return 1;
405 405
406 case CANCEL_HARD: 406 case CANCEL_HARD:
407 // raise an error interrupting execution only in case of hard cancel 407 // raise an error interrupting execution only in case of hard cancel
408 return cancel_error( L); // raises an error and doesn't return 408 return cancel_error( L); // raises an error and doesn't return
409 409
410 default: 410 default:
411 return pushed; 411 return pushed;
412 } 412 }
413} 413}
414 414
415 415
@@ -423,51 +423,51 @@ LUAG_FUNC( linda_receive)
423*/ 423*/
424LUAG_FUNC( linda_set) 424LUAG_FUNC( linda_set)
425{ 425{
426 struct s_Linda* const linda = lua_toLinda( L, 1); 426 struct s_Linda* const linda = lua_toLinda( L, 1);
427 int pushed; 427 int pushed;
428 bool_t has_value = lua_gettop( L) > 2; 428 bool_t has_value = lua_gettop( L) > 2;
429 429
430 // make sure the key is of a valid type (throws an error if not the case) 430 // make sure the key is of a valid type (throws an error if not the case)
431 check_key_types( L, 2, 2); 431 check_key_types( L, 2, 2);
432 432
433 { 433 {
434 Keeper* K = which_keeper( linda->U->keepers, LINDA_KEEPER_HASHSEED( linda)); 434 Keeper* K = which_keeper( linda->U->keepers, LINDA_KEEPER_HASHSEED( linda));
435 435
436 if( linda->simulate_cancel == CANCEL_NONE) 436 if( linda->simulate_cancel == CANCEL_NONE)
437 { 437 {
438 if( has_value) 438 if( has_value)
439 { 439 {
440 // convert nils to some special non-nil sentinel in sent values 440 // convert nils to some special non-nil sentinel in sent values
441 keeper_toggle_nil_sentinels( L, 3, eLM_ToKeeper); 441 keeper_toggle_nil_sentinels( L, 3, eLM_ToKeeper);
442 } 442 }
443 pushed = keeper_call( linda->U, K->L, KEEPER_API( set), L, linda, 2); 443 pushed = keeper_call( linda->U, K->L, KEEPER_API( set), L, linda, 2);
444 if( pushed >= 0) // no error? 444 if( pushed >= 0) // no error?
445 { 445 {
446 ASSERT_L( pushed == 0 || pushed == 1); 446 ASSERT_L( pushed == 0 || pushed == 1);
447 447
448 if( has_value) 448 if( has_value)
449 { 449 {
450 // we put some data in the slot, tell readers that they should wake 450 // we put some data in the slot, tell readers that they should wake
451 SIGNAL_ALL( &linda->write_happened); // To be done from within the 'K' locking area 451 SIGNAL_ALL( &linda->write_happened); // To be done from within the 'K' locking area
452 } 452 }
453 if( pushed == 1) 453 if( pushed == 1)
454 { 454 {
455 // the key was full, but it is no longer the case, tell writers they should wake 455 // the key was full, but it is no longer the case, tell writers they should wake
456 ASSERT_L( lua_type( L, -1) == LUA_TBOOLEAN && lua_toboolean( L, -1) == 1); 456 ASSERT_L( lua_type( L, -1) == LUA_TBOOLEAN && lua_toboolean( L, -1) == 1);
457 SIGNAL_ALL( &linda->read_happened); // To be done from within the 'K' locking area 457 SIGNAL_ALL( &linda->read_happened); // To be done from within the 'K' locking area
458 } 458 }
459 } 459 }
460 } 460 }
461 else // linda is cancelled 461 else // linda is cancelled
462 { 462 {
463 // do nothing and return lanes.cancel_error 463 // do nothing and return lanes.cancel_error
464 push_unique_key( L, CANCEL_ERROR); 464 push_unique_key( L, CANCEL_ERROR);
465 pushed = 1; 465 pushed = 1;
466 } 466 }
467 } 467 }
468 468
469 // must trigger any error after keeper state has been released 469 // must trigger any error after keeper state has been released
470 return (pushed < 0) ? luaL_error( L, "tried to copy unsupported types") : pushed; 470 return (pushed < 0) ? luaL_error( L, "tried to copy unsupported types") : pushed;
471} 471}
472 472
473 473
@@ -478,21 +478,21 @@ LUAG_FUNC( linda_set)
478 */ 478 */
479LUAG_FUNC( linda_count) 479LUAG_FUNC( linda_count)
480{ 480{
481 struct s_Linda* linda = lua_toLinda( L, 1); 481 struct s_Linda* linda = lua_toLinda( L, 1);
482 int pushed; 482 int pushed;
483 483
484 // make sure the keys are of a valid type 484 // make sure the keys are of a valid type
485 check_key_types( L, 2, lua_gettop( L)); 485 check_key_types( L, 2, lua_gettop( L));
486 486
487 { 487 {
488 Keeper* K = which_keeper( linda->U->keepers, LINDA_KEEPER_HASHSEED( linda)); 488 Keeper* K = which_keeper( linda->U->keepers, LINDA_KEEPER_HASHSEED( linda));
489 pushed = keeper_call( linda->U, K->L, KEEPER_API( count), L, linda, 2); 489 pushed = keeper_call( linda->U, K->L, KEEPER_API( count), L, linda, 2);
490 if( pushed < 0) 490 if( pushed < 0)
491 { 491 {
492 return luaL_error( L, "tried to count an invalid key"); 492 return luaL_error( L, "tried to count an invalid key");
493 } 493 }
494 } 494 }
495 return pushed; 495 return pushed;
496} 496}
497 497
498 498
@@ -503,39 +503,39 @@ LUAG_FUNC( linda_count)
503*/ 503*/
504LUAG_FUNC( linda_get) 504LUAG_FUNC( linda_get)
505{ 505{
506 struct s_Linda* const linda = lua_toLinda( L, 1); 506 struct s_Linda* const linda = lua_toLinda( L, 1);
507 int pushed; 507 int pushed;
508 lua_Integer count = luaL_optinteger( L, 3, 1); 508 lua_Integer count = luaL_optinteger( L, 3, 1);
509 luaL_argcheck( L, count >= 1, 3, "count should be >= 1"); 509 luaL_argcheck( L, count >= 1, 3, "count should be >= 1");
510 luaL_argcheck( L, lua_gettop( L) <= 3, 4, "too many arguments"); 510 luaL_argcheck( L, lua_gettop( L) <= 3, 4, "too many arguments");
511 511
512 // make sure the key is of a valid type (throws an error if not the case) 512 // make sure the key is of a valid type (throws an error if not the case)
513 check_key_types( L, 2, 2); 513 check_key_types( L, 2, 2);
514 { 514 {
515 Keeper* K = which_keeper( linda->U->keepers, LINDA_KEEPER_HASHSEED( linda)); 515 Keeper* K = which_keeper( linda->U->keepers, LINDA_KEEPER_HASHSEED( linda));
516 516
517 if( linda->simulate_cancel == CANCEL_NONE) 517 if( linda->simulate_cancel == CANCEL_NONE)
518 { 518 {
519 pushed = keeper_call( linda->U, K->L, KEEPER_API( get), L, linda, 2); 519 pushed = keeper_call( linda->U, K->L, KEEPER_API( get), L, linda, 2);
520 if( pushed > 0) 520 if( pushed > 0)
521 { 521 {
522 keeper_toggle_nil_sentinels( L, lua_gettop( L) - pushed, eLM_FromKeeper); 522 keeper_toggle_nil_sentinels( L, lua_gettop( L) - pushed, eLM_FromKeeper);
523 } 523 }
524 } 524 }
525 else // linda is cancelled 525 else // linda is cancelled
526 { 526 {
527 // do nothing and return lanes.cancel_error 527 // do nothing and return lanes.cancel_error
528 push_unique_key( L, CANCEL_ERROR); 528 push_unique_key( L, CANCEL_ERROR);
529 pushed = 1; 529 pushed = 1;
530 } 530 }
531 // an error can be raised if we attempt to read an unregistered function 531 // an error can be raised if we attempt to read an unregistered function
532 if( pushed < 0) 532 if( pushed < 0)
533 { 533 {
534 return luaL_error( L, "tried to copy unsupported types"); 534 return luaL_error( L, "tried to copy unsupported types");
535 } 535 }
536 } 536 }
537 537
538 return pushed; 538 return pushed;
539} 539}
540 540
541 541
@@ -547,38 +547,38 @@ LUAG_FUNC( linda_get)
547*/ 547*/
548LUAG_FUNC( linda_limit) 548LUAG_FUNC( linda_limit)
549{ 549{
550 struct s_Linda* linda = lua_toLinda( L, 1); 550 struct s_Linda* linda = lua_toLinda( L, 1);
551 int pushed; 551 int pushed;
552 552
553 // make sure we got 3 arguments: the linda, a key and a limit 553 // make sure we got 3 arguments: the linda, a key and a limit
554 luaL_argcheck( L, lua_gettop( L) == 3, 2, "wrong number of arguments"); 554 luaL_argcheck( L, lua_gettop( L) == 3, 2, "wrong number of arguments");
555 // make sure we got a numeric limit 555 // make sure we got a numeric limit
556 luaL_checknumber( L, 3); 556 luaL_checknumber( L, 3);
557 // make sure the key is of a valid type 557 // make sure the key is of a valid type
558 check_key_types( L, 2, 2); 558 check_key_types( L, 2, 2);
559 559
560 { 560 {
561 Keeper* K = which_keeper( linda->U->keepers, LINDA_KEEPER_HASHSEED( linda)); 561 Keeper* K = which_keeper( linda->U->keepers, LINDA_KEEPER_HASHSEED( linda));
562 562
563 if( linda->simulate_cancel == CANCEL_NONE) 563 if( linda->simulate_cancel == CANCEL_NONE)
564 { 564 {
565 pushed = keeper_call( linda->U, K->L, KEEPER_API( limit), L, linda, 2); 565 pushed = keeper_call( linda->U, K->L, KEEPER_API( limit), L, linda, 2);
566 ASSERT_L( pushed == 0 || pushed == 1); // no error, optional boolean value saying if we should wake blocked writer threads 566 ASSERT_L( pushed == 0 || pushed == 1); // no error, optional boolean value saying if we should wake blocked writer threads
567 if( pushed == 1) 567 if( pushed == 1)
568 { 568 {
569 ASSERT_L( lua_type( L, -1) == LUA_TBOOLEAN && lua_toboolean( L, -1) == 1); 569 ASSERT_L( lua_type( L, -1) == LUA_TBOOLEAN && lua_toboolean( L, -1) == 1);
570 SIGNAL_ALL( &linda->read_happened); // To be done from within the 'K' locking area 570 SIGNAL_ALL( &linda->read_happened); // To be done from within the 'K' locking area
571 } 571 }
572 } 572 }
573 else // linda is cancelled 573 else // linda is cancelled
574 { 574 {
575 // do nothing and return lanes.cancel_error 575 // do nothing and return lanes.cancel_error
576 push_unique_key( L, CANCEL_ERROR); 576 push_unique_key( L, CANCEL_ERROR);
577 pushed = 1; 577 pushed = 1;
578 } 578 }
579 } 579 }
580 // propagate pushed boolean if any 580 // propagate pushed boolean if any
581 return pushed; 581 return pushed;
582} 582}
583 583
584 584
@@ -589,35 +589,35 @@ LUAG_FUNC( linda_limit)
589*/ 589*/
590LUAG_FUNC( linda_cancel) 590LUAG_FUNC( linda_cancel)
591{ 591{
592 struct s_Linda* linda = lua_toLinda( L, 1); 592 struct s_Linda* linda = lua_toLinda( L, 1);
593 char const* who = luaL_optstring( L, 2, "both"); 593 char const* who = luaL_optstring( L, 2, "both");
594 594
595 // make sure we got 3 arguments: the linda, a key and a limit 595 // make sure we got 3 arguments: the linda, a key and a limit
596 luaL_argcheck( L, lua_gettop( L) <= 2, 2, "wrong number of arguments"); 596 luaL_argcheck( L, lua_gettop( L) <= 2, 2, "wrong number of arguments");
597 597
598 linda->simulate_cancel = CANCEL_SOFT; 598 linda->simulate_cancel = CANCEL_SOFT;
599 if( strcmp( who, "both") == 0) // tell everyone writers to wake up 599 if( strcmp( who, "both") == 0) // tell everyone writers to wake up
600 { 600 {
601 SIGNAL_ALL( &linda->write_happened); 601 SIGNAL_ALL( &linda->write_happened);
602 SIGNAL_ALL( &linda->read_happened); 602 SIGNAL_ALL( &linda->read_happened);
603 } 603 }
604 else if( strcmp( who, "none") == 0) // reset flag 604 else if( strcmp( who, "none") == 0) // reset flag
605 { 605 {
606 linda->simulate_cancel = CANCEL_NONE; 606 linda->simulate_cancel = CANCEL_NONE;
607 } 607 }
608 else if( strcmp( who, "read") == 0) // tell blocked readers to wake up 608 else if( strcmp( who, "read") == 0) // tell blocked readers to wake up
609 { 609 {
610 SIGNAL_ALL( &linda->write_happened); 610 SIGNAL_ALL( &linda->write_happened);
611 } 611 }
612 else if( strcmp( who, "write") == 0) // tell blocked writers to wake up 612 else if( strcmp( who, "write") == 0) // tell blocked writers to wake up
613 { 613 {
614 SIGNAL_ALL( &linda->read_happened); 614 SIGNAL_ALL( &linda->read_happened);
615 } 615 }
616 else 616 else
617 { 617 {
618 return luaL_error( L, "unknown wake hint '%s'", who); 618 return luaL_error( L, "unknown wake hint '%s'", who);
619 } 619 }
620 return 0; 620 return 0;
621} 621}
622 622
623 623
@@ -633,9 +633,9 @@ LUAG_FUNC( linda_cancel)
633*/ 633*/
634LUAG_FUNC( linda_deep) 634LUAG_FUNC( linda_deep)
635{ 635{
636 struct s_Linda* linda= lua_toLinda( L, 1); 636 struct s_Linda* linda= lua_toLinda( L, 1);
637 lua_pushlightuserdata( L, linda); // just the address 637 lua_pushlightuserdata( L, linda); // just the address
638 return 1; 638 return 1;
639} 639}
640 640
641 641
@@ -649,28 +649,28 @@ LUAG_FUNC( linda_deep)
649 649
650static int linda_tostring( lua_State* L, int idx_, bool_t opt_) 650static int linda_tostring( lua_State* L, int idx_, bool_t opt_)
651{ 651{
652 struct s_Linda* linda = (struct s_Linda*) luaG_todeep( L, linda_id, idx_); 652 struct s_Linda* linda = (struct s_Linda*) luaG_todeep( L, linda_id, idx_);
653 if( !opt_) 653 if( !opt_)
654 { 654 {
655 luaL_argcheck( L, linda, idx_, "expecting a linda object"); 655 luaL_argcheck( L, linda, idx_, "expecting a linda object");
656 } 656 }
657 if( linda != NULL) 657 if( linda != NULL)
658 { 658 {
659 char text[128]; 659 char text[128];
660 int len; 660 int len;
661 if( linda->name[0]) 661 if( linda->name[0])
662 len = sprintf( text, "Linda: %.*s", (int)sizeof(text) - 8, linda->name); 662 len = sprintf( text, "Linda: %.*s", (int)sizeof(text) - 8, linda->name);
663 else 663 else
664 len = sprintf( text, "Linda: %p", linda); 664 len = sprintf( text, "Linda: %p", linda);
665 lua_pushlstring( L, text, len); 665 lua_pushlstring( L, text, len);
666 return 1; 666 return 1;
667 } 667 }
668 return 0; 668 return 0;
669} 669}
670 670
671LUAG_FUNC( linda_tostring) 671LUAG_FUNC( linda_tostring)
672{ 672{
673 return linda_tostring( L, 1, FALSE); 673 return linda_tostring( L, 1, FALSE);
674} 674}
675 675
676 676
@@ -683,24 +683,24 @@ LUAG_FUNC( linda_tostring)
683*/ 683*/
684LUAG_FUNC( linda_concat) 684LUAG_FUNC( linda_concat)
685{ // linda1? linda2? 685{ // linda1? linda2?
686 bool_t atLeastOneLinda = FALSE; 686 bool_t atLeastOneLinda = FALSE;
687 // Lua semantics enforce that one of the 2 arguments is a Linda, but not necessarily both. 687 // Lua semantics enforce that one of the 2 arguments is a Linda, but not necessarily both.
688 if( linda_tostring( L, 1, TRUE)) 688 if( linda_tostring( L, 1, TRUE))
689 { 689 {
690 atLeastOneLinda = TRUE; 690 atLeastOneLinda = TRUE;
691 lua_replace( L, 1); 691 lua_replace( L, 1);
692 } 692 }
693 if( linda_tostring( L, 2, TRUE)) 693 if( linda_tostring( L, 2, TRUE))
694 { 694 {
695 atLeastOneLinda = TRUE; 695 atLeastOneLinda = TRUE;
696 lua_replace( L, 2); 696 lua_replace( L, 2);
697 } 697 }
698 if( !atLeastOneLinda) // should not be possible 698 if( !atLeastOneLinda) // should not be possible
699 { 699 {
700 return luaL_error( L, "internal error: linda_concat called on non-Linda"); 700 return luaL_error( L, "internal error: linda_concat called on non-Linda");
701 } 701 }
702 lua_concat( L, 2); 702 lua_concat( L, 2);
703 return 1; 703 return 1;
704} 704}
705 705
706/* 706/*
@@ -709,9 +709,9 @@ LUAG_FUNC( linda_concat)
709 */ 709 */
710LUAG_FUNC( linda_dump) 710LUAG_FUNC( linda_dump)
711{ 711{
712 struct s_Linda* linda = lua_toLinda( L, 1); 712 struct s_Linda* linda = lua_toLinda( L, 1);
713 ASSERT_L( linda->U == universe_get( L)); 713 ASSERT_L( linda->U == universe_get( L));
714 return keeper_push_linda_storage( linda->U, L, linda, LINDA_KEEPER_HASHSEED( linda)); 714 return keeper_push_linda_storage( linda->U, L, linda, LINDA_KEEPER_HASHSEED( linda));
715} 715}
716 716
717/* 717/*
@@ -720,16 +720,16 @@ LUAG_FUNC( linda_dump)
720 */ 720 */
721LUAG_FUNC( linda_towatch) 721LUAG_FUNC( linda_towatch)
722{ 722{
723 struct s_Linda* linda = lua_toLinda( L, 1); 723 struct s_Linda* linda = lua_toLinda( L, 1);
724 int pushed; 724 int pushed;
725 ASSERT_L( linda->U == universe_get( L)); 725 ASSERT_L( linda->U == universe_get( L));
726 pushed = keeper_push_linda_storage( linda->U, L, linda, LINDA_KEEPER_HASHSEED( linda)); 726 pushed = keeper_push_linda_storage( linda->U, L, linda, LINDA_KEEPER_HASHSEED( linda));
727 if( pushed == 0) 727 if( pushed == 0)
728 { 728 {
729 // if the linda is empty, don't return nil 729 // if the linda is empty, don't return nil
730 pushed = linda_tostring( L, 1, FALSE); 730 pushed = linda_tostring( L, 1, FALSE);
731 } 731 }
732 return pushed; 732 return pushed;
733} 733}
734 734
735/* 735/*
@@ -758,160 +758,160 @@ LUAG_FUNC( linda_towatch)
758*/ 758*/
759static void* linda_id( lua_State* L, DeepOp op_) 759static void* linda_id( lua_State* L, DeepOp op_)
760{ 760{
761 switch( op_) 761 switch( op_)
762 { 762 {
763 case eDO_new: 763 case eDO_new:
764 { 764 {
765 struct s_Linda* s; 765 struct s_Linda* s;
766 size_t name_len = 0; 766 size_t name_len = 0;
767 char const* linda_name = NULL; 767 char const* linda_name = NULL;
768 unsigned long linda_group = 0; 768 unsigned long linda_group = 0;
769 // should have a string and/or a number of the stack as parameters (name and group) 769 // should have a string and/or a number of the stack as parameters (name and group)
770 switch( lua_gettop( L)) 770 switch( lua_gettop( L))
771 { 771 {
772 default: // 0 772 default: // 0
773 break; 773 break;
774 774
775 case 1: // 1 parameter, either a name or a group 775 case 1: // 1 parameter, either a name or a group
776 if( lua_type( L, -1) == LUA_TSTRING) 776 if( lua_type( L, -1) == LUA_TSTRING)
777 { 777 {
778 linda_name = lua_tolstring( L, -1, &name_len); 778 linda_name = lua_tolstring( L, -1, &name_len);
779 } 779 }
780 else 780 else
781 { 781 {
782 linda_group = (unsigned long) lua_tointeger( L, -1); 782 linda_group = (unsigned long) lua_tointeger( L, -1);
783 } 783 }
784 break; 784 break;
785 785
786 case 2: // 2 parameters, a name and group, in that order 786 case 2: // 2 parameters, a name and group, in that order
787 linda_name = lua_tolstring( L, -2, &name_len); 787 linda_name = lua_tolstring( L, -2, &name_len);
788 linda_group = (unsigned long) lua_tointeger( L, -1); 788 linda_group = (unsigned long) lua_tointeger( L, -1);
789 break; 789 break;
790 } 790 }
791 791
792 /* The deep data is allocated separately of Lua stack; we might no 792 /* The deep data is allocated separately of Lua stack; we might no
793 * longer be around when last reference to it is being released. 793 * longer be around when last reference to it is being released.
794 * One can use any memory allocation scheme. 794 * One can use any memory allocation scheme.
795 * just don't use L's allocF because we don't know which state will get the honor of GCing the linda 795 * just don't use L's allocF because we don't know which state will get the honor of GCing the linda
796 */ 796 */
797 s = (struct s_Linda*) malloc( sizeof(struct s_Linda) + name_len); // terminating 0 is already included 797 s = (struct s_Linda*) malloc( sizeof(struct s_Linda) + name_len); // terminating 0 is already included
798 if( s) 798 if( s)
799 { 799 {
800 s->prelude.magic.value = DEEP_VERSION.value; 800 s->prelude.magic.value = DEEP_VERSION.value;
801 SIGNAL_INIT( &s->read_happened); 801 SIGNAL_INIT( &s->read_happened);
802 SIGNAL_INIT( &s->write_happened); 802 SIGNAL_INIT( &s->write_happened);
803 s->U = universe_get( L); 803 s->U = universe_get( L);
804 s->simulate_cancel = CANCEL_NONE; 804 s->simulate_cancel = CANCEL_NONE;
805 s->group = linda_group << KEEPER_MAGIC_SHIFT; 805 s->group = linda_group << KEEPER_MAGIC_SHIFT;
806 s->name[0] = 0; 806 s->name[0] = 0;
807 memcpy( s->name, linda_name, name_len ? name_len + 1 : 0); 807 memcpy( s->name, linda_name, name_len ? name_len + 1 : 0);
808 } 808 }
809 return s; 809 return s;
810 } 810 }
811 811
812 case eDO_delete: 812 case eDO_delete:
813 { 813 {
814 Keeper* K; 814 Keeper* K;
815 struct s_Linda* linda = lua_touserdata( L, 1); 815 struct s_Linda* linda = lua_touserdata( L, 1);
816 ASSERT_L( linda); 816 ASSERT_L( linda);
817 817
818 // Clean associated structures in the keeper state. 818 // Clean associated structures in the keeper state.
819 K = keeper_acquire( linda->U->keepers, LINDA_KEEPER_HASHSEED( linda)); 819 K = keeper_acquire( linda->U->keepers, LINDA_KEEPER_HASHSEED( linda));
820 if( K && K->L) // can be NULL if this happens during main state shutdown (lanes is GC'ed -> no keepers -> no need to cleanup) 820 if( K && K->L) // can be NULL if this happens during main state shutdown (lanes is GC'ed -> no keepers -> no need to cleanup)
821 { 821 {
822 // hopefully this won't ever raise an error as we would jump to the closest pcall site while forgetting to release the keeper mutex... 822 // hopefully this won't ever raise an error as we would jump to the closest pcall site while forgetting to release the keeper mutex...
823 keeper_call( linda->U, K->L, KEEPER_API( clear), L, linda, 0); 823 keeper_call( linda->U, K->L, KEEPER_API( clear), L, linda, 0);
824 } 824 }
825 keeper_release( K); 825 keeper_release( K);
826 826
827 // There aren't any lanes waiting on these lindas, since all proxies have been gc'ed. Right? 827 // There aren't any lanes waiting on these lindas, since all proxies have been gc'ed. Right?
828 SIGNAL_FREE( &linda->read_happened); 828 SIGNAL_FREE( &linda->read_happened);
829 SIGNAL_FREE( &linda->write_happened); 829 SIGNAL_FREE( &linda->write_happened);
830 free( linda); 830 free( linda);
831 return NULL; 831 return NULL;
832 } 832 }
833 833
834 case eDO_metatable: 834 case eDO_metatable:
835 { 835 {
836 836
837 STACK_CHECK( L, 0); 837 STACK_CHECK( L, 0);
838 lua_newtable( L); 838 lua_newtable( L);
839 // metatable is its own index 839 // metatable is its own index
840 lua_pushvalue( L, -1); 840 lua_pushvalue( L, -1);
841 lua_setfield( L, -2, "__index"); 841 lua_setfield( L, -2, "__index");
842 842
843 // protect metatable from external access 843 // protect metatable from external access
844 lua_pushliteral( L, "Linda"); 844 lua_pushliteral( L, "Linda");
845 lua_setfield( L, -2, "__metatable"); 845 lua_setfield( L, -2, "__metatable");
846 846
847 lua_pushcfunction( L, LG_linda_tostring); 847 lua_pushcfunction( L, LG_linda_tostring);
848 lua_setfield( L, -2, "__tostring"); 848 lua_setfield( L, -2, "__tostring");
849 849
850 // Decoda __towatch support 850 // Decoda __towatch support
851 lua_pushcfunction( L, LG_linda_towatch); 851 lua_pushcfunction( L, LG_linda_towatch);
852 lua_setfield( L, -2, "__towatch"); 852 lua_setfield( L, -2, "__towatch");
853 853
854 lua_pushcfunction( L, LG_linda_concat); 854 lua_pushcfunction( L, LG_linda_concat);
855 lua_setfield( L, -2, "__concat"); 855 lua_setfield( L, -2, "__concat");
856 856
857 // protected calls, to ensure associated keeper is always released even in case of error 857 // protected calls, to ensure associated keeper is always released even in case of error
858 // all function are the protected call wrapper, where the actual operation is provided as upvalue 858 // all function are the protected call wrapper, where the actual operation is provided as upvalue
859 // note that this kind of thing can break function lookup as we use the function pointer here and there 859 // note that this kind of thing can break function lookup as we use the function pointer here and there
860 860
861 lua_pushcfunction( L, LG_linda_send); 861 lua_pushcfunction( L, LG_linda_send);
862 lua_pushcclosure( L, LG_linda_protected_call, 1); 862 lua_pushcclosure( L, LG_linda_protected_call, 1);
863 lua_setfield( L, -2, "send"); 863 lua_setfield( L, -2, "send");
864 864
865 lua_pushcfunction( L, LG_linda_receive); 865 lua_pushcfunction( L, LG_linda_receive);
866 lua_pushcclosure( L, LG_linda_protected_call, 1); 866 lua_pushcclosure( L, LG_linda_protected_call, 1);
867 lua_setfield( L, -2, "receive"); 867 lua_setfield( L, -2, "receive");
868 868
869 lua_pushcfunction( L, LG_linda_limit); 869 lua_pushcfunction( L, LG_linda_limit);
870 lua_pushcclosure( L, LG_linda_protected_call, 1); 870 lua_pushcclosure( L, LG_linda_protected_call, 1);
871 lua_setfield( L, -2, "limit"); 871 lua_setfield( L, -2, "limit");
872 872
873 lua_pushcfunction( L, LG_linda_set); 873 lua_pushcfunction( L, LG_linda_set);
874 lua_pushcclosure( L, LG_linda_protected_call, 1); 874 lua_pushcclosure( L, LG_linda_protected_call, 1);
875 lua_setfield( L, -2, "set"); 875 lua_setfield( L, -2, "set");
876 876
877 lua_pushcfunction( L, LG_linda_count); 877 lua_pushcfunction( L, LG_linda_count);
878 lua_pushcclosure( L, LG_linda_protected_call, 1); 878 lua_pushcclosure( L, LG_linda_protected_call, 1);
879 lua_setfield( L, -2, "count"); 879 lua_setfield( L, -2, "count");
880 880
881 lua_pushcfunction( L, LG_linda_get); 881 lua_pushcfunction( L, LG_linda_get);
882 lua_pushcclosure( L, LG_linda_protected_call, 1); 882 lua_pushcclosure( L, LG_linda_protected_call, 1);
883 lua_setfield( L, -2, "get"); 883 lua_setfield( L, -2, "get");
884 884
885 lua_pushcfunction( L, LG_linda_cancel); 885 lua_pushcfunction( L, LG_linda_cancel);
886 lua_setfield( L, -2, "cancel"); 886 lua_setfield( L, -2, "cancel");
887 887
888 lua_pushcfunction( L, LG_linda_deep); 888 lua_pushcfunction( L, LG_linda_deep);
889 lua_setfield( L, -2, "deep"); 889 lua_setfield( L, -2, "deep");
890 890
891 lua_pushcfunction( L, LG_linda_dump); 891 lua_pushcfunction( L, LG_linda_dump);
892 lua_pushcclosure( L, LG_linda_protected_call, 1); 892 lua_pushcclosure( L, LG_linda_protected_call, 1);
893 lua_setfield( L, -2, "dump"); 893 lua_setfield( L, -2, "dump");
894 894
895 // some constants 895 // some constants
896 lua_pushliteral( L, BATCH_SENTINEL); 896 lua_pushliteral( L, BATCH_SENTINEL);
897 lua_setfield( L, -2, "batched"); 897 lua_setfield( L, -2, "batched");
898 898
899 push_unique_key( L, NIL_SENTINEL); 899 push_unique_key( L, NIL_SENTINEL);
900 lua_setfield( L, -2, "null"); 900 lua_setfield( L, -2, "null");
901 901
902 STACK_END( L, 1); 902 STACK_END( L, 1);
903 return NULL; 903 return NULL;
904 } 904 }
905 905
906 case eDO_module: 906 case eDO_module:
907 // linda is a special case because we know lanes must be loaded from the main lua state 907 // linda is a special case because we know lanes must be loaded from the main lua state
908 // to be able to ever get here, so we know it will remain loaded as long a the main state is around 908 // to be able to ever get here, so we know it will remain loaded as long a the main state is around
909 // in other words, forever. 909 // in other words, forever.
910 default: 910 default:
911 { 911 {
912 return NULL; 912 return NULL;
913 } 913 }
914 } 914 }
915} 915}
916 916
917/* 917/*
@@ -921,17 +921,17 @@ static void* linda_id( lua_State* L, DeepOp op_)
921 */ 921 */
922LUAG_FUNC( linda) 922LUAG_FUNC( linda)
923{ 923{
924 int const top = lua_gettop( L); 924 int const top = lua_gettop( L);
925 luaL_argcheck( L, top <= 2, top, "too many arguments"); 925 luaL_argcheck( L, top <= 2, top, "too many arguments");
926 if( top == 1) 926 if( top == 1)
927 { 927 {
928 int const t = lua_type( L, 1); 928 int const t = lua_type( L, 1);
929 luaL_argcheck( L, t == LUA_TSTRING || t == LUA_TNUMBER, 1, "wrong parameter (should be a string or a number)"); 929 luaL_argcheck( L, t == LUA_TSTRING || t == LUA_TNUMBER, 1, "wrong parameter (should be a string or a number)");
930 } 930 }
931 else if( top == 2) 931 else if( top == 2)
932 { 932 {
933 luaL_checktype( L, 1, LUA_TSTRING); 933 luaL_checktype( L, 1, LUA_TSTRING);
934 luaL_checktype( L, 2, LUA_TNUMBER); 934 luaL_checktype( L, 2, LUA_TNUMBER);
935 } 935 }
936 return luaG_newdeepuserdata( L, linda_id, 0); 936 return luaG_newdeepuserdata( L, linda_id, 0);
937} 937}