aboutsummaryrefslogtreecommitdiff
path: root/src/tools.c
diff options
context:
space:
mode:
authorBenoit Germain <bnt period germain arrobase gmail period com>2014-02-17 11:05:19 +0100
committerBenoit Germain <bnt period germain arrobase gmail period com>2014-02-17 11:05:19 +0100
commit47eb3f94373a13ac9f204ca65dfde602f53bdc1a (patch)
tree95d7d7a52ca92e6527d46d97207d3f079611a355 /src/tools.c
parent32ad991eb8c590472607d61e9a831d2ca9db05c5 (diff)
downloadlanes-47eb3f94373a13ac9f204ca65dfde602f53bdc1a.tar.gz
lanes-47eb3f94373a13ac9f204ca65dfde602f53bdc1a.tar.bz2
lanes-47eb3f94373a13ac9f204ca65dfde602f53bdc1a.zip
Deep userdata support improvements
* bumped version to 3.9.0 * keepers now require "package", receive package.path & package.cpath, and call on_state_create() if it is a C function * changed the deep public API (improved deep idfunc signature, renamed luaG_deep_userdata to luaG_newdeepuserdata) * if an error occurs while copying a deep userdata, don't raise inside the keeper state * fixed situations where raised errors could lead to memory leaks (deep gc)
Diffstat (limited to 'src/tools.c')
-rw-r--r--src/tools.c791
1 files changed, 372 insertions, 419 deletions
diff --git a/src/tools.c b/src/tools.c
index fc3e7e0..2aa9b82 100644
--- a/src/tools.c
+++ b/src/tools.c
@@ -195,14 +195,14 @@ int initialize_on_state_create( lua_State* L)
195} 195}
196 196
197// just like lua_xmove, args are (from, to) 197// just like lua_xmove, args are (from, to)
198void luaG_copy_one_time_settings( lua_State* L, lua_State* L2, char const* name_) 198void luaG_copy_one_time_settings( lua_State* L, lua_State* L2)
199{ 199{
200 STACK_GROW( L, 1); 200 STACK_GROW( L, 1);
201 // copy settings from from source to destination registry 201 // copy settings from from source to destination registry
202 lua_getfield( L, LUA_REGISTRYINDEX, CONFIG_REGKEY); 202 lua_getfield( L, LUA_REGISTRYINDEX, CONFIG_REGKEY);
203 if( luaG_inter_move( L, L2, 1, eLM_LaneBody) < 0) // error? 203 if( luaG_inter_move( L, L2, 1, eLM_LaneBody) < 0) // error?
204 { 204 {
205 (void) luaL_error( L, "failed to copy settings when loading %s", name_); 205 (void) luaL_error( L, "failed to copy settings when loading lanes.core");
206 } 206 }
207 lua_setfield( L2, LUA_REGISTRYINDEX, CONFIG_REGKEY); 207 lua_setfield( L2, LUA_REGISTRYINDEX, CONFIG_REGKEY);
208} 208}
@@ -258,7 +258,7 @@ static void open1lib( lua_State* L, char const* name_, size_t len_, lua_State* f
258 if( isLanesCore == TRUE) 258 if( isLanesCore == TRUE)
259 { 259 {
260 // copy settings from from source to destination registry 260 // copy settings from from source to destination registry
261 luaG_copy_one_time_settings( from_, L, name_); 261 luaG_copy_one_time_settings( from_, L);
262 } 262 }
263 // open the library as if through require(), and create a global as well if necessary (the library table is left on the stack) 263 // open the library as if through require(), and create a global as well if necessary (the library table is left on the stack)
264 luaL_requiref( L, name_, libfunc, !isLanesCore); 264 luaL_requiref( L, name_, libfunc, !isLanesCore);
@@ -591,28 +591,61 @@ void populate_func_lookup_table( lua_State* L, int _i, char const* name_)
591 DEBUGSPEW_CODE( -- debugspew_indent_depth); 591 DEBUGSPEW_CODE( -- debugspew_indent_depth);
592} 592}
593 593
594void call_on_state_create( lua_State* L, lua_State* from_, enum eLookupMode mode_)
595{
596 if( s_on_state_create_func != NULL)
597 {
598 STACK_CHECK( L);
599 DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "calling on_state_create()\n" INDENT_END));
600 if( s_on_state_create_func != initialize_on_state_create)
601 {
602 // C function: recreate a closure in the new state, bypassing the lookup scheme
603 lua_pushcfunction( L, s_on_state_create_func);
604 }
605 else // Lua function located in the config table, copied when we opened "lanes.core"
606 {
607 if( mode_ != eLM_LaneBody)
608 {
609 // if attempting to call in a keeper state, do nothing because the function doesn't exist there
610 return;
611 }
612 lua_getfield( L, LUA_REGISTRYINDEX, CONFIG_REGKEY);
613 lua_getfield( L, -1, "on_state_create");
614 lua_remove( L, -2);
615 }
616 // capture error and forward it to main state
617 if( lua_pcall( L, 0, 0, 0) != LUA_OK)
618 {
619 (void) luaL_error( from_, "on_state_create failed: \"%s\"", lua_isstring( L, -1) ? lua_tostring( L, -1) : lua_typename( L, lua_type( L, -1)));
620 }
621 STACK_END( L, 0);
622 }
623}
624
594/* 625/*
595* Like 'luaL_openlibs()' but allows the set of libraries be selected 626 * Like 'luaL_openlibs()' but allows the set of libraries be selected
596* 627 *
597* NULL no libraries, not even base 628 * NULL no libraries, not even base
598* "" base library only 629 * "" base library only
599* "io,string" named libraries 630 * "io,string" named libraries
600* "*" all libraries 631 * "*" all libraries
601* 632 *
602* Base ("unpack", "print" etc.) is always added, unless 'libs' is NULL. 633 * Base ("unpack", "print" etc.) is always added, unless 'libs' is NULL.
603* 634 *
604*/ 635 * *NOT* called for keeper states!
605lua_State* luaG_newstate( lua_State* _from, char const* libs) 636 *
637 */
638lua_State* luaG_newstate( lua_State* from_, char const* libs_)
606{ 639{
607 // reuse alloc function from the originating state 640 // reuse alloc function from the originating state
608#if PROPAGATE_ALLOCF 641#if PROPAGATE_ALLOCF
609 PROPAGATE_ALLOCF_PREP( _from); 642 PROPAGATE_ALLOCF_PREP( from_);
610#endif // PROPAGATE_ALLOCF 643#endif // PROPAGATE_ALLOCF
611 lua_State* L = PROPAGATE_ALLOCF_ALLOC(); 644 lua_State* L = PROPAGATE_ALLOCF_ALLOC();
612 645
613 if( L == NULL) 646 if( L == NULL)
614 { 647 {
615 (void) luaL_error( _from, "luaG_newstate() failed while creating state; out of memory"); 648 (void) luaL_error( from_, "luaG_newstate() failed while creating state; out of memory");
616 } 649 }
617 650
618 // we'll need this everytime we transfer some C function from/to this state 651 // we'll need this everytime we transfer some C function from/to this state
@@ -620,7 +653,7 @@ lua_State* luaG_newstate( lua_State* _from, char const* libs)
620 lua_setfield( L, LUA_REGISTRYINDEX, LOOKUP_REGKEY); 653 lua_setfield( L, LUA_REGISTRYINDEX, LOOKUP_REGKEY);
621 654
622 // neither libs (not even 'base') nor special init func: we are done 655 // neither libs (not even 'base') nor special init func: we are done
623 if( libs == NULL && s_on_state_create_func == NULL) 656 if( libs_ == NULL && s_on_state_create_func == NULL)
624 { 657 {
625 DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "luaG_newstate(NULL)\n" INDENT_END)); 658 DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "luaG_newstate(NULL)\n" INDENT_END));
626 return L; 659 return L;
@@ -636,17 +669,17 @@ lua_State* luaG_newstate( lua_State* _from, char const* libs)
636 669
637 // Anything causes 'base' to be taken in 670 // Anything causes 'base' to be taken in
638 // 671 //
639 if( libs != NULL) 672 if( libs_ != NULL)
640 { 673 {
641 // special "*" case (mainly to help with LuaJIT compatibility) 674 // special "*" case (mainly to help with LuaJIT compatibility)
642 // as we are called from luaopen_lanes_core() already, and that would deadlock 675 // as we are called from luaopen_lanes_core() already, and that would deadlock
643 if( libs[0] == '*' && libs[1] == 0) 676 if( libs_[0] == '*' && libs_[1] == 0)
644 { 677 {
645 DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "opening ALL standard libraries\n" INDENT_END)); 678 DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "opening ALL standard libraries\n" INDENT_END));
646 luaL_openlibs( L); 679 luaL_openlibs( L);
647 // don't forget lanes.core for regular lane states 680 // don't forget lanes.core for regular lane states
648 open1lib( L, "lanes.core", 10, _from); 681 open1lib( L, "lanes.core", 10, from_);
649 libs = NULL; // done with libs 682 libs_ = NULL; // done with libs
650 } 683 }
651 else 684 else
652 { 685 {
@@ -665,11 +698,11 @@ lua_State* luaG_newstate( lua_State* _from, char const* libs)
665 STACK_END( L, 0); 698 STACK_END( L, 0);
666 699
667 // scan all libraries, open them one by one 700 // scan all libraries, open them one by one
668 if( libs) 701 if( libs_)
669 { 702 {
670 char const* p; 703 char const* p;
671 unsigned int len = 0; 704 unsigned int len = 0;
672 for( p = libs; *p; p += len) 705 for( p = libs_; *p; p += len)
673 { 706 {
674 // skip delimiters ('.' can be part of name for "lanes.core") 707 // skip delimiters ('.' can be part of name for "lanes.core")
675 while( *p && !isalnum( *p) && *p != '.') 708 while( *p && !isalnum( *p) && *p != '.')
@@ -679,37 +712,17 @@ lua_State* luaG_newstate( lua_State* _from, char const* libs)
679 while( isalnum( p[len]) || p[len] == '.') 712 while( isalnum( p[len]) || p[len] == '.')
680 ++ len; 713 ++ len;
681 // open library 714 // open library
682 open1lib( L, p, len, _from); 715 open1lib( L, p, len, from_);
683 } 716 }
684 serialize_require( L); 717 serialize_require( L);
685 } 718 }
686 719
687 lua_gc( L, LUA_GCRESTART, 0); 720 lua_gc( L, LUA_GCRESTART, 0);
688 721
689 STACK_CHECK( L);
690 // call this after the base libraries are loaded and GC is restarted 722 // call this after the base libraries are loaded and GC is restarted
691 if( s_on_state_create_func != NULL) 723 call_on_state_create( L, from_, eLM_LaneBody);
692 {
693 DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "calling on_state_create()\n" INDENT_END));
694 if( s_on_state_create_func != initialize_on_state_create)
695 {
696 // C function: recreate a closure in the new state, bypassing the lookup scheme
697 lua_pushcfunction( L, s_on_state_create_func);
698 }
699 else // Lua function located in the config table
700 {
701 lua_getfield( L, LUA_REGISTRYINDEX, CONFIG_REGKEY);
702 lua_getfield( L, -1, "on_state_create");
703 lua_remove( L, -2);
704 }
705 // capture error and forward it to main state
706 if( lua_pcall( L, 0, 0, 0) != LUA_OK)
707 {
708 (void) luaL_error( _from, "on_state_create failed: \"%s\"", lua_isstring( L, -1) ? lua_tostring( L, -1) : lua_typename( L, lua_type( L, -1)));
709 }
710 STACK_MID( L, 0);
711 }
712 724
725 STACK_CHECK( L);
713 // after all this, register everything we find in our name<->function database 726 // after all this, register everything we find in our name<->function database
714 lua_pushglobaltable( L); // Lua 5.2 no longer has LUA_GLOBALSINDEX: we must push globals table on the stack 727 lua_pushglobaltable( L); // Lua 5.2 no longer has LUA_GLOBALSINDEX: we must push globals table on the stack
715 populate_func_lookup_table( L, -1, NULL); 728 populate_func_lookup_table( L, -1, NULL);
@@ -743,7 +756,7 @@ lua_State* luaG_newstate( lua_State* _from, char const* libs)
743/* 756/*
744* The deep proxy cache is a weak valued table listing all deep UD proxies indexed by the deep UD that they are proxying 757* The deep proxy cache is a weak valued table listing all deep UD proxies indexed by the deep UD that they are proxying
745*/ 758*/
746#define DEEP_PROXY_CACHE_KEY ((void*)luaG_push_proxy) 759#define DEEP_PROXY_CACHE_KEY ((void*)push_deep_proxy)
747 760
748static void push_registry_subtable_mode( lua_State *L, void *token, const char* mode ); 761static void push_registry_subtable_mode( lua_State *L, void *token, const char* mode );
749static void push_registry_subtable( lua_State *L, void *token ); 762static void push_registry_subtable( lua_State *L, void *token );
@@ -752,107 +765,76 @@ static void push_registry_subtable( lua_State *L, void *token );
752* Sets up [-1]<->[-2] two-way lookups, and ensures the lookup table exists. 765* Sets up [-1]<->[-2] two-way lookups, and ensures the lookup table exists.
753* Pops the both values off the stack. 766* Pops the both values off the stack.
754*/ 767*/
755void set_deep_lookup( lua_State *L ) { 768static void set_deep_lookup( lua_State* L)
756 769{
757 STACK_GROW(L,3); 770 STACK_GROW( L, 3);
758 771 STACK_CHECK( L); // a b
759 STACK_CHECK( L); 772 push_registry_subtable( L, DEEP_LOOKUP_KEY); // a b {}
760#if 1 773 STACK_MID( L, 1);
761 push_registry_subtable( L, DEEP_LOOKUP_KEY ); 774 lua_insert( L, -3); // {} a b
762#else 775 lua_pushvalue( L, -1); // {} a b b
763 /* ..to be removed.. */ 776 lua_pushvalue( L,-3); // {} a b b a
764 lua_pushlightuserdata( L, DEEP_LOOKUP_KEY ); 777 lua_rawset( L, -5); // {} a b
765 lua_rawget( L, LUA_REGISTRYINDEX ); 778 lua_rawset( L, -3); // {}
766 779 lua_pop( L, 1); //
767 if (lua_isnil(L,-1)) { 780 STACK_END( L, -2);
768 // First time here; let's make the lookup
769 //
770 lua_pop(L,1);
771
772 lua_newtable(L);
773 lua_pushlightuserdata( L, DEEP_LOOKUP_KEY );
774 lua_pushvalue(L,-2);
775 //
776 // [-3]: {} (2nd ref)
777 // [-2]: DEEP_LOOKUP_KEY
778 // [-1]: {}
779
780 lua_rawset( L, LUA_REGISTRYINDEX );
781 //
782 // [-1]: lookup table (empty)
783 }
784#endif
785 STACK_MID( L, 1);
786
787 lua_insert(L,-3);
788
789 // [-3]: lookup table
790 // [-2]: A
791 // [-1]: B
792
793 lua_pushvalue( L,-1 ); // B
794 lua_pushvalue( L,-3 ); // A
795 lua_rawset( L, -5 ); // B->A
796 lua_rawset( L, -3 ); // A->B
797 lua_pop( L,1 );
798
799 STACK_END( L, -2);
800} 781}
801 782
802/* 783/*
803* Pops the key (metatable or idfunc) off the stack, and replaces with the 784* Pops the key (metatable or idfunc) off the stack, and replaces with the
804* deep lookup value (idfunc/metatable/nil). 785* deep lookup value (idfunc/metatable/nil).
805*/ 786*/
806void get_deep_lookup( lua_State *L ) { 787static void get_deep_lookup( lua_State* L)
807 788{
808 STACK_GROW(L,1); 789 STACK_GROW( L, 1);
790 STACK_CHECK( L); // a
791 lua_pushlightuserdata( L, DEEP_LOOKUP_KEY); // a DLK
792 lua_rawget( L, LUA_REGISTRYINDEX); // a {}
809 793
810 STACK_CHECK( L); 794 if( !lua_isnil( L, -1))
811 lua_pushlightuserdata( L, DEEP_LOOKUP_KEY ); 795 {
812 lua_rawget( L, LUA_REGISTRYINDEX ); 796 lua_insert( L, -2); // {} a
813 797 lua_rawget( L, -2); // {} b
814 if (!lua_isnil(L,-1)) { 798 }
815 // [-2]: key (metatable or idfunc) 799 lua_remove( L, -2); // a|b
816 // [-1]: lookup table 800 STACK_END( L, 0);
817
818 lua_insert( L, -2 );
819 lua_rawget( L, -2 );
820
821 // [-2]: lookup table
822 // [-1]: value (metatable / idfunc / nil)
823 }
824 lua_remove(L,-2);
825 // remove lookup, or unused key
826 STACK_END( L, 0);
827} 801}
828 802
829/* 803/*
830* Return the registered ID function for 'index' (deep userdata proxy), 804* Return the registered ID function for 'index' (deep userdata proxy),
831* or NULL if 'index' is not a deep userdata proxy. 805* or NULL if 'index' is not a deep userdata proxy.
832*/ 806*/
833static 807static inline luaG_IdFunction get_idfunc( lua_State* L, int index, enum eLookupMode mode_)
834luaG_IdFunction get_idfunc( lua_State *L, int index )
835{ 808{
836 luaG_IdFunction ret; 809 // when looking inside a keeper, we are 100% sure the object is a deep userdata
837 810 if( mode_ == eLM_FromKeeper)
838 index = lua_absindex( L, index); 811 {
839 812 DEEP_PRELUDE** proxy = (DEEP_PRELUDE**) lua_touserdata( L, index);
840 STACK_GROW(L,1); 813 // we can (and must) cast and fetch the internally stored idfunc
841 814 return (*proxy)->idfunc;
842 STACK_CHECK( L); 815 }
843 if (!lua_getmetatable( L, index )) 816 else
844 return NULL; // no metatable 817 {
845 818 // essentially we are making sure that the metatable of the object we want to copy is stored in our metatable/idfunc database
846 // [-1]: metatable of [index] 819 // it is the only way to ensure that the userdata is indeed a deep userdata!
820 // of course, we could just trust the caller, but we won't
821 luaG_IdFunction ret;
822 STACK_GROW( L, 1);
823 STACK_CHECK( L);
824
825 if( !lua_getmetatable( L, index)) // deep ... metatable?
826 {
827 return NULL; // no metatable: can't be a deep userdata object!
828 }
847 829
848 get_deep_lookup(L); 830 // replace metatable with the idfunc pointer, if it is actually a deep userdata
849 // 831 get_deep_lookup( L); // deep ... idfunc|nil
850 // [-1]: idfunc/nil
851 832
852 ret= (luaG_IdFunction)lua_touserdata(L,-1); 833 ret = (luaG_IdFunction) lua_touserdata( L, -1); // NULL if not a userdata
853 lua_pop(L,1); 834 lua_pop( L, 1);
854 STACK_END( L, 0); 835 STACK_END( L, 0);
855 return ret; 836 return ret;
837 }
856} 838}
857 839
858 840
@@ -862,205 +844,190 @@ luaG_IdFunction get_idfunc( lua_State *L, int index )
862* End of life for a proxy object; reduce the deep reference count and clean 844* End of life for a proxy object; reduce the deep reference count and clean
863* it up if reaches 0. 845* it up if reaches 0.
864*/ 846*/
865static 847static int deep_userdata_gc( lua_State* L)
866int deep_userdata_gc( lua_State *L )
867{ 848{
868 DEEP_PRELUDE **proxy= (DEEP_PRELUDE**)lua_touserdata( L, 1 ); 849 DEEP_PRELUDE** proxy = (DEEP_PRELUDE**) lua_touserdata( L, 1);
869 DEEP_PRELUDE *p= *proxy; 850 DEEP_PRELUDE* p = *proxy;
870 int v; 851 int v;
871 852
872 *proxy= 0; // make sure we don't use it any more 853 *proxy = 0; // make sure we don't use it any more
873 854
874 MUTEX_LOCK( &deep_lock ); 855 MUTEX_LOCK( &deep_lock);
875 v= --(p->refcount); 856 v = -- (p->refcount);
876 MUTEX_UNLOCK( &deep_lock ); 857 MUTEX_UNLOCK( &deep_lock);
877
878 if (v==0)
879 {
880 // Call 'idfunc( "delete", deep_ptr )' to make deep cleanup
881 //
882 luaG_IdFunction idfunc = get_idfunc(L,1);
883 ASSERT_L(idfunc);
884
885 lua_settop( L, 0); // clean stack so we can call 'idfunc' directly
886 858
887 // void= idfunc( "delete", lightuserdata ) 859 if( v == 0)
888 // 860 {
889 lua_pushlightuserdata( L, p->deep ); 861 // clean stack so we can call 'idfunc' directly
890 idfunc( L, "delete"); 862 lua_settop( L, 0);
891 863 // Call 'idfunc( "delete", deep_ptr )' to make deep cleanup
892 // top was set to 0, then userdata was pushed. "delete" might want to pop the userdata (we don't care), but should not push anything! 864 lua_pushlightuserdata( L, p->deep);
893 if ( lua_gettop( L) > 1) 865 ASSERT_L( p->idfunc);
894 luaL_error( L, "Bad idfunc on \"delete\": returned something"); 866 p->idfunc( L, eDO_delete);
895 867 DEEP_FREE( (void*) p);
896 DEEP_FREE( (void*)p ); 868
897 } 869 // top was set to 0, then userdata was pushed. "delete" might want to pop the userdata (we don't care), but should not push anything!
898 return 0; 870 if ( lua_gettop( L) > 1)
871 {
872 luaL_error( L, "Bad idfunc(eDO_delete): should not push anything");
873 }
874 }
875 return 0;
899} 876}
900 877
901 878
902/* 879/*
903* Push a proxy userdata on the stack. 880 * Push a proxy userdata on the stack.
904* 881 * returns NULL if ok, else some error string related to bad idfunc behavior or module require problem
905* Initializes necessary structures if it's the first time 'idfunc' is being 882 * (error cannot happen with mode_ == eLM_ToKeeper)
906* used in this Lua state (metatable, registring it). Otherwise, increments the 883 *
907* reference count. 884 * Initializes necessary structures if it's the first time 'idfunc' is being
908*/ 885 * used in this Lua state (metatable, registring it). Otherwise, increments the
909void luaG_push_proxy( lua_State *L, luaG_IdFunction idfunc, DEEP_PRELUDE *prelude ) 886 * reference count.
887 */
888char const* push_deep_proxy( lua_State* L, DEEP_PRELUDE* prelude, enum eLookupMode mode_)
910{ 889{
911 DEEP_PRELUDE **proxy; 890 DEEP_PRELUDE** proxy;
912
913 // Check if a proxy already exists
914 push_registry_subtable_mode(L, DEEP_PROXY_CACHE_KEY, "v");
915 lua_pushlightuserdata(L, prelude->deep);
916 lua_rawget(L, -2);
917 if (!lua_isnil(L, -1))
918 {
919 lua_remove(L, -2); // deep proxy cache table
920 return;
921 }
922 else
923 {
924 lua_pop(L, 2); // Pop the nil and proxy cache table
925 }
926
927 MUTEX_LOCK( &deep_lock );
928 ++(prelude->refcount); // one more proxy pointing to this deep data
929 MUTEX_UNLOCK( &deep_lock );
930
931 STACK_GROW(L,4);
932
933 STACK_CHECK( L);
934
935 proxy= lua_newuserdata( L, sizeof( DEEP_PRELUDE* ) );
936 ASSERT_L(proxy);
937 *proxy= prelude;
938 891
939 // Get/create metatable for 'idfunc' (in this state) 892 // Check if a proxy already exists
940 // 893 push_registry_subtable_mode( L, DEEP_PROXY_CACHE_KEY, "v"); // DPC
941 lua_pushlightuserdata( L, idfunc ); // key 894 lua_pushlightuserdata( L, prelude->deep); // DPC deep
942 get_deep_lookup(L); 895 lua_rawget( L, -2); // DPC proxy
943 // 896 if ( !lua_isnil( L, -1))
944 // [-2]: proxy 897 {
945 // [-1]: metatable / nil 898 lua_remove( L, -2); // proxy
946 899 return NULL;
947 if (lua_isnil(L,-1)) 900 }
948 { 901 else
949 // No metatable yet. We have two things to do: 902 {
950 // 1 - make one and register it 903 lua_pop( L, 1); // DPC
951 { 904 }
952 int oldtop;
953 905
954 lua_pop( L, 1); 906 MUTEX_LOCK( &deep_lock);
907 ++ (prelude->refcount); // one more proxy pointing to this deep data
908 MUTEX_UNLOCK( &deep_lock);
955 909
956 // tbl= idfunc( "metatable" ) 910 STACK_GROW( L, 7);
957 // 911 STACK_CHECK( L);
958 oldtop = lua_gettop( L);
959 idfunc( L, "metatable");
960 //
961 // [-2]: proxy
962 // [-1]: metatable (returned by 'idfunc')
963 912
964 if (lua_gettop( L) - oldtop != 1 || !lua_istable(L, -1)) 913 proxy = lua_newuserdata( L, sizeof( DEEP_PRELUDE*)); // DPC proxy
965 { 914 ASSERT_L( proxy);
966 luaL_error( L, "Bad idfunc on \"metatable\": did not return one" ); 915 *proxy = prelude;
967 }
968 916
969 // Add '__gc' method 917 // Get/create metatable for 'idfunc' (in this state)
970 // 918 lua_pushlightuserdata( L, prelude->idfunc); // DPC proxy idfunc
971 lua_pushcfunction( L, deep_userdata_gc ); 919 get_deep_lookup( L); // DPC proxy metatable?
972 lua_setfield( L, -2, "__gc" );
973 920
974 // Memorize for later rounds 921 if( lua_isnil( L, -1)) // // No metatable yet.
975 // 922 {
976 lua_pushvalue( L,-1 ); 923 char const* modname;
977 lua_pushlightuserdata( L, idfunc ); 924 int oldtop = lua_gettop( L); // DPC proxy nil
978 // 925 lua_pop( L, 1); // DPC proxy
979 // [-4]: proxy 926 // 1 - make one and register it
980 // [-3]: metatable (2nd ref) 927 if( mode_ != eLM_ToKeeper)
981 // [-2]: metatable 928 {
982 // [-1]: idfunc 929 prelude->idfunc( L, eDO_metatable); // DPC proxy metatable
983 930 if( lua_gettop( L) - oldtop != 0 || !lua_istable( L, -1))
984 set_deep_lookup(L); 931 {
985 } 932 lua_pop( L, 3); //
986 933 return "Bad idfunc(eOP_metatable): unexpected pushed value";
987 // 2 - cause the target state to require the module that exported the idfunc 934 }
988 // this is needed because we must make sure the shared library is still loaded as long as we hold a pointer on the idfunc 935 // make sure the idfunc didn't export __gc, as we will store our own
989 STACK_CHECK( L); 936 lua_getfield( L, -1, "__gc"); // DPC proxy metatable __gc
990 { 937 if( !lua_isnil( L, -1))
991 char const * modname; 938 {
992 // make sure the function pushed a single value on the stack! 939 lua_pop( L, 4); //
993 { 940 return "idfunc-created metatable shouldn't contain __gc";
994 int oldtop = lua_gettop( L); 941 }
995 idfunc( L, "module"); // ... "module"/nil 942 lua_pop( L, 1); // DPC proxy metatable
996 if( lua_gettop( L) - oldtop != 1) 943 }
997 { 944 else
998 luaL_error( L, "Bad idfunc on \"module\": should return a single value"); 945 {
999 } 946 // keepers need a minimal metatable that only contains __gc
1000 } 947 lua_newtable( L); // DPC proxy metatable
1001 modname = luaL_optstring( L, -1, NULL); // raises an error if not a string or nil 948 }
1002 if( modname) // we actually got a module name 949 // Add our own '__gc' method
1003 { 950 lua_pushcfunction( L, deep_userdata_gc); // DPC proxy metatable __gc
1004 // somehow, L.registry._LOADED can exist without having registered the 'package' library. 951 lua_setfield( L, -2, "__gc"); // DPC proxy metatable
1005 lua_getglobal( L, "require"); // ... "module" require()
1006 // check that the module is already loaded (or being loaded, we are happy either way)
1007 if( lua_isfunction( L, -1))
1008 {
1009 lua_insert( L, -2); // ... require() "module"
1010 lua_getfield( L, LUA_REGISTRYINDEX, "_LOADED"); // ... require() "module" L.registry._LOADED
1011 if( lua_istable( L, -1))
1012 {
1013 bool_t alreadyloaded;
1014 lua_pushvalue( L, -2); // ... require() "module" L.registry._LOADED "module"
1015 lua_rawget( L, -2); // ... require() "module" L.registry._LOADED module
1016 alreadyloaded = lua_toboolean( L, -1);
1017 if( !alreadyloaded) // not loaded
1018 {
1019 lua_pop( L, 2); // ... require() "module"
1020 lua_call( L, 1, 0); // call require "modname" // ...
1021 }
1022 else // already loaded, we are happy
1023 {
1024 lua_pop( L, 4); // ...
1025 }
1026 }
1027 else // no L.registry._LOADED; can this ever happen?
1028 {
1029 luaL_error( L, "unexpected error while requiring a module");
1030 lua_pop( L, 3); // ...
1031 }
1032 }
1033 else // a module name, but no require() function :-(
1034 {
1035 luaL_error( L, "lanes receiving deep userdata should register the 'package' library");
1036 lua_pop( L, 2); // ...
1037 }
1038 }
1039 else // no module name
1040 {
1041 lua_pop( L, 1); // ...
1042 }
1043 }
1044 STACK_END( L, 0);
1045 }
1046 STACK_MID( L, 2);
1047 ASSERT_L( lua_isuserdata(L,-2) );
1048 ASSERT_L( lua_istable(L,-1) );
1049 952
1050 // [-2]: proxy userdata 953 // Memorize for later rounds
1051 // [-1]: metatable to use 954 lua_pushvalue( L, -1); // DPC proxy metatable metatable
955 lua_pushlightuserdata( L, prelude->idfunc); // DPC proxy metatable metatable idfunc
956 set_deep_lookup( L); // DPC proxy metatable
1052 957
1053 lua_setmetatable( L, -2 ); 958 // 2 - cause the target state to require the module that exported the idfunc
1054 959 // this is needed because we must make sure the shared library is still loaded as long as we hold a pointer on the idfunc
1055 // If we're here, we obviously had to create a new proxy, so cache it. 960 {
1056 push_registry_subtable_mode(L, DEEP_PROXY_CACHE_KEY, "v"); 961 int oldtop = lua_gettop( L);
1057 lua_pushlightuserdata(L, (*proxy)->deep); 962 modname = (char const*) prelude->idfunc( L, eDO_module); // DPC proxy metatable
1058 lua_pushvalue(L, -3); // Copy of the proxy 963 // make sure the function pushed nothing on the stack!
1059 lua_rawset(L, -3); 964 if( lua_gettop( L) - oldtop != 0)
1060 lua_pop(L, 1); // Remove the cache proxy table 965 {
1061 966 lua_pop( L, 3); //
1062 STACK_END( L, 1); 967 return "Bad idfunc(eOP_module): should not push anything";
1063 // [-1]: proxy userdata 968 }
969 }
970 if( modname) // we actually got a module name
971 {
972 // somehow, L.registry._LOADED can exist without having registered the 'package' library.
973 lua_getglobal( L, "require"); // DPC proxy metatable require()
974 // check that the module is already loaded (or being loaded, we are happy either way)
975 if( lua_isfunction( L, -1))
976 {
977 lua_pushstring( L, modname); // DPC proxy metatable require() "module"
978 lua_getfield( L, LUA_REGISTRYINDEX, "_LOADED"); // DPC proxy metatable require() "module" _R._LOADED
979 if( lua_istable( L, -1))
980 {
981 bool_t alreadyloaded;
982 lua_pushvalue( L, -2); // DPC proxy metatable require() "module" _R._LOADED "module"
983 lua_rawget( L, -2); // DPC proxy metatable require() "module" _R._LOADED module
984 alreadyloaded = lua_toboolean( L, -1);
985 if( !alreadyloaded) // not loaded
986 {
987 int require_result;
988 lua_pop( L, 2); // DPC proxy metatable require() "module"
989 // require "modname"
990 require_result = lua_pcall( L, 1, 0, 0); // DPC proxy metatable error?
991 if( require_result != LUA_OK)
992 {
993 // failed, return the error message
994 lua_pushfstring( L, "error while requiring '%s' identified by idfunc(eOP_module): ", modname);
995 lua_insert( L, -2); // DPC proxy metatable prefix error
996 lua_concat( L, 2); // DPC proxy metatable error
997 return lua_tostring( L, -1);
998 }
999 }
1000 else // already loaded, we are happy
1001 {
1002 lua_pop( L, 4); // DPC proxy metatable
1003 }
1004 }
1005 else // no L.registry._LOADED; can this ever happen?
1006 {
1007 lua_pop( L, 6); //
1008 return "unexpected error while requiring a module identified by idfunc(eOP_module)";
1009 }
1010 }
1011 else // a module name, but no require() function :-(
1012 {
1013 lua_pop( L, 4); //
1014 return "lanes receiving deep userdata should register the 'package' library";
1015 }
1016 }
1017 }
1018 STACK_MID( L, 2); // DPC proxy metatable
1019 ASSERT_L( lua_isuserdata( L, -2));
1020 ASSERT_L( lua_istable( L, -1));
1021 lua_setmetatable( L, -2); // DPC proxy
1022
1023 // If we're here, we obviously had to create a new proxy, so cache it.
1024 lua_pushlightuserdata( L, (*proxy)->deep); // DPC proxy deep
1025 lua_pushvalue( L, -2); // DPC proxy deep proxy
1026 lua_rawset( L, -4); // DPC proxy
1027 lua_remove( L, -2); // proxy
1028 ASSERT_L( lua_isuserdata( L, -1));
1029 STACK_END( L, 0);
1030 return NULL;
1064} 1031}
1065 1032
1066 1033
@@ -1086,39 +1053,34 @@ void luaG_push_proxy( lua_State *L, luaG_IdFunction idfunc, DEEP_PRELUDE *prelud
1086* 1053*
1087* Returns: 'proxy' userdata for accessing the deep data via 'luaG_todeep()' 1054* Returns: 'proxy' userdata for accessing the deep data via 'luaG_todeep()'
1088*/ 1055*/
1089int luaG_deep_userdata( lua_State *L, luaG_IdFunction idfunc) 1056int luaG_newdeepuserdata( lua_State* L, luaG_IdFunction idfunc)
1090{ 1057{
1091 int oldtop; 1058 char const* errmsg;
1092 1059 DEEP_PRELUDE* prelude = DEEP_MALLOC( sizeof(DEEP_PRELUDE));
1093 DEEP_PRELUDE *prelude= DEEP_MALLOC( sizeof(DEEP_PRELUDE) ); 1060 ASSERT_L( prelude);
1094 ASSERT_L(prelude);
1095
1096 prelude->refcount= 0; // 'luaG_push_proxy' will lift it to 1
1097
1098 STACK_GROW(L,1);
1099 STACK_CHECK( L);
1100
1101 // lightuserdata= idfunc( "new" [, ...] )
1102 //
1103 oldtop = lua_gettop( L);
1104 idfunc(L, "new");
1105
1106 if( lua_gettop( L) - oldtop != 1 || lua_type( L, -1) != LUA_TLIGHTUSERDATA)
1107 {
1108 luaL_error( L, "Bad idfunc on \"new\": did not return light userdata");
1109 }
1110 1061
1111 prelude->deep= lua_touserdata(L,-1); 1062 prelude->refcount = 0; // 'push_deep_proxy' will lift it to 1
1112 ASSERT_L(prelude->deep); 1063 prelude->idfunc = idfunc;
1113 1064
1114 lua_pop(L,1); // pop deep data 1065 STACK_GROW( L, 1);
1115 1066 STACK_CHECK( L);
1116 luaG_push_proxy( L, idfunc, prelude ); 1067 {
1117 // 1068 int oldtop = lua_gettop( L);
1118 // [-1]: proxy userdata 1069 prelude->deep = idfunc( L, eDO_new);
1070 ASSERT_L( prelude->deep);
1119 1071
1120 STACK_END( L, 1); 1072 if( lua_gettop( L) - oldtop != 0)
1121 return 1; 1073 {
1074 luaL_error( L, "Bad idfunc(eDO_new): should not push anything on the stack");
1075 }
1076 }
1077 errmsg = push_deep_proxy( L, prelude, eLM_LaneBody); // proxy
1078 if( errmsg != NULL)
1079 {
1080 luaL_error( L, errmsg);
1081 }
1082 STACK_END( L, 1);
1083 return 1;
1122} 1084}
1123 1085
1124 1086
@@ -1128,52 +1090,51 @@ int luaG_deep_userdata( lua_State *L, luaG_IdFunction idfunc)
1128* Reference count is not changed, and access to the deep userdata is not 1090* Reference count is not changed, and access to the deep userdata is not
1129* serialized. It is the module's responsibility to prevent conflicting usage. 1091* serialized. It is the module's responsibility to prevent conflicting usage.
1130*/ 1092*/
1131void *luaG_todeep( lua_State *L, luaG_IdFunction idfunc, int index ) 1093void* luaG_todeep( lua_State* L, luaG_IdFunction idfunc, int index)
1132{ 1094{
1133 DEEP_PRELUDE **proxy; 1095 DEEP_PRELUDE** proxy;
1134 1096
1135 STACK_CHECK( L); 1097 STACK_CHECK( L);
1136 if( get_idfunc(L,index) != idfunc) 1098 // ensure it is actually a deep userdata
1137 return NULL; // no metatable, or wrong kind 1099 if( get_idfunc( L, index, eLM_LaneBody) != idfunc)
1100 {
1101 return NULL; // no metatable, or wrong kind
1102 }
1138 1103
1139 proxy= (DEEP_PRELUDE**)lua_touserdata( L, index ); 1104 proxy = (DEEP_PRELUDE**) lua_touserdata( L, index);
1140 STACK_END( L, 0); 1105 STACK_END( L, 0);
1141 1106
1142 return (*proxy)->deep; 1107 return (*proxy)->deep;
1143} 1108}
1144 1109
1145 1110
1146/* 1111/*
1147* Copy deep userdata between two separate Lua states. 1112 * Copy deep userdata between two separate Lua states (from L to L2)
1148* 1113 *
1149* Returns: 1114 * Returns:
1150* the id function of the copied value, or NULL for non-deep userdata 1115 * the id function of the copied value, or NULL for non-deep userdata
1151* (not copied) 1116 * (not copied)
1152*/ 1117 */
1153static 1118static luaG_IdFunction copydeep( lua_State* L, lua_State* L2, int index, enum eLookupMode mode_)
1154luaG_IdFunction luaG_copydeep( lua_State *L, lua_State *L2, int index )
1155{ 1119{
1156 DEEP_PRELUDE **proxy; 1120 char const* errmsg;
1157 DEEP_PRELUDE *p; 1121 luaG_IdFunction idfunc = get_idfunc( L, index, mode_);
1158 1122 if( idfunc == NULL)
1159 luaG_IdFunction idfunc = get_idfunc( L, index); 1123 {
1160 if (!idfunc) 1124 return NULL; // not a deep userdata
1161 return NULL; // not a deep userdata 1125 }
1162
1163 // Increment reference count
1164 //
1165 proxy= (DEEP_PRELUDE**)lua_touserdata( L, index );
1166 p= *proxy;
1167
1168 luaG_push_proxy( L2, idfunc, p );
1169 //
1170 // L2 [-1]: proxy userdata
1171 1126
1172 return idfunc; 1127 errmsg = push_deep_proxy( L2, *(DEEP_PRELUDE**) lua_touserdata( L, index), mode_);
1128 if( errmsg != NULL)
1129 {
1130 // raise the error in the proper state (not the keeper)
1131 lua_State* errL = (mode_ == eLM_FromKeeper) ? L2 : L;
1132 luaL_error( errL, errmsg);
1133 }
1134 return idfunc;
1173} 1135}
1174 1136
1175 1137
1176
1177/*---=== Inter-state copying ===---*/ 1138/*---=== Inter-state copying ===---*/
1178 1139
1179/*-- Metatable copying --*/ 1140/*-- Metatable copying --*/
@@ -1190,51 +1151,45 @@ luaG_IdFunction luaG_copydeep( lua_State *L, lua_State *L2, int index )
1190/* 1151/*
1191* Does what the original 'push_registry_subtable' function did, but adds an optional mode argument to it 1152* Does what the original 'push_registry_subtable' function did, but adds an optional mode argument to it
1192*/ 1153*/
1193static 1154static void push_registry_subtable_mode( lua_State* L, void* key_, const char* mode_)
1194void push_registry_subtable_mode( lua_State *L, void *token, const char* mode ) { 1155{
1156 STACK_GROW( L, 3);
1157 STACK_CHECK( L);
1195 1158
1196 STACK_GROW(L,3); 1159 lua_pushlightuserdata( L, key_); // key
1160 lua_rawget( L, LUA_REGISTRYINDEX); // {}|nil
1197 1161
1198 STACK_CHECK( L); 1162 if( lua_isnil( L, -1))
1199 1163 {
1200 lua_pushlightuserdata( L, token ); 1164 lua_pop( L, 1); //
1201 lua_rawget( L, LUA_REGISTRYINDEX ); 1165 lua_newtable( L); // {}
1202 // 1166 lua_pushlightuserdata( L, key_); // {} key
1203 // [-1]: nil/subtable 1167 lua_pushvalue( L, -2); // {} key {}
1204 1168
1205 if (lua_isnil(L,-1)) { 1169 // _R[key_] = {}
1206 lua_pop(L,1); 1170 lua_rawset( L, LUA_REGISTRYINDEX); // {}
1207 lua_newtable(L); // value
1208 lua_pushlightuserdata( L, token ); // key
1209 lua_pushvalue(L,-2);
1210 //
1211 // [-3]: value (2nd ref)
1212 // [-2]: key
1213 // [-1]: value
1214
1215 lua_rawset( L, LUA_REGISTRYINDEX );
1216
1217 // Set it's metatable if requested
1218 if (mode) {
1219 lua_newtable(L);
1220 lua_pushliteral(L, "__mode");
1221 lua_pushstring(L, mode);
1222 lua_rawset(L, -3);
1223 lua_setmetatable(L, -2);
1224 }
1225 }
1226 STACK_END( L, 1);
1227 1171
1228 ASSERT_L( lua_istable(L,-1) ); 1172 // Set its metatable if requested
1173 if( mode_)
1174 {
1175 lua_newtable( L); // {} mt
1176 lua_pushliteral( L, "__mode"); // {} mt "__mode"
1177 lua_pushstring( L, mode_); // {} mt "__mode" mode
1178 lua_rawset( L, -3); // {} mt
1179 lua_setmetatable( L, -2); // {}
1180 }
1181 }
1182 STACK_END( L, 1);
1183 ASSERT_L( lua_istable( L, -1));
1229} 1184}
1230 1185
1231/* 1186/*
1232* Push a registry subtable (keyed by unique 'token') onto the stack. 1187* Push a registry subtable (keyed by unique 'key_') onto the stack.
1233* If the subtable does not exist, it is created and chained. 1188* If the subtable does not exist, it is created and chained.
1234*/ 1189*/
1235static 1190static inline void push_registry_subtable( lua_State* L, void* key_)
1236void push_registry_subtable( lua_State *L, void *token ) { 1191{
1237 push_registry_subtable_mode(L, token, NULL); 1192 push_registry_subtable_mode( L, key_, NULL);
1238} 1193}
1239 1194
1240#define REG_MTID ( (void*) get_mt_id ) 1195#define REG_MTID ( (void*) get_mt_id )
@@ -1864,12 +1819,10 @@ static void push_cached_func( lua_State* L2, uint_t L2_cache_i, lua_State* L, ui
1864static bool_t inter_copy_one_( lua_State* L2, uint_t L2_cache_i, lua_State* L, uint_t i, enum e_vt vt, enum eLookupMode mode_, char const* upName_) 1819static bool_t inter_copy_one_( lua_State* L2, uint_t L2_cache_i, lua_State* L, uint_t i, enum e_vt vt, enum eLookupMode mode_, char const* upName_)
1865{ 1820{
1866 bool_t ret = TRUE; 1821 bool_t ret = TRUE;
1867
1868 STACK_GROW( L2, 1); 1822 STACK_GROW( L2, 1);
1869
1870 STACK_CHECK( L2); 1823 STACK_CHECK( L2);
1871 1824
1872 switch ( lua_type( L, i)) 1825 switch( lua_type( L, i))
1873 { 1826 {
1874 /* Basic types allowed both as values, and as table keys */ 1827 /* Basic types allowed both as values, and as table keys */
1875 1828
@@ -1921,7 +1874,7 @@ static bool_t inter_copy_one_( lua_State* L2, uint_t L2_cache_i, lua_State* L, u
1921 /* Allow only deep userdata entities to be copied across 1874 /* Allow only deep userdata entities to be copied across
1922 */ 1875 */
1923 DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "USERDATA\n" INDENT_END)); 1876 DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "USERDATA\n" INDENT_END));
1924 if( !luaG_copydeep( L, L2, i)) 1877 if( !copydeep( L, L2, i, mode_))
1925 { 1878 {
1926 // Not a deep full userdata 1879 // Not a deep full userdata
1927 bool_t demote = FALSE; 1880 bool_t demote = FALSE;
@@ -2129,7 +2082,6 @@ static bool_t inter_copy_one_( lua_State* L2, uint_t L2_cache_i, lua_State* L, u
2129 } 2082 }
2130 2083
2131 STACK_END( L2, ret ? 1 : 0); 2084 STACK_END( L2, ret ? 1 : 0);
2132
2133 return ret; 2085 return ret;
2134} 2086}
2135 2087
@@ -2225,7 +2177,8 @@ void luaG_inter_copy_package( lua_State* L, lua_State* L2, int _idx, enum eLooku
2225 // package.loaders is renamed package.searchers in Lua 5.2 2177 // package.loaders is renamed package.searchers in Lua 5.2
2226 // but don't copy it anyway, as the function names change depending on the slot index! 2178 // but don't copy it anyway, as the function names change depending on the slot index!
2227 // users should provide an on_state_create function to setup custom loaders instead 2179 // users should provide an on_state_create function to setup custom loaders instead
2228 char const* entries[] = { "path", "cpath", "preload"/*, (LUA_VERSION_NUM == 501) ? "loaders" : "searchers"*/, NULL}; 2180 // don't copy package.preload in keeper states (they don't know how to translate functions)
2181 char const* entries[] = { "path", "cpath", (mode_ == eLM_LaneBody) ? "preload" : NULL/*, (LUA_VERSION_NUM == 501) ? "loaders" : "searchers"*/, NULL};
2229 for( i = 0; entries[i]; ++ i) 2182 for( i = 0; entries[i]; ++ i)
2230 { 2183 {
2231 DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "%s\n" INDENT_END, entries[i])); 2184 DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "%s\n" INDENT_END, entries[i]));