aboutsummaryrefslogtreecommitdiff
path: root/src/keeper.c
diff options
context:
space:
mode:
authorBenoit Germain <bnt period germain arrobase gmail period com>2014-01-20 10:51:11 +0100
committerBenoit Germain <bnt period germain arrobase gmail period com>2014-01-20 10:51:11 +0100
commitcf9b09ff352611fb8cee3679127f3655cbe73ae7 (patch)
tree011ae091b0bff2d10a9e8dd0fd564ab2b6365f86 /src/keeper.c
parent1843a0add00186eee129b0b0a2ee605866acbb61 (diff)
downloadlanes-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.c102
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
118static void fifo_peek( lua_State* L, keeper_fifo* fifo, int _count) 118static 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
389int keepercall_set( lua_State* L) 389int 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
463int keepercall_get( lua_State* L) 462int 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
685void keeper_toggle_nil_sentinels( lua_State* L, int _val_i, int _nil_to_sentinel) 691void 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 {