diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/keeper.c | 8 | ||||
-rw-r--r-- | src/keeper.h | 2 | ||||
-rw-r--r-- | src/lanes.c | 32 |
3 files changed, 30 insertions, 12 deletions
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) | |||
756 | void keeper_toggle_nil_sentinels( lua_State* L, int val_i_, enum eLookupMode mode_) | 756 | void keeper_toggle_nil_sentinels( lua_State* L, int val_i_, enum eLookupMode mode_) |
757 | { | 757 | { |
758 | int i, n = lua_gettop( L); | 758 | int i, n = lua_gettop( L); |
759 | /* We could use an empty table in 'keeper.lua' as the sentinel, but maybe | ||
760 | * checking for a lightuserdata is faster. (any unique value will do -> take the address of some global symbol of ours) | ||
761 | */ | ||
762 | void* nil_sentinel = (void*) keeper_toggle_nil_sentinels; | ||
763 | for( i = val_i_; i <= n; ++ i) | 759 | for( i = val_i_; i <= n; ++ i) |
764 | { | 760 | { |
765 | if( mode_ == eLM_ToKeeper) | 761 | if( mode_ == eLM_ToKeeper) |
766 | { | 762 | { |
767 | if( lua_isnil( L, i)) | 763 | if( lua_isnil( L, i)) |
768 | { | 764 | { |
769 | lua_pushlightuserdata( L, nil_sentinel); | 765 | lua_pushlightuserdata( L, NIL_SENTINEL); |
770 | lua_replace( L, i); | 766 | lua_replace( L, i); |
771 | } | 767 | } |
772 | } | 768 | } |
773 | else | 769 | else |
774 | { | 770 | { |
775 | if( lua_touserdata( L, i) == nil_sentinel) | 771 | if( lua_touserdata( L, i) == NIL_SENTINEL) |
776 | { | 772 | { |
777 | lua_pushnil( L); | 773 | lua_pushnil( L); |
778 | lua_replace( L, i); | 774 | 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); | |||
23 | void keeper_toggle_nil_sentinels( lua_State* L, int _val_i, enum eLookupMode const mode_); | 23 | void keeper_toggle_nil_sentinels( lua_State* L, int _val_i, enum eLookupMode const mode_); |
24 | int keeper_push_linda_storage( struct s_Universe* U, lua_State* L, void* ptr, unsigned long magic_); | 24 | int keeper_push_linda_storage( struct s_Universe* U, lua_State* L, void* ptr, unsigned long magic_); |
25 | 25 | ||
26 | #define NIL_SENTINEL ((void*)keeper_toggle_nil_sentinels) | ||
27 | |||
26 | typedef lua_CFunction keeper_api_t; | 28 | typedef lua_CFunction keeper_api_t; |
27 | #define KEEPER_API( _op) keepercall_ ## _op | 29 | #define KEEPER_API( _op) keepercall_ ## _op |
28 | #define PUSH_KEEPER_FUNC lua_pushcfunction | 30 | #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 @@ | |||
52 | * ... | 52 | * ... |
53 | */ | 53 | */ |
54 | 54 | ||
55 | char const* VERSION = "3.9.2"; | 55 | char const* VERSION = "3.9.3"; |
56 | 56 | ||
57 | /* | 57 | /* |
58 | =============================================================================== | 58 | =============================================================================== |
@@ -442,7 +442,7 @@ static void check_key_types( lua_State* L, int start_, int end_) | |||
442 | } | 442 | } |
443 | 443 | ||
444 | /* | 444 | /* |
445 | * bool= linda_send( linda_ud, [timeout_secs=-1,] key_num|str|bool|lightuserdata, ... ) | 445 | * bool= linda_send( linda_ud, [timeout_secs=-1,] [linda.null,] key_num|str|bool|lightuserdata, ... ) |
446 | * | 446 | * |
447 | * Send one or more values to a Linda. If there is a limit, all values must fit. | 447 | * Send one or more values to a Linda. If there is a limit, all values must fit. |
448 | * | 448 | * |
@@ -458,10 +458,11 @@ LUAG_FUNC( linda_send) | |||
458 | int pushed; | 458 | int pushed; |
459 | time_d timeout = -1.0; | 459 | time_d timeout = -1.0; |
460 | uint_t key_i = 2; // index of first key, if timeout not there | 460 | uint_t key_i = 2; // index of first key, if timeout not there |
461 | void* as_nil_sentinel; // if not NULL, send() will silently send a single nil if nothing is provided | ||
461 | 462 | ||
462 | if( lua_type( L, 2) == LUA_TNUMBER) // we don't want to use lua_isnumber() because of autocoercion | 463 | if( lua_type( L, 2) == LUA_TNUMBER) // we don't want to use lua_isnumber() because of autocoercion |
463 | { | 464 | { |
464 | timeout = SIGNAL_TIMEOUT_PREPARE( lua_tonumber( L,2)); | 465 | timeout = SIGNAL_TIMEOUT_PREPARE( lua_tonumber( L, 2)); |
465 | ++ key_i; | 466 | ++ key_i; |
466 | } | 467 | } |
467 | else if( lua_isnil( L, 2)) // alternate explicit "no timeout" by passing nil before the key | 468 | else if( lua_isnil( L, 2)) // alternate explicit "no timeout" by passing nil before the key |
@@ -469,19 +470,35 @@ LUAG_FUNC( linda_send) | |||
469 | ++ key_i; | 470 | ++ key_i; |
470 | } | 471 | } |
471 | 472 | ||
472 | // make sure the keys are of a valid type | 473 | as_nil_sentinel = lua_touserdata( L, key_i); |
474 | if( as_nil_sentinel == NIL_SENTINEL) | ||
475 | { | ||
476 | // the real key to send data to is after the NIL_SENTINEL marker | ||
477 | ++ key_i; | ||
478 | } | ||
479 | |||
480 | // make sure the key is of a valid type | ||
473 | check_key_types( L, key_i, key_i); | 481 | check_key_types( L, key_i, key_i); |
474 | 482 | ||
483 | STACK_GROW( L, 1); | ||
484 | |||
475 | // make sure there is something to send | 485 | // make sure there is something to send |
476 | if( (uint_t)lua_gettop( L) == key_i) | 486 | if( (uint_t)lua_gettop( L) == key_i) |
477 | { | 487 | { |
478 | return luaL_error( L, "no data to send"); | 488 | if( as_nil_sentinel == NIL_SENTINEL) |
489 | { | ||
490 | // send a single nil if nothing is provided | ||
491 | lua_pushlightuserdata( L, NIL_SENTINEL); | ||
492 | } | ||
493 | else | ||
494 | { | ||
495 | return luaL_error( L, "no data to send"); | ||
496 | } | ||
479 | } | 497 | } |
480 | 498 | ||
481 | // convert nils to some special non-nil sentinel in sent values | 499 | // convert nils to some special non-nil sentinel in sent values |
482 | keeper_toggle_nil_sentinels( L, key_i + 1, eLM_ToKeeper); | 500 | keeper_toggle_nil_sentinels( L, key_i + 1, eLM_ToKeeper); |
483 | 501 | ||
484 | STACK_GROW( L, 1); | ||
485 | { | 502 | { |
486 | bool_t try_again = TRUE; | 503 | bool_t try_again = TRUE; |
487 | struct s_lane* const s = get_lane_from_registry( L); | 504 | struct s_lane* const s = get_lane_from_registry( L); |
@@ -1210,6 +1227,9 @@ static void* linda_id( lua_State* L, enum eDeepOp op_) | |||
1210 | lua_pushliteral( L, BATCH_SENTINEL); | 1227 | lua_pushliteral( L, BATCH_SENTINEL); |
1211 | lua_setfield(L, -2, "batched"); | 1228 | lua_setfield(L, -2, "batched"); |
1212 | 1229 | ||
1230 | lua_pushlightuserdata( L, NIL_SENTINEL); | ||
1231 | lua_setfield(L, -2, "null"); | ||
1232 | |||
1213 | STACK_END( L, 1); | 1233 | STACK_END( L, 1); |
1214 | return NULL; | 1234 | return NULL; |
1215 | } | 1235 | } |