summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorBenoit Germain <bnt.germain@gmail.com>2012-08-22 21:36:37 +0200
committerBenoit Germain <bnt.germain@gmail.com>2012-08-22 21:36:37 +0200
commitf0b1c6d629464c0a59ac78382d86f434e74c2162 (patch)
treee6788f8e7c0e859cd5f8d9254a922e187d9e7938 /src
parenta9075ff6cf43e99cee994f5e77d0e1e54cb8dbac (diff)
downloadlanes-3.2.0.tar.gz
lanes-3.2.0.tar.bz2
lanes-3.2.0.zip
lanes version 3.2.0v3.2.0
* keeper internals implemented in C instead of Lua for better performances * fixed arguments checks in linda:limit() and linda:set()
Diffstat (limited to 'src')
-rw-r--r--src/keeper.c390
-rw-r--r--src/keeper.h25
-rw-r--r--src/lanes-keeper.lua2
-rw-r--r--src/lanes.c31
4 files changed, 427 insertions, 21 deletions
diff --git a/src/keeper.c b/src/keeper.c
index 444a98e..86c69e2 100644
--- a/src/keeper.c
+++ b/src/keeper.c
@@ -14,7 +14,7 @@
14 --[[ 14 --[[
15 =============================================================================== 15 ===============================================================================
16 16
17 Copyright (C) 2011 Benoit Germain <bnt.germain@gmail.com> 17 Copyright (C) 2011-2012 Benoit Germain <bnt.germain@gmail.com>
18 18
19 Permission is hereby granted, free of charge, to any person obtaining a copy 19 Permission is hereby granted, free of charge, to any person obtaining a copy
20 of this software and associated documentation files (the "Software"), to deal 20 of this software and associated documentation files (the "Software"), to deal
@@ -50,6 +50,374 @@
50#include "tools.h" 50#include "tools.h"
51#include "keeper.h" 51#include "keeper.h"
52 52
53#if KEEPER_MODEL == KEEPER_MODEL_C
54//###################################################################################
55// Keeper implementation
56//###################################################################################
57
58typedef struct
59{
60 int first;
61 int count;
62 int limit;
63} keeper_fifo;
64
65// replaces the fifo ud by its uservalue on the stack
66static keeper_fifo* prepare_fifo_access( lua_State* L, int idx)
67{
68 keeper_fifo* fifo = (keeper_fifo*) lua_touserdata( L, idx);
69 if( fifo)
70 {
71 idx = lua_absindex( L, idx);
72 STACK_GROW( L, 1);
73 // we can replace the fifo userdata in the stack without fear of it being GCed, there are other references around
74 lua_getuservalue( L, idx);
75 lua_replace( L, idx);
76 }
77 return fifo;
78}
79
80// in: nothing
81// out: { first = 1, count = 0, limit = -1}
82static void fifo_new( lua_State* L)
83{
84 keeper_fifo* fifo;
85 STACK_GROW( L, 2);
86 fifo = (keeper_fifo*) lua_newuserdata( L, sizeof( keeper_fifo));
87 fifo->first = 1;
88 fifo->count = 0;
89 fifo->limit = -1;
90 lua_newtable( L);
91 lua_setuservalue( L, -2);
92}
93
94// in: expect fifo ... on top of the stack
95// out: nothing, removes all pushed values on the stack
96static void fifo_push( lua_State* L, keeper_fifo* fifo, int _count)
97{
98 int idx = lua_gettop( L) - _count;
99 int start = fifo->first + fifo->count - 1;
100 int i;
101 // pop all additional arguments, storing them in the fifo
102 for( i = _count; i >= 1; -- i)
103 {
104 // store in the fifo the value at the top of the stack at the specified index, popping it from the stack
105 lua_rawseti( L, idx, start + i);
106 }
107 fifo->count += _count;
108}
109
110// in: fifo
111// out: ...|nothing
112// expects exactly 1 value on the stack!
113// currently only called with a count of 1, but this may change in the future
114// function assumes that there is enough data in the fifo to satisfy the request
115static void fifo_peek( lua_State* L, keeper_fifo* fifo, int _count)
116{
117 int i;
118 STACK_GROW( L, _count);
119 for( i = 0; i < _count; ++ i)
120 {
121 lua_rawgeti( L, 1, fifo->first + i);
122 }
123}
124
125// in: fifo
126// out: pushes as many items as required on the stack (function assumes they exist in sufficient number)
127static void fifo_pop( lua_State* L, keeper_fifo* fifo, int _count)
128{
129 int fifo_idx = lua_gettop( L); // ... fifo
130 int i;
131 // each iteration pushes a value on the stack!
132 STACK_GROW( L, _count + 1);
133 for( i = 0; i < _count; ++ i)
134 {
135 int at = fifo->first + i;
136 lua_rawgeti( L, fifo_idx, at); // ... fifo val
137 lua_pushnil( L); // ... fifo val nil
138 lua_rawseti( L, fifo_idx, at); // ... fifo val
139 }
140 fifo->first += _count;
141 fifo->count -= _count;
142}
143
144// in: linda_ud expected at *absolute* stack slot idx
145// out: fifos[ud]
146static void* const fifos_key = (void*) prepare_fifo_access;
147static void push_table( lua_State* L, int idx)
148{
149 STACK_GROW( L, 4);
150 STACK_CHECK( L)
151 idx = lua_absindex( L, idx);
152 lua_pushlightuserdata( L, fifos_key); // ud fifos_key
153 lua_rawget( L, LUA_REGISTRYINDEX); // ud fifos
154 lua_pushvalue( L, idx); // ud fifos ud
155 lua_rawget( L, -2); // ud fifos fifos[ud]
156 STACK_MID( L, 2);
157 if( lua_isnil( L, -1))
158 {
159 lua_pop( L, 1); // ud fifos
160 // add a new fifos table for this linda
161 lua_newtable( L); // ud fifos fifos[ud]
162 lua_pushvalue( L, idx); // ud fifos fifos[ud] ud
163 lua_pushvalue( L, -2); // ud fifos fifos[ud] ud fifos[ud]
164 lua_rawset( L, -4); // ud fifos fifos[ud]
165 }
166 lua_remove( L, -2); // ud fifos[ud]
167 STACK_END( L, 1);
168}
169
170// in: linda_ud
171int keepercall_clear( lua_State* L)
172{
173 STACK_GROW( L, 3);
174 lua_pushlightuserdata( L, fifos_key); // ud fifos_key
175 lua_rawget( L, LUA_REGISTRYINDEX); // ud fifos
176 lua_pushvalue( L, 1); // ud fifos ud
177 lua_pushnil( L); // ud fifos ud nil
178 lua_rawset( L, -3); // ud fifos
179 lua_pop( L, 1); // ud
180 return 0;
181}
182
183
184// in: linda_ud, key, ...
185// out: true|false
186int keepercall_send( lua_State* L)
187{
188 keeper_fifo* fifo;
189 int n = lua_gettop( L) - 2;
190 push_table( L, 1); // ud key ... fifos
191 // get the fifo associated to this key in this linda, create it if it doesn't exist
192 lua_pushvalue( L, 2); // ud key ... fifos key
193 lua_rawget( L, -2); // ud key ... fifos fifo
194 if( lua_isnil( L, -1))
195 {
196 lua_pop( L, 1); // ud key ... fifos
197 fifo_new( L); // ud key ... fifos fifo
198 lua_pushvalue( L, 2); // ud key ... fifos fifo key
199 lua_pushvalue( L, -2); // ud key ... fifos fifo key fifo
200 lua_rawset( L, -4); // ud key ... fifos fifo
201 }
202 lua_remove( L, -2); // ud key ... fifo
203 fifo = (keeper_fifo*) lua_touserdata( L, -1);
204 if( fifo->limit >= 0 && fifo->count + n > fifo->limit)
205 {
206 lua_settop( L, 0); //
207 lua_pushboolean( L, 0); // false
208 }
209 else
210 {
211 fifo = prepare_fifo_access( L, -1);
212 lua_replace( L, 2); // ud fifo ...
213 fifo_push( L, fifo, n); // ud fifo
214 lua_settop( L, 0); //
215 lua_pushboolean( L, 1); // true
216 }
217 return 1;
218}
219
220// in: linda_ud, key [, key]?
221// out: (val, key) or nothing
222int keepercall_receive( lua_State* L)
223{
224 int top = lua_gettop( L);
225 int i;
226 keeper_fifo* fifo;
227 push_table( L, 1); // ud keys fifos
228 lua_replace( L, 1); // fifos keys
229 for( i = 2; i <= top; ++ i)
230 {
231 lua_pushvalue( L, i); // fifos keys key[i]
232 lua_rawget( L, 1); // fifos keys fifo
233 fifo = prepare_fifo_access( L, -1); // fifos keys fifo
234 if( fifo && fifo->count > 0)
235 {
236 fifo_pop( L, fifo, 1); // fifos keys fifo val
237 if( !lua_isnil( L, -1))
238 {
239 lua_replace( L, 1); // val keys fifo
240 if( i != 2)
241 {
242 lua_pushvalue( L, i); // val keys fifo key[i]
243 lua_replace( L, 2); // val key keys fifo
244 }
245 lua_settop( L, 2); // val key
246 return 2;
247 }
248 }
249 lua_settop( L, top); // data keys
250 }
251 // nothing to receive
252 return 0;
253}
254
255//in: linda_ud key mincount [maxcount]
256int keepercall_receive_batched( lua_State* L)
257{
258 int const min_count = (int) lua_tointeger( L, 3);
259 if( min_count > 0)
260 {
261 keeper_fifo* fifo;
262 int const max_count = (int) luaL_optinteger( L, 4, min_count);
263 lua_settop( L, 2); // ud key
264 push_table( L, 1); // ud key fifos
265 lua_replace( L, 1); // fifos key
266 lua_rawget( L, -2); // fifos fifo
267 lua_remove( L, 1); // fifo
268 fifo = prepare_fifo_access( L, 1); // fifo
269 if( fifo && fifo->count >= min_count)
270 {
271 fifo_pop( L, fifo, min( max_count, fifo->count)); // fifo ...
272 }
273 return lua_gettop( L) - 1;
274 }
275 else
276 {
277 return 0;
278 }
279}
280
281// in: linda_ud key n
282// out: nothing
283int keepercall_limit( lua_State* L)
284{
285 keeper_fifo* fifo;
286 int limit = (int) lua_tointeger( L, 3);
287 push_table( L, 1); // ud key n fifos
288 lua_replace( L, 1); // fifos key n
289 lua_pop( L, 1); // fifos key
290 lua_pushvalue( L, -1); // fifos key key
291 lua_rawget( L, -3); // fifos key fifo
292 fifo = (keeper_fifo*) lua_touserdata( L, -1);
293 if( !fifo)
294 {
295 lua_pop( L, 1); // fifos key
296 fifo_new( L); // fifos key fifo
297 fifo = (keeper_fifo*) lua_touserdata( L, -1);
298 lua_rawset( L, -3); // fifos
299 }
300 fifo->limit = limit;
301 return 0;
302}
303
304//in: linda_ud key [val]
305int keepercall_set( lua_State* L)
306{
307 // make sure we have a value on the stack
308 if( lua_gettop( L) == 2)
309 {
310 lua_pushnil( L);
311 }
312 push_table( L, 1); // ud key val fifos
313 lua_replace( L, 1); // fifos key val
314 if( !lua_isnil( L, 3)) // replace contents stored at the specified key?
315 {
316 keeper_fifo* fifo;
317 fifo_new( L); // fifos key val fifo
318 lua_pushvalue( L, 2); // fifos key val fifo key
319 lua_pushvalue( L, -2); // fifos key val fifo key fifo
320 lua_rawset( L, 1); // fifos key val fifo
321 fifo = prepare_fifo_access( L, -1);
322 lua_insert( L, -2); // fifos key fifo val
323 fifo_push( L, fifo, 1); // fifos key fifo
324 }
325 else
326 {
327 // val == nil => stack contents: fifos key nil => remove the fifo associated with the current key
328 lua_rawset( L, 1); // fifos
329 }
330 return 0;
331}
332
333// in: linda_ud key
334int keepercall_get( lua_State* L)
335{
336 keeper_fifo* fifo;
337 push_table( L, 1); // ud key fifos
338 lua_replace( L, 1); // fifos key
339 lua_rawget( L, 1); // fifos fifo
340 fifo = prepare_fifo_access( L, -1); // fifos fifo
341 if( fifo && fifo->count > 0)
342 {
343 lua_remove( L, 1); // fifo
344 // read one value off the fifo
345 fifo_peek( L, fifo, 1); // fifo ...
346 return 1;
347 }
348 // no fifo was ever registered for this key, or it is empty
349 return 0;
350}
351
352// in: linda_ud [, key [, ...]]
353int keepercall_count( lua_State* L)
354{
355 int top;
356 push_table( L, 1); // ud keys fifos
357 switch( lua_gettop( L))
358 {
359 // no key is specified: return a table giving the count of all known keys
360 case 2: // ud fifos
361 lua_newtable( L); // ud fifos out
362 lua_replace( L, 1); // out fifos
363 lua_pushnil( L); // out fifos nil
364 while( lua_next( L, 2)) // out fifos key fifo
365 {
366 keeper_fifo* fifo = prepare_fifo_access( L, -1); // out fifos key fifo
367 lua_pop( L, 1); // out fifos key
368 lua_pushvalue( L, -1); // out fifos key key
369 lua_pushinteger( L, fifo->count); // out fifos key key count
370 lua_rawset( L, -5); // out fifos key
371 }
372 lua_pop( L, 1); // out
373 break;
374
375 // 1 key is specified: return its count
376 case 3: // ud key fifos
377 {
378 keeper_fifo* fifo;
379 lua_replace( L, 1); // fifos key
380 lua_rawget( L, -2); // fifos fifo
381 fifo = prepare_fifo_access( L, -1); // fifos fifo
382 lua_pushinteger( L, fifo->count); // fifos fifo count
383 lua_replace( L, -3); // count fifo
384 lua_pop( L, 1); // count
385 }
386 break;
387
388 // a variable number of keys is specified: return a table of their counts
389 default: // ud keys fifos
390 lua_newtable( L); // ud keys fifos out
391 lua_replace( L, 1); // out keys fifos
392 // shifts all keys up in the stack. potentially slow if there are a lot of them, but then it should be bearable
393 lua_insert( L, 2); // out fifos keys
394 while( (top = lua_gettop( L)) > 2)
395 {
396 keeper_fifo* fifo;
397 lua_pushvalue( L, -1); // out fifos keys key
398 lua_rawget( L, 2); // out fifos keys fifo
399 fifo = prepare_fifo_access( L, -1); // out fifos keys fifo
400 lua_pop( L, 1); // out fifos keys
401 if( fifo)
402 {
403 lua_pushinteger( L, fifo->count); // out fifos keys count
404 lua_rawset( L, 1); // out fifos keys
405 }
406 else
407 {
408 lua_pop( L, 1); // out fifos keys
409 }
410 }
411 lua_pop( L, 1); // out
412 }
413 return 1;
414}
415#endif // KEEPER_MODEL == KEEPER_MODEL_C
416
417//###################################################################################
418// Keeper API, accessed from linda methods
419//###################################################################################
420
53/*---=== Keeper states ===--- 421/*---=== Keeper states ===---
54*/ 422*/
55 423
@@ -115,6 +483,14 @@ char const* init_keepers( int const _nbKeepers, lua_CFunction _on_state_create)
115 lua_concat( K, 2); 483 lua_concat( K, 2);
116 lua_setglobal( K, "decoda_name"); 484 lua_setglobal( K, "decoda_name");
117 485
486#if KEEPER_MODEL == KEEPER_MODEL_C
487 // create the fifos table in the keeper state
488 lua_pushlightuserdata( K, fifos_key);
489 lua_newtable( K);
490 lua_rawset( K, LUA_REGISTRYINDEX);
491#endif // KEEPER_MODEL == KEEPER_MODEL_C
492
493#if KEEPER_MODEL == KEEPER_MODEL_LUA
118 // use package.loaders[2] to find keeper microcode 494 // use package.loaders[2] to find keeper microcode
119 lua_getglobal( K, "package"); // package 495 lua_getglobal( K, "package"); // package
120 lua_getfield( K, -1, "loaders"); // package package.loaders 496 lua_getfield( K, -1, "loaders"); // package package.loaders
@@ -132,6 +508,7 @@ char const* init_keepers( int const _nbKeepers, lua_CFunction _on_state_create)
132 } // package package.loaders 508 } // package package.loaders
133 STACK_MID( K, 2); 509 STACK_MID( K, 2);
134 lua_pop( K, 2); 510 lua_pop( K, 2);
511#endif // KEEPER_MODEL == KEEPER_MODEL_LUA
135 STACK_END( K, 0) 512 STACK_END( K, 0)
136 MUTEX_INIT( &GKeepers[i].lock_); 513 MUTEX_INIT( &GKeepers[i].lock_);
137 GKeepers[i].L = K; 514 GKeepers[i].L = K;
@@ -207,7 +584,7 @@ struct s_Keeper *keeper_acquire( const void *ptr)
207 * 584 *
208 * Pointers are often aligned by 8 or so - ignore the low order bits 585 * Pointers are often aligned by 8 or so - ignore the low order bits
209 */ 586 */
210 unsigned int i= ((unsigned long)(ptr) >> 3) % GNbKeepers; 587 unsigned int i= ((uintptr_t)(ptr) >> 3) % GNbKeepers;
211 struct s_Keeper *K= &GKeepers[i]; 588 struct s_Keeper *K= &GKeepers[i];
212 589
213 MUTEX_LOCK( &K->lock_); 590 MUTEX_LOCK( &K->lock_);
@@ -259,16 +636,15 @@ void keeper_toggle_nil_sentinels( lua_State *L, int _val_i, int _nil_to_sentinel
259* 636*
260* Returns: number of return values (pushed to 'L') or -1 in case of error 637* Returns: number of return values (pushed to 'L') or -1 in case of error
261*/ 638*/
262int keeper_call( lua_State *K, char const *func_name, lua_State *L, void *linda, uint_t starting_index) 639int keeper_call( lua_State *K, keeper_api_t _func, lua_State *L, void *linda, uint_t starting_index)
263{ 640{
264 int const args = starting_index ? (lua_gettop(L) - starting_index +1) : 0; 641 int const args = starting_index ? (lua_gettop( L) - starting_index + 1) : 0;
265 int const Ktos = lua_gettop(K); 642 int const Ktos = lua_gettop( K);
266 int retvals = -1; 643 int retvals = -1;
267 644
268 STACK_GROW( K, 2); 645 STACK_GROW( K, 2);
269 646
270 lua_getglobal( K, func_name); 647 PUSH_KEEPER_FUNC( K, _func);
271 ASSERT_L( lua_isfunction(K, -1));
272 648
273 lua_pushlightuserdata( K, linda); 649 lua_pushlightuserdata( K, linda);
274 650
diff --git a/src/keeper.h b/src/keeper.h
index 6c4c6f9..a0ea8c5 100644
--- a/src/keeper.h
+++ b/src/keeper.h
@@ -13,7 +13,30 @@ void populate_keepers( lua_State *L);
13struct s_Keeper *keeper_acquire( const void *ptr); 13struct s_Keeper *keeper_acquire( const void *ptr);
14void keeper_release( struct s_Keeper *K); 14void keeper_release( struct s_Keeper *K);
15void keeper_toggle_nil_sentinels( lua_State *L, int _val_i, int _nil_to_sentinel); 15void keeper_toggle_nil_sentinels( lua_State *L, int _val_i, int _nil_to_sentinel);
16int keeper_call( lua_State *K, char const *func_name, lua_State *L, void *linda, uint_t starting_index);
17 16
17#define KEEPER_MODEL_LUA 1
18#define KEEPER_MODEL_C 2
19#define KEEPER_MODEL KEEPER_MODEL_C
20
21#if KEEPER_MODEL == KEEPER_MODEL_LUA
22typedef char const* keeper_api_t;
23#define KEEPER_API( _op) #_op
24#define PUSH_KEEPER_FUNC( K, _api) lua_getglobal( K, _api)
25#elif KEEPER_MODEL == KEEPER_MODEL_C
26typedef lua_CFunction keeper_api_t;
27#define KEEPER_API( _op) keepercall_ ## _op
28#define PUSH_KEEPER_FUNC lua_pushcfunction
29// lua_Cfunctions to run inside a keeper state (formerly implemented in Lua)
30int keepercall_clear( lua_State* L);
31int keepercall_send( lua_State* L);
32int keepercall_receive( lua_State* L);
33int keepercall_receive_batched( lua_State* L);
34int keepercall_limit( lua_State* L);
35int keepercall_get( lua_State* L);
36int keepercall_set( lua_State* L);
37int keepercall_count( lua_State* L);
38#endif // KEEPER_MODEL
39
40int keeper_call( lua_State *K, keeper_api_t _func, lua_State *L, void *linda, uint_t starting_index);
18 41
19#endif // __keeper_h__ \ No newline at end of file 42#endif // __keeper_h__ \ No newline at end of file
diff --git a/src/lanes-keeper.lua b/src/lanes-keeper.lua
index 1f17599..b07d6a9 100644
--- a/src/lanes-keeper.lua
+++ b/src/lanes-keeper.lua
@@ -2,6 +2,8 @@
2-- KEEPER.LUA 2-- KEEPER.LUA
3-- 3--
4-- Keeper state logic 4-- Keeper state logic
5-- DEPRECATED BY THE EQUIVALENT C IMPLEMENTATION, KEPT FOR REFERENCE ONLY
6-- SHOULD NOT BE PART OF THE INSTALLATION ANYMORE
5-- 7--
6-- This code is read in for each "keeper state", which are the hidden, inter- 8-- This code is read in for each "keeper state", which are the hidden, inter-
7-- mediate data stores used by Lanes inter-state communication objects. 9-- mediate data stores used by Lanes inter-state communication objects.
diff --git a/src/lanes.c b/src/lanes.c
index 8f5768f..9f455b2 100644
--- a/src/lanes.c
+++ b/src/lanes.c
@@ -51,7 +51,7 @@
51 * ... 51 * ...
52 */ 52 */
53 53
54char const* VERSION = "3.1.6"; 54char const* VERSION = "3.2.0";
55 55
56/* 56/*
57=============================================================================== 57===============================================================================
@@ -309,7 +309,7 @@ LUAG_FUNC( linda_send)
309 for( ;;) 309 for( ;;)
310 { 310 {
311 STACK_MID(KL, 0) 311 STACK_MID(KL, 0)
312 pushed = keeper_call( KL, "send", L, linda, key_i); 312 pushed = keeper_call( KL, KEEPER_API( send), L, linda, key_i);
313 if( pushed < 0) 313 if( pushed < 0)
314 { 314 {
315 break; 315 break;
@@ -410,7 +410,7 @@ LUAG_FUNC( linda_receive)
410 struct s_Linda *linda = lua_toLinda( L, 1); 410 struct s_Linda *linda = lua_toLinda( L, 1);
411 int pushed, expected_pushed_min, expected_pushed_max; 411 int pushed, expected_pushed_min, expected_pushed_max;
412 bool_t cancel = FALSE; 412 bool_t cancel = FALSE;
413 char *keeper_receive; 413 keeper_api_t keeper_receive;
414 414
415 time_d timeout = -1.0; 415 time_d timeout = -1.0;
416 uint_t key_i = 2; 416 uint_t key_i = 2;
@@ -440,7 +440,7 @@ LUAG_FUNC( linda_receive)
440 // make sure the keys are of a valid type 440 // make sure the keys are of a valid type
441 check_key_types( L, key_i, key_i); 441 check_key_types( L, key_i, key_i);
442 // receive multiple values from a single slot 442 // receive multiple values from a single slot
443 keeper_receive = "receive_batched"; 443 keeper_receive = KEEPER_API( receive_batched);
444 // we expect a user-defined amount of return value 444 // we expect a user-defined amount of return value
445 expected_pushed_min = (int)luaL_checkinteger( L, key_i + 1); 445 expected_pushed_min = (int)luaL_checkinteger( L, key_i + 1);
446 expected_pushed_max = (int)luaL_optinteger( L, key_i + 2, expected_pushed_min); 446 expected_pushed_max = (int)luaL_optinteger( L, key_i + 2, expected_pushed_min);
@@ -454,7 +454,7 @@ LUAG_FUNC( linda_receive)
454 // make sure the keys are of a valid type 454 // make sure the keys are of a valid type
455 check_key_types( L, key_i, lua_gettop( L)); 455 check_key_types( L, key_i, lua_gettop( L));
456 // receive a single value, checking multiple slots 456 // receive a single value, checking multiple slots
457 keeper_receive = "receive"; 457 keeper_receive = KEEPER_API( receive);
458 // we expect a single (value, key) pair of returned values 458 // we expect a single (value, key) pair of returned values
459 expected_pushed_min = expected_pushed_max = 2; 459 expected_pushed_min = expected_pushed_max = 2;
460 } 460 }
@@ -558,6 +558,7 @@ LUAG_FUNC( linda_set)
558 struct s_Linda *linda = lua_toLinda( L, 1); 558 struct s_Linda *linda = lua_toLinda( L, 1);
559 bool_t has_value = !lua_isnil( L, 3); 559 bool_t has_value = !lua_isnil( L, 3);
560 luaL_argcheck( L, linda, 1, "expected a linda object!"); 560 luaL_argcheck( L, linda, 1, "expected a linda object!");
561 luaL_argcheck( L, lua_gettop( L) <= 3, 4, "too many arguments");
561 562
562 // make sure the key is of a valid type 563 // make sure the key is of a valid type
563 check_key_types( L, 2, 2); 564 check_key_types( L, 2, 2);
@@ -566,7 +567,7 @@ LUAG_FUNC( linda_set)
566 int pushed; 567 int pushed;
567 struct s_Keeper *K = keeper_acquire( linda); 568 struct s_Keeper *K = keeper_acquire( linda);
568 // no nil->sentinel toggling, we really clear the linda contents for the given key with a set() 569 // no nil->sentinel toggling, we really clear the linda contents for the given key with a set()
569 pushed = keeper_call( K->L, "set", L, linda, 2); 570 pushed = keeper_call( K->L, KEEPER_API( set), L, linda, 2);
570 if( pushed >= 0) // no error? 571 if( pushed >= 0) // no error?
571 { 572 {
572 ASSERT_L( pushed == 0); 573 ASSERT_L( pushed == 0);
@@ -606,7 +607,7 @@ LUAG_FUNC( linda_count)
606 607
607 { 608 {
608 struct s_Keeper *K = keeper_acquire( linda); 609 struct s_Keeper *K = keeper_acquire( linda);
609 pushed = keeper_call( K->L, "count", L, linda, 2); 610 pushed = keeper_call( K->L, KEEPER_API( count), L, linda, 2);
610 keeper_release( K); 611 keeper_release( K);
611 if( pushed < 0) 612 if( pushed < 0)
612 { 613 {
@@ -634,7 +635,7 @@ LUAG_FUNC( linda_get)
634 635
635 { 636 {
636 struct s_Keeper *K = keeper_acquire( linda); 637 struct s_Keeper *K = keeper_acquire( linda);
637 pushed = keeper_call( K->L, "get", L, linda, 2); 638 pushed = keeper_call( K->L, KEEPER_API( get), L, linda, 2);
638 ASSERT_L( pushed==0 || pushed==1 ); 639 ASSERT_L( pushed==0 || pushed==1 );
639 if( pushed > 0) 640 if( pushed > 0)
640 { 641 {
@@ -659,15 +660,19 @@ LUAG_FUNC( linda_get)
659*/ 660*/
660LUAG_FUNC( linda_limit) 661LUAG_FUNC( linda_limit)
661{ 662{
662 struct s_Linda *linda= lua_toLinda( L, 1 ); 663 struct s_Linda* linda= lua_toLinda( L, 1 );
663 664
664 luaL_argcheck( L, linda, 1, "expected a linda object!"); 665 luaL_argcheck( L, linda, 1, "expected a linda object!");
666 // make sure we got a key and a limit
667 luaL_argcheck( L, lua_gettop( L) == 3, 2, "wrong number of arguments");
668 // make sure we got a numeric limit
669 luaL_checknumber( L, 3);
665 // make sure the key is of a valid type 670 // make sure the key is of a valid type
666 check_key_types( L, 2, 2); 671 check_key_types( L, 2, 2);
667 672
668 { 673 {
669 struct s_Keeper *K = keeper_acquire( linda); 674 struct s_Keeper* K = keeper_acquire( linda);
670 int pushed = keeper_call( K->L, "limit", L, linda, 2); 675 int pushed = keeper_call( K->L, KEEPER_API( limit), L, linda, 2);
671 ASSERT_L( pushed <= 0); // either error or no return values 676 ASSERT_L( pushed <= 0); // either error or no return values
672 keeper_release( K); 677 keeper_release( K);
673 // must trigger error after keeper state has been released 678 // must trigger error after keeper state has been released
@@ -825,8 +830,8 @@ static void linda_id( lua_State *L, char const * const which)
825 K= keeper_acquire(s); 830 K= keeper_acquire(s);
826 if( K && K->L) // can be NULL if this happens during main state shutdown (lanes is GC'ed -> no keepers -> no need to cleanup) 831 if( K && K->L) // can be NULL if this happens during main state shutdown (lanes is GC'ed -> no keepers -> no need to cleanup)
827 { 832 {
828 keeper_call( K->L, "clear", L, s, 0 ); 833 keeper_call( K->L, KEEPER_API( clear), L, s, 0 );
829 keeper_release(K); 834 keeper_release( K);
830 } 835 }
831 836
832 /* There aren't any lanes waiting on these lindas, since all proxies 837 /* There aren't any lanes waiting on these lindas, since all proxies