From f0b1c6d629464c0a59ac78382d86f434e74c2162 Mon Sep 17 00:00:00 2001
From: Benoit Germain
Date: Wed, 22 Aug 2012 21:36:37 +0200
Subject: lanes version 3.2.0 * keeper internals implemented in C instead of
Lua for better performances * fixed arguments checks in linda:limit() and
linda:set()
---
ABOUT | 2 +-
CHANGES | 4 +
COPYRIGHT | 2 +-
Makefile | 3 +-
docs/index.html | 6 +-
src/keeper.c | 390 ++++++++++++++++++++++++++++++++++++++++++++++++++-
src/keeper.h | 25 +++-
src/lanes-keeper.lua | 2 +
src/lanes.c | 31 ++--
9 files changed, 437 insertions(+), 28 deletions(-)
diff --git a/ABOUT b/ABOUT
index 260fb5c..258ca57 100644
--- a/ABOUT
+++ b/ABOUT
@@ -3,7 +3,7 @@ Lua Lanes
---------
Lanes is a lightweight, native, lazy evaluating multithreading library for
-Lua 5.1. It allows efficient use of multicore processors in Lua, by passing
+Lua 5.1 and Lua 5.2. It allows efficient use of multicore processors in Lua, by passing
function calls into separate OS threads, and separate Lua states.
No locking of the threads is needed, only launching and waiting for (with an
diff --git a/CHANGES b/CHANGES
index 30f73c2..cc7b4a2 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,5 +1,9 @@
CHANGES:
+CHANGE 45: BGe 21-Aug-2012
+ * keeper internals implemented in C instead of Lua for better performances
+ * fixed arguments checks in linda:limit() and linda:set()
+
CHANGE 44: BGe 13-Aug-2012
* lanes code updated to build against Lua 5.1 and Lua 5.2
* removed the search for MSVCR80.DLL when building for MinGW32 since it no longer seems to be necessary
diff --git a/COPYRIGHT b/COPYRIGHT
index 2fdb982..615a79b 100644
--- a/COPYRIGHT
+++ b/COPYRIGHT
@@ -7,7 +7,7 @@ For details and rationale, see http://www.lua.org/license.html
===============================================================================
Copyright (C) 2007-11 Asko Kauppi,
-Copyright (C) 2010-11 Benoit Germain,
+Copyright (C) 2010-12 Benoit Germain,
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
diff --git a/Makefile b/Makefile
index c5c41b1..261504d 100644
--- a/Makefile
+++ b/Makefile
@@ -197,11 +197,10 @@ LUA_SHAREDIR=$(DESTDIR)/share/lua/5.1
#
# AKa 17-Oct: changed to use 'install -m 644' and 'cp -p'
#
-install: $(_TARGET_SO) src/lanes.lua src/lanes-keeper.lua
+install: $(_TARGET_SO) src/lanes.lua
mkdir -p $(LUA_LIBDIR) $(LUA_LIBDIR)/lanes $(LUA_SHAREDIR)
install -m 644 $(_TARGET_SO) $(LUA_LIBDIR)/lanes
cp -p src/lanes.lua $(LUA_SHAREDIR)
- cp -p src/lanes-keeper.lua $(LUA_SHAREDIR)
#--- Packaging ---
diff --git a/docs/index.html b/docs/index.html
index 4e37fe6..84ae5c0 100644
--- a/docs/index.html
+++ b/docs/index.html
@@ -56,7 +56,7 @@
Copyright © 2007-12 Asko Kauppi, Benoit Germain. All rights reserved.
Lua Lanes is published under the same MIT license as Lua 5.1 and 5.2.
-
This document was revised on 13-Aug-12, and applies to version 3.1.6
+
This document was revised on 21-Aug-12, and applies to version 3.2.0
@@ -147,7 +147,7 @@
details and limitations.
-To install Lanes, all you need are the lanes.lua lanes-keeper.lua and lanes/core.so|dll
+
To install Lanes, all you need are the lanes.lua and lanes/core.so|dll
files to be reachable by Lua (see LUA_PATH, LUA_CPATH).
Or use Lua Rocks package management.
@@ -1070,7 +1070,7 @@ Here are some things one should consider, if best performance is vital:
Lindas are hashed to a fixed number of "keeper states", which are a locking entity.
If you are using a lot of Linda objects,
it may be useful to try having more of these keeper states. By default,
- only one is used (see KEEPER_STATES_N), but this is an implementation detail.
+ only one is used (see lanes.configure()).
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 @@
--[[
===============================================================================
- Copyright (C) 2011 Benoit Germain
+ Copyright (C) 2011-2012 Benoit Germain
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
@@ -50,6 +50,374 @@
#include "tools.h"
#include "keeper.h"
+#if KEEPER_MODEL == KEEPER_MODEL_C
+//###################################################################################
+// Keeper implementation
+//###################################################################################
+
+typedef struct
+{
+ int first;
+ int count;
+ int limit;
+} keeper_fifo;
+
+// replaces the fifo ud by its uservalue on the stack
+static keeper_fifo* prepare_fifo_access( lua_State* L, int idx)
+{
+ keeper_fifo* fifo = (keeper_fifo*) lua_touserdata( L, idx);
+ if( fifo)
+ {
+ idx = lua_absindex( L, idx);
+ STACK_GROW( L, 1);
+ // we can replace the fifo userdata in the stack without fear of it being GCed, there are other references around
+ lua_getuservalue( L, idx);
+ lua_replace( L, idx);
+ }
+ return fifo;
+}
+
+// in: nothing
+// out: { first = 1, count = 0, limit = -1}
+static void fifo_new( lua_State* L)
+{
+ keeper_fifo* fifo;
+ STACK_GROW( L, 2);
+ fifo = (keeper_fifo*) lua_newuserdata( L, sizeof( keeper_fifo));
+ fifo->first = 1;
+ fifo->count = 0;
+ fifo->limit = -1;
+ lua_newtable( L);
+ lua_setuservalue( L, -2);
+}
+
+// in: expect fifo ... on top of the stack
+// out: nothing, removes all pushed values on the stack
+static void fifo_push( lua_State* L, keeper_fifo* fifo, int _count)
+{
+ int idx = lua_gettop( L) - _count;
+ int start = fifo->first + fifo->count - 1;
+ int i;
+ // pop all additional arguments, storing them in the fifo
+ for( i = _count; i >= 1; -- i)
+ {
+ // store in the fifo the value at the top of the stack at the specified index, popping it from the stack
+ lua_rawseti( L, idx, start + i);
+ }
+ fifo->count += _count;
+}
+
+// in: fifo
+// out: ...|nothing
+// expects exactly 1 value on the stack!
+// currently only called with a count of 1, but this may change in the future
+// function assumes that there is enough data in the fifo to satisfy the request
+static void fifo_peek( lua_State* L, keeper_fifo* fifo, int _count)
+{
+ int i;
+ STACK_GROW( L, _count);
+ for( i = 0; i < _count; ++ i)
+ {
+ lua_rawgeti( L, 1, fifo->first + i);
+ }
+}
+
+// in: fifo
+// out: pushes as many items as required on the stack (function assumes they exist in sufficient number)
+static void fifo_pop( lua_State* L, keeper_fifo* fifo, int _count)
+{
+ int fifo_idx = lua_gettop( L); // ... fifo
+ int i;
+ // each iteration pushes a value on the stack!
+ STACK_GROW( L, _count + 1);
+ for( i = 0; i < _count; ++ i)
+ {
+ int at = fifo->first + i;
+ lua_rawgeti( L, fifo_idx, at); // ... fifo val
+ lua_pushnil( L); // ... fifo val nil
+ lua_rawseti( L, fifo_idx, at); // ... fifo val
+ }
+ fifo->first += _count;
+ fifo->count -= _count;
+}
+
+// in: linda_ud expected at *absolute* stack slot idx
+// out: fifos[ud]
+static void* const fifos_key = (void*) prepare_fifo_access;
+static void push_table( lua_State* L, int idx)
+{
+ STACK_GROW( L, 4);
+ STACK_CHECK( L)
+ idx = lua_absindex( L, idx);
+ lua_pushlightuserdata( L, fifos_key); // ud fifos_key
+ lua_rawget( L, LUA_REGISTRYINDEX); // ud fifos
+ lua_pushvalue( L, idx); // ud fifos ud
+ lua_rawget( L, -2); // ud fifos fifos[ud]
+ STACK_MID( L, 2);
+ if( lua_isnil( L, -1))
+ {
+ lua_pop( L, 1); // ud fifos
+ // add a new fifos table for this linda
+ lua_newtable( L); // ud fifos fifos[ud]
+ lua_pushvalue( L, idx); // ud fifos fifos[ud] ud
+ lua_pushvalue( L, -2); // ud fifos fifos[ud] ud fifos[ud]
+ lua_rawset( L, -4); // ud fifos fifos[ud]
+ }
+ lua_remove( L, -2); // ud fifos[ud]
+ STACK_END( L, 1);
+}
+
+// in: linda_ud
+int keepercall_clear( lua_State* L)
+{
+ STACK_GROW( L, 3);
+ lua_pushlightuserdata( L, fifos_key); // ud fifos_key
+ lua_rawget( L, LUA_REGISTRYINDEX); // ud fifos
+ lua_pushvalue( L, 1); // ud fifos ud
+ lua_pushnil( L); // ud fifos ud nil
+ lua_rawset( L, -3); // ud fifos
+ lua_pop( L, 1); // ud
+ return 0;
+}
+
+
+// in: linda_ud, key, ...
+// out: true|false
+int keepercall_send( lua_State* L)
+{
+ keeper_fifo* fifo;
+ int n = lua_gettop( L) - 2;
+ push_table( L, 1); // ud key ... fifos
+ // get the fifo associated to this key in this linda, create it if it doesn't exist
+ lua_pushvalue( L, 2); // ud key ... fifos key
+ lua_rawget( L, -2); // ud key ... fifos fifo
+ if( lua_isnil( L, -1))
+ {
+ lua_pop( L, 1); // ud key ... fifos
+ fifo_new( L); // ud key ... fifos fifo
+ lua_pushvalue( L, 2); // ud key ... fifos fifo key
+ lua_pushvalue( L, -2); // ud key ... fifos fifo key fifo
+ lua_rawset( L, -4); // ud key ... fifos fifo
+ }
+ lua_remove( L, -2); // ud key ... fifo
+ fifo = (keeper_fifo*) lua_touserdata( L, -1);
+ if( fifo->limit >= 0 && fifo->count + n > fifo->limit)
+ {
+ lua_settop( L, 0); //
+ lua_pushboolean( L, 0); // false
+ }
+ else
+ {
+ fifo = prepare_fifo_access( L, -1);
+ lua_replace( L, 2); // ud fifo ...
+ fifo_push( L, fifo, n); // ud fifo
+ lua_settop( L, 0); //
+ lua_pushboolean( L, 1); // true
+ }
+ return 1;
+}
+
+// in: linda_ud, key [, key]?
+// out: (val, key) or nothing
+int keepercall_receive( lua_State* L)
+{
+ int top = lua_gettop( L);
+ int i;
+ keeper_fifo* fifo;
+ push_table( L, 1); // ud keys fifos
+ lua_replace( L, 1); // fifos keys
+ for( i = 2; i <= top; ++ i)
+ {
+ lua_pushvalue( L, i); // fifos keys key[i]
+ lua_rawget( L, 1); // fifos keys fifo
+ fifo = prepare_fifo_access( L, -1); // fifos keys fifo
+ if( fifo && fifo->count > 0)
+ {
+ fifo_pop( L, fifo, 1); // fifos keys fifo val
+ if( !lua_isnil( L, -1))
+ {
+ lua_replace( L, 1); // val keys fifo
+ if( i != 2)
+ {
+ lua_pushvalue( L, i); // val keys fifo key[i]
+ lua_replace( L, 2); // val key keys fifo
+ }
+ lua_settop( L, 2); // val key
+ return 2;
+ }
+ }
+ lua_settop( L, top); // data keys
+ }
+ // nothing to receive
+ return 0;
+}
+
+//in: linda_ud key mincount [maxcount]
+int keepercall_receive_batched( lua_State* L)
+{
+ int const min_count = (int) lua_tointeger( L, 3);
+ if( min_count > 0)
+ {
+ keeper_fifo* fifo;
+ int const max_count = (int) luaL_optinteger( L, 4, min_count);
+ lua_settop( L, 2); // ud key
+ push_table( L, 1); // ud key fifos
+ lua_replace( L, 1); // fifos key
+ lua_rawget( L, -2); // fifos fifo
+ lua_remove( L, 1); // fifo
+ fifo = prepare_fifo_access( L, 1); // fifo
+ if( fifo && fifo->count >= min_count)
+ {
+ fifo_pop( L, fifo, min( max_count, fifo->count)); // fifo ...
+ }
+ return lua_gettop( L) - 1;
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+// in: linda_ud key n
+// out: nothing
+int keepercall_limit( lua_State* L)
+{
+ keeper_fifo* fifo;
+ int limit = (int) lua_tointeger( L, 3);
+ push_table( L, 1); // ud key n fifos
+ lua_replace( L, 1); // fifos key n
+ lua_pop( L, 1); // fifos key
+ lua_pushvalue( L, -1); // fifos key key
+ lua_rawget( L, -3); // fifos key fifo
+ fifo = (keeper_fifo*) lua_touserdata( L, -1);
+ if( !fifo)
+ {
+ lua_pop( L, 1); // fifos key
+ fifo_new( L); // fifos key fifo
+ fifo = (keeper_fifo*) lua_touserdata( L, -1);
+ lua_rawset( L, -3); // fifos
+ }
+ fifo->limit = limit;
+ return 0;
+}
+
+//in: linda_ud key [val]
+int keepercall_set( lua_State* L)
+{
+ // make sure we have a value on the stack
+ if( lua_gettop( L) == 2)
+ {
+ lua_pushnil( L);
+ }
+ push_table( L, 1); // ud key val fifos
+ lua_replace( L, 1); // fifos key val
+ if( !lua_isnil( L, 3)) // replace contents stored at the specified key?
+ {
+ keeper_fifo* fifo;
+ fifo_new( L); // fifos key val fifo
+ lua_pushvalue( L, 2); // fifos key val fifo key
+ lua_pushvalue( L, -2); // fifos key val fifo key fifo
+ lua_rawset( L, 1); // fifos key val fifo
+ fifo = prepare_fifo_access( L, -1);
+ lua_insert( L, -2); // fifos key fifo val
+ fifo_push( L, fifo, 1); // fifos key fifo
+ }
+ else
+ {
+ // val == nil => stack contents: fifos key nil => remove the fifo associated with the current key
+ lua_rawset( L, 1); // fifos
+ }
+ return 0;
+}
+
+// in: linda_ud key
+int keepercall_get( lua_State* L)
+{
+ keeper_fifo* fifo;
+ push_table( L, 1); // ud key fifos
+ lua_replace( L, 1); // fifos key
+ lua_rawget( L, 1); // fifos fifo
+ fifo = prepare_fifo_access( L, -1); // fifos fifo
+ if( fifo && fifo->count > 0)
+ {
+ lua_remove( L, 1); // fifo
+ // read one value off the fifo
+ fifo_peek( L, fifo, 1); // fifo ...
+ return 1;
+ }
+ // no fifo was ever registered for this key, or it is empty
+ return 0;
+}
+
+// in: linda_ud [, key [, ...]]
+int keepercall_count( lua_State* L)
+{
+ int top;
+ push_table( L, 1); // ud keys fifos
+ switch( lua_gettop( L))
+ {
+ // no key is specified: return a table giving the count of all known keys
+ case 2: // ud fifos
+ lua_newtable( L); // ud fifos out
+ lua_replace( L, 1); // out fifos
+ lua_pushnil( L); // out fifos nil
+ while( lua_next( L, 2)) // out fifos key fifo
+ {
+ keeper_fifo* fifo = prepare_fifo_access( L, -1); // out fifos key fifo
+ lua_pop( L, 1); // out fifos key
+ lua_pushvalue( L, -1); // out fifos key key
+ lua_pushinteger( L, fifo->count); // out fifos key key count
+ lua_rawset( L, -5); // out fifos key
+ }
+ lua_pop( L, 1); // out
+ break;
+
+ // 1 key is specified: return its count
+ case 3: // ud key fifos
+ {
+ keeper_fifo* fifo;
+ lua_replace( L, 1); // fifos key
+ lua_rawget( L, -2); // fifos fifo
+ fifo = prepare_fifo_access( L, -1); // fifos fifo
+ lua_pushinteger( L, fifo->count); // fifos fifo count
+ lua_replace( L, -3); // count fifo
+ lua_pop( L, 1); // count
+ }
+ break;
+
+ // a variable number of keys is specified: return a table of their counts
+ default: // ud keys fifos
+ lua_newtable( L); // ud keys fifos out
+ lua_replace( L, 1); // out keys fifos
+ // shifts all keys up in the stack. potentially slow if there are a lot of them, but then it should be bearable
+ lua_insert( L, 2); // out fifos keys
+ while( (top = lua_gettop( L)) > 2)
+ {
+ keeper_fifo* fifo;
+ lua_pushvalue( L, -1); // out fifos keys key
+ lua_rawget( L, 2); // out fifos keys fifo
+ fifo = prepare_fifo_access( L, -1); // out fifos keys fifo
+ lua_pop( L, 1); // out fifos keys
+ if( fifo)
+ {
+ lua_pushinteger( L, fifo->count); // out fifos keys count
+ lua_rawset( L, 1); // out fifos keys
+ }
+ else
+ {
+ lua_pop( L, 1); // out fifos keys
+ }
+ }
+ lua_pop( L, 1); // out
+ }
+ return 1;
+}
+#endif // KEEPER_MODEL == KEEPER_MODEL_C
+
+//###################################################################################
+// Keeper API, accessed from linda methods
+//###################################################################################
+
/*---=== Keeper states ===---
*/
@@ -115,6 +483,14 @@ char const* init_keepers( int const _nbKeepers, lua_CFunction _on_state_create)
lua_concat( K, 2);
lua_setglobal( K, "decoda_name");
+#if KEEPER_MODEL == KEEPER_MODEL_C
+ // create the fifos table in the keeper state
+ lua_pushlightuserdata( K, fifos_key);
+ lua_newtable( K);
+ lua_rawset( K, LUA_REGISTRYINDEX);
+#endif // KEEPER_MODEL == KEEPER_MODEL_C
+
+#if KEEPER_MODEL == KEEPER_MODEL_LUA
// use package.loaders[2] to find keeper microcode
lua_getglobal( K, "package"); // package
lua_getfield( K, -1, "loaders"); // package package.loaders
@@ -132,6 +508,7 @@ char const* init_keepers( int const _nbKeepers, lua_CFunction _on_state_create)
} // package package.loaders
STACK_MID( K, 2);
lua_pop( K, 2);
+#endif // KEEPER_MODEL == KEEPER_MODEL_LUA
STACK_END( K, 0)
MUTEX_INIT( &GKeepers[i].lock_);
GKeepers[i].L = K;
@@ -207,7 +584,7 @@ struct s_Keeper *keeper_acquire( const void *ptr)
*
* Pointers are often aligned by 8 or so - ignore the low order bits
*/
- unsigned int i= ((unsigned long)(ptr) >> 3) % GNbKeepers;
+ unsigned int i= ((uintptr_t)(ptr) >> 3) % GNbKeepers;
struct s_Keeper *K= &GKeepers[i];
MUTEX_LOCK( &K->lock_);
@@ -259,16 +636,15 @@ void keeper_toggle_nil_sentinels( lua_State *L, int _val_i, int _nil_to_sentinel
*
* Returns: number of return values (pushed to 'L') or -1 in case of error
*/
-int keeper_call( lua_State *K, char const *func_name, lua_State *L, void *linda, uint_t starting_index)
+int keeper_call( lua_State *K, keeper_api_t _func, lua_State *L, void *linda, uint_t starting_index)
{
- int const args = starting_index ? (lua_gettop(L) - starting_index +1) : 0;
- int const Ktos = lua_gettop(K);
+ int const args = starting_index ? (lua_gettop( L) - starting_index + 1) : 0;
+ int const Ktos = lua_gettop( K);
int retvals = -1;
STACK_GROW( K, 2);
- lua_getglobal( K, func_name);
- ASSERT_L( lua_isfunction(K, -1));
+ PUSH_KEEPER_FUNC( K, _func);
lua_pushlightuserdata( K, linda);
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);
struct s_Keeper *keeper_acquire( const void *ptr);
void keeper_release( struct s_Keeper *K);
void keeper_toggle_nil_sentinels( lua_State *L, int _val_i, int _nil_to_sentinel);
-int keeper_call( lua_State *K, char const *func_name, lua_State *L, void *linda, uint_t starting_index);
+#define KEEPER_MODEL_LUA 1
+#define KEEPER_MODEL_C 2
+#define KEEPER_MODEL KEEPER_MODEL_C
+
+#if KEEPER_MODEL == KEEPER_MODEL_LUA
+typedef char const* keeper_api_t;
+#define KEEPER_API( _op) #_op
+#define PUSH_KEEPER_FUNC( K, _api) lua_getglobal( K, _api)
+#elif KEEPER_MODEL == KEEPER_MODEL_C
+typedef lua_CFunction keeper_api_t;
+#define KEEPER_API( _op) keepercall_ ## _op
+#define PUSH_KEEPER_FUNC lua_pushcfunction
+// lua_Cfunctions to run inside a keeper state (formerly implemented in Lua)
+int keepercall_clear( lua_State* L);
+int keepercall_send( lua_State* L);
+int keepercall_receive( lua_State* L);
+int keepercall_receive_batched( lua_State* L);
+int keepercall_limit( lua_State* L);
+int keepercall_get( lua_State* L);
+int keepercall_set( lua_State* L);
+int keepercall_count( lua_State* L);
+#endif // KEEPER_MODEL
+
+int keeper_call( lua_State *K, keeper_api_t _func, lua_State *L, void *linda, uint_t starting_index);
#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 @@
-- KEEPER.LUA
--
-- Keeper state logic
+-- DEPRECATED BY THE EQUIVALENT C IMPLEMENTATION, KEPT FOR REFERENCE ONLY
+-- SHOULD NOT BE PART OF THE INSTALLATION ANYMORE
--
-- This code is read in for each "keeper state", which are the hidden, inter-
-- 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 @@
* ...
*/
-char const* VERSION = "3.1.6";
+char const* VERSION = "3.2.0";
/*
===============================================================================
@@ -309,7 +309,7 @@ LUAG_FUNC( linda_send)
for( ;;)
{
STACK_MID(KL, 0)
- pushed = keeper_call( KL, "send", L, linda, key_i);
+ pushed = keeper_call( KL, KEEPER_API( send), L, linda, key_i);
if( pushed < 0)
{
break;
@@ -410,7 +410,7 @@ LUAG_FUNC( linda_receive)
struct s_Linda *linda = lua_toLinda( L, 1);
int pushed, expected_pushed_min, expected_pushed_max;
bool_t cancel = FALSE;
- char *keeper_receive;
+ keeper_api_t keeper_receive;
time_d timeout = -1.0;
uint_t key_i = 2;
@@ -440,7 +440,7 @@ LUAG_FUNC( linda_receive)
// make sure the keys are of a valid type
check_key_types( L, key_i, key_i);
// receive multiple values from a single slot
- keeper_receive = "receive_batched";
+ keeper_receive = KEEPER_API( receive_batched);
// we expect a user-defined amount of return value
expected_pushed_min = (int)luaL_checkinteger( L, key_i + 1);
expected_pushed_max = (int)luaL_optinteger( L, key_i + 2, expected_pushed_min);
@@ -454,7 +454,7 @@ LUAG_FUNC( linda_receive)
// make sure the keys are of a valid type
check_key_types( L, key_i, lua_gettop( L));
// receive a single value, checking multiple slots
- keeper_receive = "receive";
+ keeper_receive = KEEPER_API( receive);
// we expect a single (value, key) pair of returned values
expected_pushed_min = expected_pushed_max = 2;
}
@@ -558,6 +558,7 @@ LUAG_FUNC( linda_set)
struct s_Linda *linda = lua_toLinda( L, 1);
bool_t has_value = !lua_isnil( L, 3);
luaL_argcheck( L, linda, 1, "expected a linda object!");
+ luaL_argcheck( L, lua_gettop( L) <= 3, 4, "too many arguments");
// make sure the key is of a valid type
check_key_types( L, 2, 2);
@@ -566,7 +567,7 @@ LUAG_FUNC( linda_set)
int pushed;
struct s_Keeper *K = keeper_acquire( linda);
// no nil->sentinel toggling, we really clear the linda contents for the given key with a set()
- pushed = keeper_call( K->L, "set", L, linda, 2);
+ pushed = keeper_call( K->L, KEEPER_API( set), L, linda, 2);
if( pushed >= 0) // no error?
{
ASSERT_L( pushed == 0);
@@ -606,7 +607,7 @@ LUAG_FUNC( linda_count)
{
struct s_Keeper *K = keeper_acquire( linda);
- pushed = keeper_call( K->L, "count", L, linda, 2);
+ pushed = keeper_call( K->L, KEEPER_API( count), L, linda, 2);
keeper_release( K);
if( pushed < 0)
{
@@ -634,7 +635,7 @@ LUAG_FUNC( linda_get)
{
struct s_Keeper *K = keeper_acquire( linda);
- pushed = keeper_call( K->L, "get", L, linda, 2);
+ pushed = keeper_call( K->L, KEEPER_API( get), L, linda, 2);
ASSERT_L( pushed==0 || pushed==1 );
if( pushed > 0)
{
@@ -659,15 +660,19 @@ LUAG_FUNC( linda_get)
*/
LUAG_FUNC( linda_limit)
{
- struct s_Linda *linda= lua_toLinda( L, 1 );
+ struct s_Linda* linda= lua_toLinda( L, 1 );
luaL_argcheck( L, linda, 1, "expected a linda object!");
+ // make sure we got a key and a limit
+ luaL_argcheck( L, lua_gettop( L) == 3, 2, "wrong number of arguments");
+ // make sure we got a numeric limit
+ luaL_checknumber( L, 3);
// make sure the key is of a valid type
check_key_types( L, 2, 2);
{
- struct s_Keeper *K = keeper_acquire( linda);
- int pushed = keeper_call( K->L, "limit", L, linda, 2);
+ struct s_Keeper* K = keeper_acquire( linda);
+ int pushed = keeper_call( K->L, KEEPER_API( limit), L, linda, 2);
ASSERT_L( pushed <= 0); // either error or no return values
keeper_release( K);
// must trigger error after keeper state has been released
@@ -825,8 +830,8 @@ static void linda_id( lua_State *L, char const * const which)
K= keeper_acquire(s);
if( K && K->L) // can be NULL if this happens during main state shutdown (lanes is GC'ed -> no keepers -> no need to cleanup)
{
- keeper_call( K->L, "clear", L, s, 0 );
- keeper_release(K);
+ keeper_call( K->L, KEEPER_API( clear), L, s, 0 );
+ keeper_release( K);
}
/* There aren't any lanes waiting on these lindas, since all proxies
--
cgit v1.2.3-55-g6feb