diff options
author | Benoit Germain <bnt.germain@gmail.com> | 2013-01-24 22:46:21 +0100 |
---|---|---|
committer | Benoit Germain <bnt.germain@gmail.com> | 2013-01-24 22:46:21 +0100 |
commit | 68d8db431ec2b739dc53233d6b4d8aeee9324e48 (patch) | |
tree | d8f0fbe0f8c4e1a07ac4248fd1b7673f49beb4d3 /src/keeper.c | |
parent | 623fb3c0cae9beb3d5e7d3f7424b47d80041c1ac (diff) | |
download | lanes-3.4.3.tar.gz lanes-3.4.3.tar.bz2 lanes-3.4.3.zip |
version 3.4.3v3.4.3
* raise an error if lane generator libs specification contains a lib more than once
* bit32 is a valid lib name in the libs specification (silently ignored by the Lua 5.1 build)
* improved lanes.nameof to search inside table- and userdata- metatables for an object's name
* fixed an unwarranted error when trying to discover a function name upon a failed transfer
* contents of package.[path,cpath,preload,loaders|searchers] are pulled *only once* inside keeper states at initialisation
* Lua function upvalues equal to the global environment aren't copied by value, but bound to the destination's global environment
especially useful for Lua 5.2 _ENV
* fixed loading of base libraries that didn't create the global tables when built for Lua 5.2
Diffstat (limited to 'src/keeper.c')
-rw-r--r-- | src/keeper.c | 57 |
1 files changed, 23 insertions, 34 deletions
diff --git a/src/keeper.c b/src/keeper.c index 0be4fd3..a7c8647 100644 --- a/src/keeper.c +++ b/src/keeper.c | |||
@@ -557,7 +557,7 @@ void close_keepers( void) | |||
557 | * unclosed, because it does not really matter. In production code, this | 557 | * unclosed, because it does not really matter. In production code, this |
558 | * function never fails. | 558 | * function never fails. |
559 | */ | 559 | */ |
560 | char const* init_keepers( int const _nbKeepers, lua_CFunction _on_state_create) | 560 | char const* init_keepers( lua_State* L, int const _nbKeepers, lua_CFunction _on_state_create) |
561 | { | 561 | { |
562 | int i; | 562 | int i; |
563 | assert( _nbKeepers >= 1); | 563 | assert( _nbKeepers >= 1); |
@@ -565,15 +565,16 @@ char const* init_keepers( int const _nbKeepers, lua_CFunction _on_state_create) | |||
565 | GKeepers = malloc( _nbKeepers * sizeof( struct s_Keeper)); | 565 | GKeepers = malloc( _nbKeepers * sizeof( struct s_Keeper)); |
566 | for( i = 0; i < _nbKeepers; ++ i) | 566 | for( i = 0; i < _nbKeepers; ++ i) |
567 | { | 567 | { |
568 | |||
569 | // We need to load all base libraries in the keeper states so that the transfer databases are populated properly | 568 | // We need to load all base libraries in the keeper states so that the transfer databases are populated properly |
570 | // | 569 | // |
571 | // 'io' for debugging messages, 'package' because we need to require modules exporting idfuncs | 570 | // 'io' for debugging messages, 'package' because we need to require modules exporting idfuncs |
572 | // the others because they export functions that we may store in a keeper for transfer between lanes | 571 | // the others because they export functions that we may store in a keeper for transfer between lanes |
573 | lua_State* K = luaG_newstate( "*", _on_state_create); | 572 | lua_State* K = luaG_newstate( "*", _on_state_create); |
574 | if (!K) | 573 | if( !K) |
575 | return "out of memory"; | 574 | return "out of memory"; |
576 | 575 | ||
576 | DEBUGSPEW_CODE( fprintf( stderr, "init_keepers %d\n", i)); | ||
577 | |||
577 | STACK_CHECK( K) | 578 | STACK_CHECK( K) |
578 | // to see VM name in Decoda debugger | 579 | // to see VM name in Decoda debugger |
579 | lua_pushliteral( K, "Keeper #"); | 580 | lua_pushliteral( K, "Keeper #"); |
@@ -581,6 +582,11 @@ char const* init_keepers( int const _nbKeepers, lua_CFunction _on_state_create) | |||
581 | lua_concat( K, 2); | 582 | lua_concat( K, 2); |
582 | lua_setglobal( K, "decoda_name"); | 583 | lua_setglobal( K, "decoda_name"); |
583 | 584 | ||
585 | // replace default 'package' contents with stuff gotten from the master state | ||
586 | lua_getglobal( L, "package"); | ||
587 | luaG_inter_copy_package( L, K, -1); | ||
588 | lua_pop( L, 1); | ||
589 | |||
584 | #if KEEPER_MODEL == KEEPER_MODEL_C | 590 | #if KEEPER_MODEL == KEEPER_MODEL_C |
585 | // create the fifos table in the keeper state | 591 | // create the fifos table in the keeper state |
586 | lua_pushlightuserdata( K, fifos_key); | 592 | lua_pushlightuserdata( K, fifos_key); |
@@ -589,7 +595,7 @@ char const* init_keepers( int const _nbKeepers, lua_CFunction _on_state_create) | |||
589 | #endif // KEEPER_MODEL == KEEPER_MODEL_C | 595 | #endif // KEEPER_MODEL == KEEPER_MODEL_C |
590 | 596 | ||
591 | #if KEEPER_MODEL == KEEPER_MODEL_LUA | 597 | #if KEEPER_MODEL == KEEPER_MODEL_LUA |
592 | // use package.loaders[2] to find keeper microcode | 598 | // use package.loaders[2] to find keeper microcode (NOTE: this works only if nobody tampered with the loaders table...) |
593 | lua_getglobal( K, "package"); // package | 599 | lua_getglobal( K, "package"); // package |
594 | lua_getfield( K, -1, "loaders"); // package package.loaders | 600 | lua_getfield( K, -1, "loaders"); // package package.loaders |
595 | lua_rawgeti( K, -1, 2); // package package.loaders package.loaders[2] | 601 | lua_rawgeti( K, -1, 2); // package package.loaders package.loaders[2] |
@@ -619,55 +625,38 @@ char const* init_keepers( int const _nbKeepers, lua_CFunction _on_state_create) | |||
619 | } | 625 | } |
620 | 626 | ||
621 | // cause each keeper state to populate its database of transferable functions with those from the specified module | 627 | // cause each keeper state to populate its database of transferable functions with those from the specified module |
622 | void populate_keepers( lua_State *L) | 628 | // do do this we simply require the module inside the keeper state, then populate the lookup database |
629 | void populate_keepers( lua_State* L) | ||
623 | { | 630 | { |
624 | size_t name_len; | 631 | size_t name_len; |
625 | char const *name = luaL_checklstring( L, -1, &name_len); | 632 | char const* name = luaL_checklstring( L, -1, &name_len); |
626 | size_t package_path_len; | ||
627 | char const *package_path; | ||
628 | size_t package_cpath_len; | ||
629 | char const *package_cpath; | ||
630 | int i; | 633 | int i; |
631 | 634 | ||
632 | // we need to make sure that package.path & package.cpath are the same in the keepers | 635 | STACK_CHECK( L) |
633 | // than what is currently in use when the module is required in the caller's Lua state | ||
634 | STACK_CHECK(L) | ||
635 | STACK_GROW( L, 3); | 636 | STACK_GROW( L, 3); |
636 | lua_getglobal( L, "package"); | ||
637 | lua_getfield( L, -1, "path"); | ||
638 | package_path = luaL_checklstring( L, -1, &package_path_len); | ||
639 | lua_getfield( L, -2, "cpath"); | ||
640 | package_cpath = luaL_checklstring( L, -1, &package_cpath_len); | ||
641 | 637 | ||
642 | for( i = 0; i < GNbKeepers; ++ i) | 638 | for( i = 0; i < GNbKeepers; ++ i) |
643 | { | 639 | { |
644 | lua_State *K = GKeepers[i].L; | 640 | lua_State* K = GKeepers[i].L; |
645 | int res; | 641 | int res; |
646 | MUTEX_LOCK( &GKeepers[i].lock_); | 642 | MUTEX_LOCK( &GKeepers[i].lock_); |
647 | STACK_CHECK(K) | 643 | STACK_CHECK( K) |
648 | STACK_GROW( K, 2); | 644 | STACK_GROW( K, 2); |
649 | lua_getglobal( K, "package"); | ||
650 | lua_pushlstring( K, package_path, package_path_len); | ||
651 | lua_setfield( K, -2, "path"); | ||
652 | lua_pushlstring( K, package_cpath, package_cpath_len); | ||
653 | lua_setfield( K, -2, "cpath"); | ||
654 | lua_pop( K, 1); | ||
655 | lua_getglobal( K, "require"); | 645 | lua_getglobal( K, "require"); |
656 | lua_pushlstring( K, name, name_len); | 646 | lua_pushlstring( K, name, name_len); |
657 | res = lua_pcall( K, 1, 0, 0); | 647 | res = lua_pcall( K, 1, 0, 0); |
658 | if( res != 0) | 648 | if( res != 0) |
659 | { | 649 | { |
660 | char const *err = luaL_checkstring( K, -1); | 650 | char const* err = luaL_checkstring( K, -1); |
661 | luaL_error( L, "error requiring '%s' in keeper state: %s", name, err); | 651 | luaL_error( L, "error requiring '%s' in keeper state: %s", name, err); |
662 | } | 652 | } |
663 | STACK_END(K, 0) | 653 | STACK_END( K, 0) |
664 | MUTEX_UNLOCK( &GKeepers[i].lock_); | 654 | MUTEX_UNLOCK( &GKeepers[i].lock_); |
665 | } | 655 | } |
666 | lua_pop( L, 3); | 656 | STACK_END( L, 0) |
667 | STACK_END(L, 0) | ||
668 | } | 657 | } |
669 | 658 | ||
670 | struct s_Keeper *keeper_acquire( const void *ptr) | 659 | struct s_Keeper* keeper_acquire( void const* ptr) |
671 | { | 660 | { |
672 | // can be 0 if this happens during main state shutdown (lanes is being GC'ed -> no keepers) | 661 | // can be 0 if this happens during main state shutdown (lanes is being GC'ed -> no keepers) |
673 | if( GNbKeepers == 0) | 662 | if( GNbKeepers == 0) |
@@ -691,19 +680,19 @@ struct s_Keeper *keeper_acquire( const void *ptr) | |||
691 | } | 680 | } |
692 | } | 681 | } |
693 | 682 | ||
694 | void keeper_release( struct s_Keeper *K) | 683 | void keeper_release( struct s_Keeper* K) |
695 | { | 684 | { |
696 | //-- K->count; | 685 | //-- K->count; |
697 | if( K) MUTEX_UNLOCK( &K->lock_); | 686 | if( K) MUTEX_UNLOCK( &K->lock_); |
698 | } | 687 | } |
699 | 688 | ||
700 | void keeper_toggle_nil_sentinels( lua_State *L, int _val_i, int _nil_to_sentinel) | 689 | void keeper_toggle_nil_sentinels( lua_State* L, int _val_i, int _nil_to_sentinel) |
701 | { | 690 | { |
702 | int i, n = lua_gettop( L); | 691 | int i, n = lua_gettop( L); |
703 | /* We could use an empty table in 'keeper.lua' as the sentinel, but maybe | 692 | /* We could use an empty table in 'keeper.lua' as the sentinel, but maybe |
704 | * checking for a lightuserdata is faster. (any unique value will do -> take the address of some global of ours) | 693 | * checking for a lightuserdata is faster. (any unique value will do -> take the address of some global of ours) |
705 | */ | 694 | */ |
706 | void *nil_sentinel = &GNbKeepers; | 695 | void* nil_sentinel = &GNbKeepers; |
707 | for( i = _val_i; i <= n; ++ i) | 696 | for( i = _val_i; i <= n; ++ i) |
708 | { | 697 | { |
709 | if( _nil_to_sentinel) | 698 | if( _nil_to_sentinel) |