diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/keeper.lua | 26 | ||||
| -rw-r--r-- | src/lanes.c | 55 |
2 files changed, 50 insertions, 31 deletions
diff --git a/src/keeper.lua b/src/keeper.lua index 77bf880..1f17599 100644 --- a/src/keeper.lua +++ b/src/keeper.lua | |||
| @@ -87,7 +87,6 @@ local fifo_peek = function( fifo, count) | |||
| 87 | end | 87 | end |
| 88 | 88 | ||
| 89 | local fifo_pop = function( fifo, count) | 89 | local fifo_pop = function( fifo, count) |
| 90 | if count > fifo.count then error("list is too short") end | ||
| 91 | local first = fifo.first | 90 | local first = fifo.first |
| 92 | local last = first + count - 1 | 91 | local last = first + count - 1 |
| 93 | local out = { unpack( fifo, first, last)} | 92 | local out = { unpack( fifo, first, last)} |
| @@ -178,7 +177,7 @@ end | |||
| 178 | -- | 177 | -- |
| 179 | function receive( ud, ...) | 178 | function receive( ud, ...) |
| 180 | 179 | ||
| 181 | local data, _ = tables( ud) | 180 | local data = tables( ud) |
| 182 | 181 | ||
| 183 | for i = 1, select( '#', ...) do | 182 | for i = 1, select( '#', ...) do |
| 184 | local key = select( i, ...) | 183 | local key = select( i, ...) |
| @@ -186,7 +185,7 @@ function receive( ud, ...) | |||
| 186 | if fifo and fifo.count > 0 then | 185 | if fifo and fifo.count > 0 then |
| 187 | local val = fifo_pop( fifo, 1) | 186 | local val = fifo_pop( fifo, 1) |
| 188 | if val ~= nil then | 187 | if val ~= nil then |
| 189 | return val, key | 188 | return val, key |
| 190 | end | 189 | end |
| 191 | end | 190 | end |
| 192 | end | 191 | end |
| @@ -194,17 +193,20 @@ end | |||
| 194 | 193 | ||
| 195 | 194 | ||
| 196 | ----- | 195 | ----- |
| 197 | -- [val1, ... valCOUNT]= receive_batched( linda_deep_ud, batch_sentinel, key , COUNT) | 196 | -- [val1, ... valCOUNT]= receive_batched( linda_deep_ud, key , min_COUNT, max_COUNT) |
| 198 | -- | 197 | -- |
| 199 | -- Read any of the given keys, consuming the data found. Keys are read in | 198 | -- Read a single key, consuming the data found. |
| 200 | -- order. | ||
| 201 | -- | 199 | -- |
| 202 | receive_batched = function( ud, batch_sentinel, key, count) | 200 | receive_batched = function( ud, key, min_count, max_count) |
| 203 | if count > 0 then | 201 | if min_count > 0 then |
| 204 | local data, _ = tables( ud) | 202 | local fifo = tables( ud)[key] |
| 205 | local fifo = data[key] | 203 | if fifo then |
| 206 | if fifo and fifo.count >= count then | 204 | local fifo_count = fifo.count |
| 207 | return fifo_pop( fifo, count) | 205 | if fifo_count >= min_count then |
| 206 | max_count = max_count or min_count | ||
| 207 | max_count = (max_count > fifo_count) and fifo_count or max_count | ||
| 208 | return fifo_pop( fifo, max_count) | ||
| 209 | end | ||
| 208 | end | 210 | end |
| 209 | end | 211 | end |
| 210 | end | 212 | end |
diff --git a/src/lanes.c b/src/lanes.c index d777be1..931af98 100644 --- a/src/lanes.c +++ b/src/lanes.c | |||
| @@ -51,7 +51,7 @@ | |||
| 51 | * ... | 51 | * ... |
| 52 | */ | 52 | */ |
| 53 | 53 | ||
| 54 | char const* VERSION = "3.1.2"; | 54 | char const* VERSION = "3.1.3"; |
| 55 | 55 | ||
| 56 | /* | 56 | /* |
| 57 | =============================================================================== | 57 | =============================================================================== |
| @@ -398,16 +398,16 @@ LUAG_FUNC( linda_send) | |||
| 398 | * Consumes a single value from the Linda, in any key. | 398 | * Consumes a single value from the Linda, in any key. |
| 399 | * Returns: received value (which is consumed from the slot), and the key which had it | 399 | * Returns: received value (which is consumed from the slot), and the key which had it |
| 400 | 400 | ||
| 401 | * [val1, ... valCOUNT]= linda_receive( linda_ud, [timeout_secs_num=-1], linda.batched, key_num|str|bool|lightuserdata, COUNT) | 401 | * [val1, ... valCOUNT]= linda_receive( linda_ud, [timeout_secs_num=-1], linda.batched, key_num|str|bool|lightuserdata, min_COUNT[, max_COUNT]) |
| 402 | * Consumes COUNT values from the linda, from a single key. | 402 | * Consumes between min_COUNT and max_COUNT values from the linda, from a single key. |
| 403 | * returns the COUNT consumed values, or nil if there weren't enough values to consume | 403 | * returns the actual consumed values, or nil if there weren't enough values to consume |
| 404 | * | 404 | * |
| 405 | */ | 405 | */ |
| 406 | #define BATCH_SENTINEL "270e6c9d-280f-4983-8fee-a7ecdda01475" | 406 | #define BATCH_SENTINEL "270e6c9d-280f-4983-8fee-a7ecdda01475" |
| 407 | LUAG_FUNC( linda_receive) | 407 | LUAG_FUNC( linda_receive) |
| 408 | { | 408 | { |
| 409 | struct s_Linda *linda = lua_toLinda( L, 1); | 409 | struct s_Linda *linda = lua_toLinda( L, 1); |
| 410 | int pushed, expected_pushed; | 410 | int pushed, expected_pushed_min, expected_pushed_max; |
| 411 | bool_t cancel = FALSE; | 411 | bool_t cancel = FALSE; |
| 412 | char *keeper_receive; | 412 | char *keeper_receive; |
| 413 | 413 | ||
| @@ -426,27 +426,44 @@ LUAG_FUNC( linda_receive) | |||
| 426 | ++ key_i; | 426 | ++ key_i; |
| 427 | } | 427 | } |
| 428 | 428 | ||
| 429 | // make sure the keys are of a valid type | ||
| 430 | check_key_types( L, key_i, lua_gettop( L)); | ||
| 431 | |||
| 432 | // are we in batched mode? | 429 | // are we in batched mode? |
| 433 | lua_pushliteral( L, BATCH_SENTINEL); | ||
| 434 | if( lua_equal( L, key_i, -1)) | ||
| 435 | { | ||
| 436 | keeper_receive = "receive_batched"; | ||
| 437 | expected_pushed = (int)luaL_checkinteger( L, key_i + 2); | ||
| 438 | } | ||
| 439 | else | ||
| 440 | { | 430 | { |
| 441 | keeper_receive = "receive"; | 431 | int is_batched; |
| 442 | expected_pushed = 2; | 432 | lua_pushliteral( L, BATCH_SENTINEL); |
| 433 | is_batched = lua_equal( L, key_i, -1); | ||
| 434 | lua_pop( L, 1); | ||
| 435 | if( is_batched) | ||
| 436 | { | ||
| 437 | // no need to pass linda.batched in the keeper state | ||
| 438 | ++ key_i; | ||
| 439 | // make sure the keys are of a valid type | ||
| 440 | check_key_types( L, key_i, key_i); | ||
| 441 | // receive multiple values from a single slot | ||
| 442 | keeper_receive = "receive_batched"; | ||
| 443 | // we expect a user-defined amount of return value | ||
| 444 | expected_pushed_min = (int)luaL_checkinteger( L, key_i + 1); | ||
| 445 | expected_pushed_max = (int)luaL_optinteger( L, key_i + 2, expected_pushed_min); | ||
| 446 | if( expected_pushed_min > expected_pushed_max) | ||
| 447 | { | ||
| 448 | luaL_error( L, "batched min/max error"); | ||
| 449 | } | ||
| 450 | } | ||
| 451 | else | ||
| 452 | { | ||
| 453 | // make sure the keys are of a valid type | ||
| 454 | check_key_types( L, key_i, lua_gettop( L)); | ||
| 455 | // receive a single value, checking multiple slots | ||
| 456 | keeper_receive = "receive"; | ||
| 457 | // we expect a single (value, key) pair of returned values | ||
| 458 | expected_pushed_min = expected_pushed_max = 2; | ||
| 459 | } | ||
| 443 | } | 460 | } |
| 444 | lua_pop( L, 1); | ||
| 445 | 461 | ||
| 446 | { | 462 | { |
| 447 | struct s_Keeper *K = keeper_acquire( linda); | 463 | struct s_Keeper *K = keeper_acquire( linda); |
| 448 | for( ;;) | 464 | for( ;;) |
| 449 | { | 465 | { |
| 466 | // all arguments of receive() but the first are passed to the keeper's receive function | ||
| 450 | pushed = keeper_call( K->L, keeper_receive, L, linda, key_i); | 467 | pushed = keeper_call( K->L, keeper_receive, L, linda, key_i); |
| 451 | if( pushed < 0) | 468 | if( pushed < 0) |
| 452 | { | 469 | { |
| @@ -454,7 +471,7 @@ LUAG_FUNC( linda_receive) | |||
| 454 | } | 471 | } |
| 455 | if( pushed > 0) | 472 | if( pushed > 0) |
| 456 | { | 473 | { |
| 457 | ASSERT_L( pushed == expected_pushed); | 474 | ASSERT_L( pushed >= expected_pushed_min && pushed <= expected_pushed_max); |
| 458 | // replace sentinels with real nils | 475 | // replace sentinels with real nils |
| 459 | keeper_toggle_nil_sentinels( L, lua_gettop( L) - pushed, 0); | 476 | keeper_toggle_nil_sentinels( L, lua_gettop( L) - pushed, 0); |
| 460 | // To be done from within the 'K' locking area | 477 | // To be done from within the 'K' locking area |
