From 437759ddf0ce7e6dc5ed4944e033ef04674de430 Mon Sep 17 00:00:00 2001 From: Benoit Germain Date: Thu, 27 Feb 2014 18:32:00 +0100 Subject: linda:send() improvements * Bumped version to 3.9.3 * new exposed variable linda.null that exposes the internal NIL_SENTINEL marker * linda:send() interprets send key linda.null as authorization to silently send a single nil when not provided with anything to send (useful when sending results of a function that can return nothing) --- src/keeper.c | 8 ++------ src/keeper.h | 2 ++ src/lanes.c | 32 ++++++++++++++++++++++++++------ 3 files changed, 30 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/keeper.c b/src/keeper.c index 9e5317b..7362ca6 100644 --- a/src/keeper.c +++ b/src/keeper.c @@ -756,23 +756,19 @@ void keeper_release( struct s_Keeper* K) void keeper_toggle_nil_sentinels( lua_State* L, int val_i_, enum eLookupMode mode_) { int i, n = lua_gettop( L); - /* We could use an empty table in 'keeper.lua' as the sentinel, but maybe - * checking for a lightuserdata is faster. (any unique value will do -> take the address of some global symbol of ours) - */ - void* nil_sentinel = (void*) keeper_toggle_nil_sentinels; for( i = val_i_; i <= n; ++ i) { if( mode_ == eLM_ToKeeper) { if( lua_isnil( L, i)) { - lua_pushlightuserdata( L, nil_sentinel); + lua_pushlightuserdata( L, NIL_SENTINEL); lua_replace( L, i); } } else { - if( lua_touserdata( L, i) == nil_sentinel) + if( lua_touserdata( L, i) == NIL_SENTINEL) { lua_pushnil( L); lua_replace( L, i); diff --git a/src/keeper.h b/src/keeper.h index 450f64d..6ca4ad4 100644 --- a/src/keeper.h +++ b/src/keeper.h @@ -23,6 +23,8 @@ void keeper_release( struct s_Keeper* K); void keeper_toggle_nil_sentinels( lua_State* L, int _val_i, enum eLookupMode const mode_); int keeper_push_linda_storage( struct s_Universe* U, lua_State* L, void* ptr, unsigned long magic_); +#define NIL_SENTINEL ((void*)keeper_toggle_nil_sentinels) + typedef lua_CFunction keeper_api_t; #define KEEPER_API( _op) keepercall_ ## _op #define PUSH_KEEPER_FUNC lua_pushcfunction diff --git a/src/lanes.c b/src/lanes.c index bca8b74..4130b24 100644 --- a/src/lanes.c +++ b/src/lanes.c @@ -52,7 +52,7 @@ * ... */ -char const* VERSION = "3.9.2"; +char const* VERSION = "3.9.3"; /* =============================================================================== @@ -442,7 +442,7 @@ static void check_key_types( lua_State* L, int start_, int end_) } /* -* bool= linda_send( linda_ud, [timeout_secs=-1,] key_num|str|bool|lightuserdata, ... ) +* bool= linda_send( linda_ud, [timeout_secs=-1,] [linda.null,] key_num|str|bool|lightuserdata, ... ) * * Send one or more values to a Linda. If there is a limit, all values must fit. * @@ -458,10 +458,11 @@ LUAG_FUNC( linda_send) int pushed; time_d timeout = -1.0; uint_t key_i = 2; // index of first key, if timeout not there + void* as_nil_sentinel; // if not NULL, send() will silently send a single nil if nothing is provided if( lua_type( L, 2) == LUA_TNUMBER) // we don't want to use lua_isnumber() because of autocoercion { - timeout = SIGNAL_TIMEOUT_PREPARE( lua_tonumber( L,2)); + timeout = SIGNAL_TIMEOUT_PREPARE( lua_tonumber( L, 2)); ++ key_i; } else if( lua_isnil( L, 2)) // alternate explicit "no timeout" by passing nil before the key @@ -469,19 +470,35 @@ LUAG_FUNC( linda_send) ++ key_i; } - // make sure the keys are of a valid type + as_nil_sentinel = lua_touserdata( L, key_i); + if( as_nil_sentinel == NIL_SENTINEL) + { + // the real key to send data to is after the NIL_SENTINEL marker + ++ key_i; + } + + // make sure the key is of a valid type check_key_types( L, key_i, key_i); + STACK_GROW( L, 1); + // make sure there is something to send if( (uint_t)lua_gettop( L) == key_i) { - return luaL_error( L, "no data to send"); + if( as_nil_sentinel == NIL_SENTINEL) + { + // send a single nil if nothing is provided + lua_pushlightuserdata( L, NIL_SENTINEL); + } + else + { + return luaL_error( L, "no data to send"); + } } // convert nils to some special non-nil sentinel in sent values keeper_toggle_nil_sentinels( L, key_i + 1, eLM_ToKeeper); - STACK_GROW( L, 1); { bool_t try_again = TRUE; struct s_lane* const s = get_lane_from_registry( L); @@ -1210,6 +1227,9 @@ static void* linda_id( lua_State* L, enum eDeepOp op_) lua_pushliteral( L, BATCH_SENTINEL); lua_setfield(L, -2, "batched"); + lua_pushlightuserdata( L, NIL_SENTINEL); + lua_setfield(L, -2, "null"); + STACK_END( L, 1); return NULL; } -- cgit v1.2.3-55-g6feb