diff options
author | Benoit Germain <bnt period germain arrobase gmail period com> | 2014-01-20 10:51:11 +0100 |
---|---|---|
committer | Benoit Germain <bnt period germain arrobase gmail period com> | 2014-01-20 10:51:11 +0100 |
commit | cf9b09ff352611fb8cee3679127f3655cbe73ae7 (patch) | |
tree | 011ae091b0bff2d10a9e8dd0fd564ab2b6365f86 /src/keeper.c | |
parent | 1843a0add00186eee129b0b0a2ee605866acbb61 (diff) | |
download | lanes-cf9b09ff352611fb8cee3679127f3655cbe73ae7.tar.gz lanes-cf9b09ff352611fb8cee3679127f3655cbe73ae7.tar.bz2 lanes-cf9b09ff352611fb8cee3679127f3655cbe73ae7.zip |
get()/set() improvements
* bumped version to 3.8.0
* linda:set() accepts multiple values to set in the specified slot
* linda:get() accepts an optional count to peek several values at once
* nil values are now converted just as in send()/receive()
Diffstat (limited to 'src/keeper.c')
-rw-r--r-- | src/keeper.c | 102 |
1 files changed, 54 insertions, 48 deletions
diff --git a/src/keeper.c b/src/keeper.c index 6d5ecbf..b0db8b4 100644 --- a/src/keeper.c +++ b/src/keeper.c | |||
@@ -115,11 +115,11 @@ static void fifo_push( lua_State* L, keeper_fifo* fifo, int _count) | |||
115 | // expects exactly 1 value on the stack! | 115 | // expects exactly 1 value on the stack! |
116 | // currently only called with a count of 1, but this may change in the future | 116 | // currently only called with a count of 1, but this may change in the future |
117 | // function assumes that there is enough data in the fifo to satisfy the request | 117 | // function assumes that there is enough data in the fifo to satisfy the request |
118 | static void fifo_peek( lua_State* L, keeper_fifo* fifo, int _count) | 118 | static void fifo_peek( lua_State* L, keeper_fifo* fifo, int count_) |
119 | { | 119 | { |
120 | int i; | 120 | int i; |
121 | STACK_GROW( L, _count); | 121 | STACK_GROW( L, count_); |
122 | for( i = 0; i < _count; ++ i) | 122 | for( i = 0; i < count_; ++ i) |
123 | { | 123 | { |
124 | lua_rawgeti( L, 1, fifo->first + i); | 124 | lua_rawgeti( L, 1, fifo->first + i); |
125 | } | 125 | } |
@@ -384,54 +384,21 @@ int keepercall_limit( lua_State* L) | |||
384 | return lua_gettop( L); | 384 | return lua_gettop( L); |
385 | } | 385 | } |
386 | 386 | ||
387 | //in: linda_ud key [val] | 387 | //in: linda_ud key [[val] ...] |
388 | //out: true or nil | 388 | //out: true or nil |
389 | int keepercall_set( lua_State* L) | 389 | int keepercall_set( lua_State* L) |
390 | { | 390 | { |
391 | bool_t should_wake_writers = FALSE; | 391 | bool_t should_wake_writers = FALSE; |
392 | STACK_GROW( L, 6); | 392 | STACK_GROW( L, 6); |
393 | // make sure we have a value on the stack | ||
394 | if( lua_gettop( L) == 2) // ud key val? | ||
395 | { | ||
396 | lua_pushnil( L); // ud key nil | ||
397 | } | ||
398 | 393 | ||
399 | // retrieve fifos associated with the linda | 394 | // retrieve fifos associated with the linda |
400 | push_table( L, 1); // ud key val fifos | 395 | push_table( L, 1); // ud key [val [, ...]] fifos |
401 | lua_replace( L, 1); // fifos key val | 396 | lua_replace( L, 1); // fifos key [val [, ...]] |
402 | 397 | ||
403 | if( !lua_isnil( L, 3)) // set/replace contents stored at the specified key? | 398 | // make sure we have a value on the stack |
399 | if( lua_gettop( L) == 2) // fifos key | ||
404 | { | 400 | { |
405 | keeper_fifo* fifo; | 401 | keeper_fifo* fifo; |
406 | lua_pushvalue( L, -2); // fifos key val key | ||
407 | lua_rawget( L, 1); // fifos key val fifo|nil | ||
408 | fifo = (keeper_fifo*) lua_touserdata( L, -1); | ||
409 | if( fifo == NULL) // can be NULL if we store a value at a new key | ||
410 | { // fifos key val nil | ||
411 | lua_pop( L, 1); // fifos key val | ||
412 | fifo_new( L); // fifos key val fifo | ||
413 | lua_pushvalue( L, 2); // fifos key val fifo key | ||
414 | lua_pushvalue( L, -2); // fifos key val fifo key fifo | ||
415 | lua_rawset( L, 1); // fifos key val fifo | ||
416 | } | ||
417 | else // the fifo exists, we just want to update its contents | ||
418 | { // fifos key val fifo | ||
419 | // we create room if the fifo was full but it is no longer the case | ||
420 | should_wake_writers = (fifo->limit > 0) && (fifo->count >= fifo->limit); | ||
421 | // empty the fifo for the specified key: replace uservalue with a virgin table, reset counters, but leave limit unchanged! | ||
422 | lua_newtable( L); // fifos key val fifo {} | ||
423 | lua_setuservalue( L, -2); // fifos key val fifo | ||
424 | fifo->first = 1; | ||
425 | fifo->count = 0; | ||
426 | } | ||
427 | fifo = prepare_fifo_access( L, -1); | ||
428 | lua_insert( L, -2); // fifos key fifo val | ||
429 | fifo_push( L, fifo, 1); // fifos key fifo | ||
430 | } | ||
431 | else // val == nil: we clear the key contents | ||
432 | { // fifos key nil | ||
433 | keeper_fifo* fifo; | ||
434 | lua_pop( L, 1); // fifos key | ||
435 | lua_pushvalue( L, -1); // fifos key key | 402 | lua_pushvalue( L, -1); // fifos key key |
436 | lua_rawget( L, 1); // fifos key fifo|nil | 403 | lua_rawget( L, 1); // fifos key fifo|nil |
437 | // empty the fifo for the specified key: replace uservalue with a virgin table, reset counters, but leave limit unchanged! | 404 | // empty the fifo for the specified key: replace uservalue with a virgin table, reset counters, but leave limit unchanged! |
@@ -456,13 +423,51 @@ int keepercall_set( lua_State* L) | |||
456 | } | 423 | } |
457 | } | 424 | } |
458 | } | 425 | } |
426 | else // set/replace contents stored at the specified key? | ||
427 | { | ||
428 | int count = lua_gettop( L) - 2; // number of items we want to store | ||
429 | keeper_fifo* fifo; // fifos key [val [, ...]] | ||
430 | lua_pushvalue( L, 2); // fifos key [val [, ...]] key | ||
431 | lua_rawget( L, 1); // fifos key [val [, ...]] fifo|nil | ||
432 | fifo = (keeper_fifo*) lua_touserdata( L, -1); | ||
433 | if( fifo == NULL) // can be NULL if we store a value at a new key | ||
434 | { // fifos key [val [, ...]] nil | ||
435 | // no need to wake writers in that case, because a writer can't wait on an inexistent key | ||
436 | lua_pop( L, 1); // fifos key [val [, ...]] | ||
437 | fifo_new( L); // fifos key [val [, ...]] fifo | ||
438 | lua_pushvalue( L, 2); // fifos key [val [, ...]] fifo key | ||
439 | lua_pushvalue( L, -2); // fifos key [val [, ...]] fifo key fifo | ||
440 | lua_rawset( L, 1); // fifos key [val [, ...]] fifo | ||
441 | } | ||
442 | else // the fifo exists, we just want to update its contents | ||
443 | { // fifos key [val [, ...]] fifo | ||
444 | // we create room if the fifo was full but it is no longer the case | ||
445 | should_wake_writers = (fifo->limit > 0) && (fifo->count >= fifo->limit) && (count < fifo->limit); | ||
446 | // empty the fifo for the specified key: replace uservalue with a virgin table, reset counters, but leave limit unchanged! | ||
447 | lua_newtable( L); // fifos key [val [, ...]] fifo {} | ||
448 | lua_setuservalue( L, -2); // fifos key [val [, ...]] fifo | ||
449 | fifo->first = 1; | ||
450 | fifo->count = 0; | ||
451 | } | ||
452 | fifo = prepare_fifo_access( L, -1); | ||
453 | // move the fifo below the values we want to store | ||
454 | lua_insert( L, 3); // fifos key fifo [val [, ...]] | ||
455 | fifo_push( L, fifo, count); // fifos key fifo | ||
456 | } | ||
459 | return should_wake_writers ? (lua_pushboolean( L, 1), 1) : 0; | 457 | return should_wake_writers ? (lua_pushboolean( L, 1), 1) : 0; |
460 | } | 458 | } |
461 | 459 | ||
462 | // in: linda_ud key | 460 | // in: linda_ud key [count] |
461 | // out: at most <count> values | ||
463 | int keepercall_get( lua_State* L) | 462 | int keepercall_get( lua_State* L) |
464 | { | 463 | { |
465 | keeper_fifo* fifo; | 464 | keeper_fifo* fifo; |
465 | int count = 1; | ||
466 | if( lua_gettop( L) == 3) // ud key count | ||
467 | { | ||
468 | count = lua_tointeger( L, 3); | ||
469 | lua_pop( L, 1); // ud key | ||
470 | } | ||
466 | push_table( L, 1); // ud key fifos | 471 | push_table( L, 1); // ud key fifos |
467 | lua_replace( L, 1); // fifos key | 472 | lua_replace( L, 1); // fifos key |
468 | lua_rawget( L, 1); // fifos fifo | 473 | lua_rawget( L, 1); // fifos fifo |
@@ -470,9 +475,10 @@ int keepercall_get( lua_State* L) | |||
470 | if( fifo != NULL && fifo->count > 0) | 475 | if( fifo != NULL && fifo->count > 0) |
471 | { | 476 | { |
472 | lua_remove( L, 1); // fifo | 477 | lua_remove( L, 1); // fifo |
473 | // read one value off the fifo | 478 | count = __min( count, fifo->count); |
474 | fifo_peek( L, fifo, 1); // fifo ... | 479 | // read <count> value off the fifo |
475 | return 1; | 480 | fifo_peek( L, fifo, count); // fifo ... |
481 | return count; | ||
476 | } | 482 | } |
477 | // no fifo was ever registered for this key, or it is empty | 483 | // no fifo was ever registered for this key, or it is empty |
478 | return 0; | 484 | return 0; |
@@ -682,16 +688,16 @@ void keeper_release( struct s_Keeper* K) | |||
682 | if( K) MUTEX_UNLOCK( &K->lock_); | 688 | if( K) MUTEX_UNLOCK( &K->lock_); |
683 | } | 689 | } |
684 | 690 | ||
685 | void keeper_toggle_nil_sentinels( lua_State* L, int _val_i, int _nil_to_sentinel) | 691 | void keeper_toggle_nil_sentinels( lua_State* L, int val_i_, enum eLookupMode mode_) |
686 | { | 692 | { |
687 | int i, n = lua_gettop( L); | 693 | int i, n = lua_gettop( L); |
688 | /* We could use an empty table in 'keeper.lua' as the sentinel, but maybe | 694 | /* We could use an empty table in 'keeper.lua' as the sentinel, but maybe |
689 | * checking for a lightuserdata is faster. (any unique value will do -> take the address of some global of ours) | 695 | * checking for a lightuserdata is faster. (any unique value will do -> take the address of some global of ours) |
690 | */ | 696 | */ |
691 | void* nil_sentinel = &GNbKeepers; | 697 | void* nil_sentinel = &GNbKeepers; |
692 | for( i = _val_i; i <= n; ++ i) | 698 | for( i = val_i_; i <= n; ++ i) |
693 | { | 699 | { |
694 | if( _nil_to_sentinel) | 700 | if( mode_ == eLM_ToKeeper) |
695 | { | 701 | { |
696 | if( lua_isnil( L, i)) | 702 | if( lua_isnil( L, i)) |
697 | { | 703 | { |