diff options
| author | Benoit Germain <bnt period germain arrobase gmail period com> | 2014-02-27 18:32:00 +0100 |
|---|---|---|
| committer | Benoit Germain <bnt period germain arrobase gmail period com> | 2014-02-27 18:32:00 +0100 |
| commit | 437759ddf0ce7e6dc5ed4944e033ef04674de430 (patch) | |
| tree | fc4a00832167b6f2735bdd3749965d85d00ab068 /src | |
| parent | cf2d7438f0e6e56a7c5dd78dfde7639eac571d98 (diff) | |
| download | lanes-437759ddf0ce7e6dc5ed4944e033ef04674de430.tar.gz lanes-437759ddf0ce7e6dc5ed4944e033ef04674de430.tar.bz2 lanes-437759ddf0ce7e6dc5ed4944e033ef04674de430.zip | |
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)
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 | } |
