diff options
Diffstat (limited to 'src/keeper.c')
-rw-r--r-- | src/keeper.c | 96 |
1 files changed, 67 insertions, 29 deletions
diff --git a/src/keeper.c b/src/keeper.c index 4c90069..6d5ecbf 100644 --- a/src/keeper.c +++ b/src/keeper.c | |||
@@ -95,7 +95,7 @@ static void fifo_new( lua_State* L) | |||
95 | } | 95 | } |
96 | 96 | ||
97 | // in: expect fifo ... on top of the stack | 97 | // in: expect fifo ... on top of the stack |
98 | // out: nothing, removes all pushed values on the stack | 98 | // out: nothing, removes all pushed values from the stack |
99 | static void fifo_push( lua_State* L, keeper_fifo* fifo, int _count) | 99 | static void fifo_push( lua_State* L, keeper_fifo* fifo, int _count) |
100 | { | 100 | { |
101 | int idx = lua_gettop( L) - _count; | 101 | int idx = lua_gettop( L) - _count; |
@@ -349,7 +349,7 @@ int keepercall_receive_batched( lua_State* L) | |||
349 | } | 349 | } |
350 | 350 | ||
351 | // in: linda_ud key n | 351 | // in: linda_ud key n |
352 | // out: nothing | 352 | // out: true or nil |
353 | int keepercall_limit( lua_State* L) | 353 | int keepercall_limit( lua_State* L) |
354 | { | 354 | { |
355 | keeper_fifo* fifo; | 355 | keeper_fifo* fifo; |
@@ -358,22 +358,37 @@ int keepercall_limit( lua_State* L) | |||
358 | lua_replace( L, 1); // fifos key n | 358 | lua_replace( L, 1); // fifos key n |
359 | lua_pop( L, 1); // fifos key | 359 | lua_pop( L, 1); // fifos key |
360 | lua_pushvalue( L, -1); // fifos key key | 360 | lua_pushvalue( L, -1); // fifos key key |
361 | lua_rawget( L, -3); // fifos key fifo | 361 | lua_rawget( L, -3); // fifos key fifo|nil |
362 | fifo = (keeper_fifo*) lua_touserdata( L, -1); | 362 | fifo = (keeper_fifo*) lua_touserdata( L, -1); |
363 | if( fifo == NULL) | 363 | if( fifo == NULL) |
364 | { | 364 | { // fifos key nil |
365 | lua_pop( L, 1); // fifos key | 365 | lua_pop( L, 1); // fifos key |
366 | fifo_new( L); // fifos key fifo | 366 | fifo_new( L); // fifos key fifo |
367 | fifo = (keeper_fifo*) lua_touserdata( L, -1); | 367 | fifo = (keeper_fifo*) lua_touserdata( L, -1); |
368 | lua_rawset( L, -3); // fifos | 368 | lua_rawset( L, -3); // fifos |
369 | } | 369 | } |
370 | // remove any clutter on the stack | ||
371 | lua_settop( L, 0); | ||
372 | // return true if we decide that blocked threads waiting to write on that key should be awakened | ||
373 | // this is the case if we detect the key was full but it is no longer the case | ||
374 | if( | ||
375 | ((fifo->limit >= 0) && (fifo->count >= fifo->limit)) // the key was full if limited and count exceeded the previous limit | ||
376 | && ((limit < 0) || (fifo->count < limit)) // the key is not full if unlimited or count is lower than the new limit | ||
377 | ) | ||
378 | { | ||
379 | lua_pushboolean( L, 1); | ||
380 | } | ||
381 | // set the new limit | ||
370 | fifo->limit = limit; | 382 | fifo->limit = limit; |
371 | return 0; | 383 | // return 0 or 1 value |
384 | return lua_gettop( L); | ||
372 | } | 385 | } |
373 | 386 | ||
374 | //in: linda_ud key [val] | 387 | //in: linda_ud key [val] |
388 | //out: true or nil | ||
375 | int keepercall_set( lua_State* L) | 389 | int keepercall_set( lua_State* L) |
376 | { | 390 | { |
391 | bool_t should_wake_writers = FALSE; | ||
377 | STACK_GROW( L, 6); | 392 | STACK_GROW( L, 6); |
378 | // make sure we have a value on the stack | 393 | // make sure we have a value on the stack |
379 | if( lua_gettop( L) == 2) // ud key val? | 394 | if( lua_gettop( L) == 2) // ud key val? |
@@ -391,16 +406,18 @@ int keepercall_set( lua_State* L) | |||
391 | lua_pushvalue( L, -2); // fifos key val key | 406 | lua_pushvalue( L, -2); // fifos key val key |
392 | lua_rawget( L, 1); // fifos key val fifo|nil | 407 | lua_rawget( L, 1); // fifos key val fifo|nil |
393 | fifo = (keeper_fifo*) lua_touserdata( L, -1); | 408 | fifo = (keeper_fifo*) lua_touserdata( L, -1); |
394 | if( fifo == NULL) // might be NULL if we set a nonexistent key to nil | 409 | if( fifo == NULL) // can be NULL if we store a value at a new key |
395 | { | 410 | { // fifos key val nil |
396 | lua_pop( L, 1); // fifos key val | 411 | lua_pop( L, 1); // fifos key val |
397 | fifo_new( L); // fifos key val fifo | 412 | fifo_new( L); // fifos key val fifo |
398 | lua_pushvalue( L, 2); // fifos key val fifo key | 413 | lua_pushvalue( L, 2); // fifos key val fifo key |
399 | lua_pushvalue( L, -2); // fifos key val fifo key fifo | 414 | lua_pushvalue( L, -2); // fifos key val fifo key fifo |
400 | lua_rawset( L, 1); // fifos key val fifo | 415 | lua_rawset( L, 1); // fifos key val fifo |
401 | } | 416 | } |
402 | else // the fifo exists, we just want to clear its contents | 417 | else // the fifo exists, we just want to update its contents |
403 | { | 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); | ||
404 | // empty the fifo for the specified key: replace uservalue with a virgin table, reset counters, but leave limit unchanged! | 421 | // empty the fifo for the specified key: replace uservalue with a virgin table, reset counters, but leave limit unchanged! |
405 | lua_newtable( L); // fifos key val fifo {} | 422 | lua_newtable( L); // fifos key val fifo {} |
406 | lua_setuservalue( L, -2); // fifos key val fifo | 423 | lua_setuservalue( L, -2); // fifos key val fifo |
@@ -411,22 +428,35 @@ int keepercall_set( lua_State* L) | |||
411 | lua_insert( L, -2); // fifos key fifo val | 428 | lua_insert( L, -2); // fifos key fifo val |
412 | fifo_push( L, fifo, 1); // fifos key fifo | 429 | fifo_push( L, fifo, 1); // fifos key fifo |
413 | } | 430 | } |
414 | else // val == nil // fifos key nil | 431 | else // val == nil: we clear the key contents |
415 | { | 432 | { // fifos key nil |
416 | keeper_fifo* fifo; | 433 | keeper_fifo* fifo; |
417 | lua_pop( L, 1); // fifos key | 434 | lua_pop( L, 1); // fifos key |
418 | lua_rawget( L, 1); // fifos fifo|nil | 435 | lua_pushvalue( L, -1); // fifos key key |
436 | lua_rawget( L, 1); // fifos key fifo|nil | ||
419 | // empty the fifo for the specified key: replace uservalue with a virgin table, reset counters, but leave limit unchanged! | 437 | // empty the fifo for the specified key: replace uservalue with a virgin table, reset counters, but leave limit unchanged! |
420 | fifo = (keeper_fifo*) lua_touserdata( L, -1); | 438 | fifo = (keeper_fifo*) lua_touserdata( L, -1); |
421 | if( fifo != NULL) // might be NULL if we set a nonexistent key to nil | 439 | if( fifo != NULL) // might be NULL if we set a nonexistent key to nil |
422 | { | 440 | { // fifos key fifo |
423 | lua_newtable( L); // fifos fifo {} | 441 | if( fifo->limit < 0) // fifo limit value is the default (unlimited): we can totally remove it |
424 | lua_setuservalue( L, -2); // fifos fifo | 442 | { |
425 | fifo->first = 1; | 443 | lua_pop( L, 1); // fifos key |
426 | fifo->count = 0; | 444 | lua_pushnil( L); // fifos key nil |
445 | lua_rawset( L, -3); // fifos | ||
446 | } | ||
447 | else | ||
448 | { | ||
449 | // we create room if the fifo was full but it is no longer the case | ||
450 | should_wake_writers = (fifo->limit > 0) && (fifo->count >= fifo->limit); | ||
451 | lua_remove( L, -2); // fifos fifo | ||
452 | lua_newtable( L); // fifos fifo {} | ||
453 | lua_setuservalue( L, -2); // fifos fifo | ||
454 | fifo->first = 1; | ||
455 | fifo->count = 0; | ||
456 | } | ||
427 | } | 457 | } |
428 | } | 458 | } |
429 | return 0; | 459 | return should_wake_writers ? (lua_pushboolean( L, 1), 1) : 0; |
430 | } | 460 | } |
431 | 461 | ||
432 | // in: linda_ud key | 462 | // in: linda_ud key |
@@ -476,11 +506,18 @@ int keepercall_count( lua_State* L) | |||
476 | { | 506 | { |
477 | keeper_fifo* fifo; | 507 | keeper_fifo* fifo; |
478 | lua_replace( L, 1); // fifos key | 508 | lua_replace( L, 1); // fifos key |
479 | lua_rawget( L, -2); // fifos fifo | 509 | lua_rawget( L, -2); // fifos fifo|nil |
480 | fifo = prepare_fifo_access( L, -1); // fifos fifo | 510 | if( lua_isnil( L, -1)) // the key is unknown |
481 | lua_pushinteger( L, fifo->count); // fifos fifo count | 511 | { // fifos nil |
482 | lua_replace( L, -3); // count fifo | 512 | lua_remove( L, -2); // nil |
483 | lua_pop( L, 1); // count | 513 | } |
514 | else // the key is known | ||
515 | { // fifos fifo | ||
516 | fifo = prepare_fifo_access( L, -1); // fifos fifo | ||
517 | lua_pushinteger( L, fifo->count); // fifos fifo count | ||
518 | lua_replace( L, -3); // count fifo | ||
519 | lua_pop( L, 1); // count | ||
520 | } | ||
484 | } | 521 | } |
485 | break; | 522 | break; |
486 | 523 | ||
@@ -494,21 +531,22 @@ int keepercall_count( lua_State* L) | |||
494 | { | 531 | { |
495 | keeper_fifo* fifo; | 532 | keeper_fifo* fifo; |
496 | lua_pushvalue( L, -1); // out fifos keys key | 533 | lua_pushvalue( L, -1); // out fifos keys key |
497 | lua_rawget( L, 2); // out fifos keys fifo | 534 | lua_rawget( L, 2); // out fifos keys fifo|nil |
498 | fifo = prepare_fifo_access( L, -1); // out fifos keys fifo | 535 | fifo = prepare_fifo_access( L, -1); // out fifos keys fifo|nil |
499 | lua_pop( L, 1); // out fifos keys | 536 | lua_pop( L, 1); // out fifos keys |
500 | if( fifo != NULL) | 537 | if( fifo != NULL) // the key is known |
501 | { | 538 | { |
502 | lua_pushinteger( L, fifo->count); // out fifos keys count | 539 | lua_pushinteger( L, fifo->count); // out fifos keys count |
503 | lua_rawset( L, 1); // out fifos keys | 540 | lua_rawset( L, 1); // out fifos keys |
504 | } | 541 | } |
505 | else | 542 | else // the key is unknown |
506 | { | 543 | { |
507 | lua_pop( L, 1); // out fifos keys | 544 | lua_pop( L, 1); // out fifos keys |
508 | } | 545 | } |
509 | } | 546 | } |
510 | lua_pop( L, 1); // out | 547 | lua_pop( L, 1); // out |
511 | } | 548 | } |
549 | ASSERT_L( lua_gettop( L) == 1); | ||
512 | return 1; | 550 | return 1; |
513 | } | 551 | } |
514 | 552 | ||
@@ -681,7 +719,7 @@ void keeper_toggle_nil_sentinels( lua_State* L, int _val_i, int _nil_to_sentinel | |||
681 | * | 719 | * |
682 | * Returns: number of return values (pushed to 'L') or -1 in case of error | 720 | * Returns: number of return values (pushed to 'L') or -1 in case of error |
683 | */ | 721 | */ |
684 | int keeper_call( lua_State *K, keeper_api_t _func, lua_State *L, void *linda, uint_t starting_index) | 722 | int keeper_call( lua_State* K, keeper_api_t func_, lua_State* L, void* linda, uint_t starting_index) |
685 | { | 723 | { |
686 | int const args = starting_index ? (lua_gettop( L) - starting_index + 1) : 0; | 724 | int const args = starting_index ? (lua_gettop( L) - starting_index + 1) : 0; |
687 | int const Ktos = lua_gettop( K); | 725 | int const Ktos = lua_gettop( K); |
@@ -689,7 +727,7 @@ int keeper_call( lua_State *K, keeper_api_t _func, lua_State *L, void *linda, ui | |||
689 | 727 | ||
690 | STACK_GROW( K, 2); | 728 | STACK_GROW( K, 2); |
691 | 729 | ||
692 | PUSH_KEEPER_FUNC( K, _func); | 730 | PUSH_KEEPER_FUNC( K, func_); |
693 | 731 | ||
694 | lua_pushlightuserdata( K, linda); | 732 | lua_pushlightuserdata( K, linda); |
695 | 733 | ||