aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/deep.h12
-rw-r--r--src/keeper.c44
-rw-r--r--src/lanes.c286
-rw-r--r--src/tools.c791
-rw-r--r--src/tools.h16
5 files changed, 575 insertions, 574 deletions
diff --git a/src/deep.h b/src/deep.h
index 1315157..e1f2c4f 100644
--- a/src/deep.h
+++ b/src/deep.h
@@ -15,9 +15,17 @@
15#define LANES_API 15#define LANES_API
16#endif // (defined PLATFORM_WIN32) || (defined PLATFORM_POCKETPC) 16#endif // (defined PLATFORM_WIN32) || (defined PLATFORM_POCKETPC)
17 17
18typedef void (*luaG_IdFunction)( lua_State* L, char const* const which); 18enum eDeepOp
19{
20 eDO_new,
21 eDO_delete,
22 eDO_metatable,
23 eDO_module,
24};
19 25
20extern LANES_API int luaG_deep_userdata( lua_State* L, luaG_IdFunction idfunc); 26typedef void* (*luaG_IdFunction)( lua_State* L, enum eDeepOp op_);
27
28extern LANES_API int luaG_newdeepuserdata( lua_State* L, luaG_IdFunction idfunc);
21extern LANES_API void* luaG_todeep( lua_State* L, luaG_IdFunction idfunc, int index); 29extern LANES_API void* luaG_todeep( lua_State* L, luaG_IdFunction idfunc, int index);
22 30
23#endif // __LANES_DEEP_H__ 31#endif // __LANES_DEEP_H__
diff --git a/src/keeper.c b/src/keeper.c
index c22bfed..4eb8bb3 100644
--- a/src/keeper.c
+++ b/src/keeper.c
@@ -44,6 +44,7 @@
44#include <ctype.h> 44#include <ctype.h>
45 45
46#include "lua.h" 46#include "lua.h"
47#include "lualib.h"
47#include "lauxlib.h" 48#include "lauxlib.h"
48 49
49#include "threading.h" 50#include "threading.h"
@@ -623,11 +624,10 @@ char const* init_keepers( lua_State* L)
623 int i; 624 int i;
624 PROPAGATE_ALLOCF_PREP( L); 625 PROPAGATE_ALLOCF_PREP( L);
625 626
626 STACK_CHECK( L); 627 STACK_CHECK( L); // L K
627 lua_getfield( L, 1, "nb_keepers"); 628 lua_getfield( L, 1, "nb_keepers"); // nb_keepers
628 GNbKeepers = (int) lua_tointeger( L, -1); 629 GNbKeepers = (int) lua_tointeger( L, -1);
629 lua_pop( L, 1); 630 lua_pop( L, 1); //
630 STACK_END( L, 0);
631 assert( GNbKeepers >= 1); 631 assert( GNbKeepers >= 1);
632 632
633 GKeepers = malloc( GNbKeepers * sizeof( struct s_Keeper)); 633 GKeepers = malloc( GNbKeepers * sizeof( struct s_Keeper));
@@ -640,16 +640,37 @@ char const* init_keepers( lua_State* L)
640 } 640 }
641 STACK_CHECK( K); 641 STACK_CHECK( K);
642 642
643 // make sure 'package' is initialized in keeper states, so that we have require()
644 // this because this is needed when transfering deep userdata object
645 luaL_requiref( K, "package", luaopen_package, 1); // package
646 lua_pop( K, 1); //
647 STACK_MID( K, 0);
648 serialize_require( K);
649 STACK_MID( K, 0);
650
651 // copy package.path and package.cpath from the source state
652 lua_getglobal( L, "package"); // package
653 if( !lua_isnil( L, -1))
654 {
655 luaG_inter_copy_package( L, K, -1, eLM_ToKeeper);
656 }
657 lua_pop( L, 1); //
658 STACK_MID( L, 0);
659
660 // attempt to call on_state_create(), if we have one and it is a C function
661 // (only support a C function because we can't transfer executable Lua code in keepers)
662 call_on_state_create( K, L, eLM_ToKeeper);
663
643 // to see VM name in Decoda debugger 664 // to see VM name in Decoda debugger
644 lua_pushliteral( K, "Keeper #"); 665 lua_pushliteral( K, "Keeper #"); // "Keeper #"
645 lua_pushinteger( K, i + 1); 666 lua_pushinteger( K, i + 1); // "Keeper #" n
646 lua_concat( K, 2); 667 lua_concat( K, 2); // "Keeper #n"
647 lua_setglobal( K, "decoda_name"); 668 lua_setglobal( K, "decoda_name"); //
648 669
649 // create the fifos table in the keeper state 670 // create the fifos table in the keeper state
650 lua_pushlightuserdata( K, fifos_key); 671 lua_pushlightuserdata( K, fifos_key); // fifo_key
651 lua_newtable( K); 672 lua_newtable( K); // fifo_key {}
652 lua_rawset( K, LUA_REGISTRYINDEX); 673 lua_rawset( K, LUA_REGISTRYINDEX); //
653 674
654 STACK_END( K, 0); 675 STACK_END( K, 0);
655 // we can trigger a GC from inside keeper_call(), where a keeper is acquired 676 // we can trigger a GC from inside keeper_call(), where a keeper is acquired
@@ -660,6 +681,7 @@ char const* init_keepers( lua_State* L)
660#if HAVE_KEEPER_ATEXIT_DESINIT 681#if HAVE_KEEPER_ATEXIT_DESINIT
661 atexit( atexit_close_keepers); 682 atexit( atexit_close_keepers);
662#endif // HAVE_KEEPER_ATEXIT_DESINIT 683#endif // HAVE_KEEPER_ATEXIT_DESINIT
684 STACK_END( L, 0);
663 return NULL; // ok 685 return NULL; // ok
664} 686}
665 687
diff --git a/src/lanes.c b/src/lanes.c
index dbb0a82..597ac4b 100644
--- a/src/lanes.c
+++ b/src/lanes.c
@@ -52,7 +52,7 @@
52 * ... 52 * ...
53 */ 53 */
54 54
55char const* VERSION = "3.8.5"; 55char const* VERSION = "3.9.0";
56 56
57/* 57/*
58=============================================================================== 58===============================================================================
@@ -422,11 +422,11 @@ struct s_Linda
422 char name[1]; 422 char name[1];
423}; 423};
424 424
425static void linda_id( lua_State*, char const * const which); 425static void* linda_id( lua_State*, enum eDeepOp);
426 426
427static inline struct s_Linda* lua_toLinda( lua_State* L, int idx_) 427static inline struct s_Linda* lua_toLinda( lua_State* L, int idx_)
428{ 428{
429 struct s_Linda* linda = luaG_todeep( L, linda_id, idx_); 429 struct s_Linda* linda = (struct s_Linda*) luaG_todeep( L, linda_id, idx_);
430 luaL_argcheck( L, linda != NULL, idx_, "expecting a linda object"); 430 luaL_argcheck( L, linda != NULL, idx_, "expecting a linda object");
431 return linda; 431 return linda;
432} 432}
@@ -996,7 +996,7 @@ LUAG_FUNC( linda_deep)
996 996
997static int linda_tostring( lua_State* L, int idx_, bool_t opt_) 997static int linda_tostring( lua_State* L, int idx_, bool_t opt_)
998{ 998{
999 struct s_Linda* linda = luaG_todeep( L, linda_id, idx_); 999 struct s_Linda* linda = (struct s_Linda*) luaG_todeep( L, linda_id, idx_);
1000 if( !opt_) 1000 if( !opt_)
1001 { 1001 {
1002 luaL_argcheck( L, linda, idx_, "expecting a linda object"); 1002 luaL_argcheck( L, linda, idx_, "expecting a linda object");
@@ -1084,122 +1084,127 @@ LUAG_FUNC( linda_dump)
1084* For any other strings, the ID function must not react at all. This allows 1084* For any other strings, the ID function must not react at all. This allows
1085* future extensions of the system. 1085* future extensions of the system.
1086*/ 1086*/
1087static void linda_id( lua_State* L, char const* const which) 1087static void* linda_id( lua_State* L, enum eDeepOp op_)
1088{ 1088{
1089 if( strcmp( which, "new" ) == 0) 1089 switch( op_)
1090 { 1090 {
1091 struct s_Linda* s; 1091 case eDO_new:
1092 size_t name_len = 0;
1093 char const* linda_name = NULL;
1094 int const top = lua_gettop( L);
1095
1096 if( top > 0 && lua_type( L, top) == LUA_TSTRING)
1097 { 1092 {
1098 linda_name = lua_tostring( L, top); 1093 struct s_Linda* s;
1099 name_len = strlen( linda_name); 1094 size_t name_len = 0;
1100 } 1095 char const* linda_name = NULL;
1096 int const top = lua_gettop( L);
1101 1097
1102 /* The deep data is allocated separately of Lua stack; we might no 1098 if( top > 0 && lua_type( L, top) == LUA_TSTRING)
1103 * longer be around when last reference to it is being released. 1099 {
1104 * One can use any memory allocation scheme. 1100 linda_name = lua_tolstring( L, top, &name_len);
1105 */ 1101 }
1106 s = (struct s_Linda*) malloc( sizeof(struct s_Linda) + name_len); // terminating 0 is already included
1107 ASSERT_L( s);
1108
1109 SIGNAL_INIT( &s->read_happened);
1110 SIGNAL_INIT( &s->write_happened);
1111 s->simulate_cancel = CANCEL_NONE;
1112 s->name[0] = 0;
1113 memcpy( s->name, linda_name, name_len ? name_len + 1 : 0);
1114 1102
1115 lua_pushlightuserdata( L, s); 1103 /* The deep data is allocated separately of Lua stack; we might no
1116 } 1104 * longer be around when last reference to it is being released.
1117 else if( strcmp( which, "delete") == 0) 1105 * One can use any memory allocation scheme.
1118 { 1106 */
1119 struct s_Keeper* K; 1107 s = (struct s_Linda*) malloc( sizeof(struct s_Linda) + name_len); // terminating 0 is already included
1120 struct s_Linda* l = lua_touserdata( L, 1); 1108 ASSERT_L( s);
1121 ASSERT_L( l); 1109
1110 SIGNAL_INIT( &s->read_happened);
1111 SIGNAL_INIT( &s->write_happened);
1112 s->simulate_cancel = CANCEL_NONE;
1113 s->name[0] = 0;
1114 memcpy( s->name, linda_name, name_len ? name_len + 1 : 0);
1115 return s;
1116 }
1122 1117
1123 /* Clean associated structures in the keeper state. 1118 case eDO_delete:
1124 */
1125 K = keeper_acquire( l);
1126 if( K && K->L) // can be NULL if this happens during main state shutdown (lanes is GC'ed -> no keepers -> no need to cleanup)
1127 { 1119 {
1128 keeper_call( K->L, KEEPER_API( clear), L, l, 0); 1120 struct s_Keeper* K;
1121 struct s_Linda* l = lua_touserdata( L, 1);
1122 ASSERT_L( l);
1123
1124 /* Clean associated structures in the keeper state.
1125 */
1126 K = keeper_acquire( l);
1127 if( K && K->L) // can be NULL if this happens during main state shutdown (lanes is GC'ed -> no keepers -> no need to cleanup)
1128 {
1129 keeper_call( K->L, KEEPER_API( clear), L, l, 0);
1130 }
1131 keeper_release( K);
1132
1133 /* There aren't any lanes waiting on these lindas, since all proxies
1134 * have been gc'ed. Right?
1135 */
1136 SIGNAL_FREE( &l->read_happened);
1137 SIGNAL_FREE( &l->write_happened);
1138 free( l);
1139 return NULL;
1129 } 1140 }
1130 keeper_release( K);
1131 1141
1132 /* There aren't any lanes waiting on these lindas, since all proxies 1142 case eDO_metatable:
1133 * have been gc'ed. Right? 1143 {
1134 */
1135 SIGNAL_FREE( &l->read_happened);
1136 SIGNAL_FREE( &l->write_happened);
1137 free( l);
1138 }
1139 else if( strcmp( which, "metatable" ) == 0)
1140 {
1141 1144
1142 STACK_CHECK( L); 1145 STACK_CHECK( L);
1143 lua_newtable( L); 1146 lua_newtable( L);
1144 // metatable is its own index 1147 // metatable is its own index
1145 lua_pushvalue( L, -1); 1148 lua_pushvalue( L, -1);
1146 lua_setfield( L, -2, "__index"); 1149 lua_setfield( L, -2, "__index");
1147 1150
1148 // protect metatable from external access 1151 // protect metatable from external access
1149 lua_pushliteral( L, "Linda"); 1152 lua_pushliteral( L, "Linda");
1150 lua_setfield( L, -2, "__metatable"); 1153 lua_setfield( L, -2, "__metatable");
1151 1154
1152 lua_pushcfunction( L, LG_linda_tostring); 1155 lua_pushcfunction( L, LG_linda_tostring);
1153 lua_setfield( L, -2, "__tostring"); 1156 lua_setfield( L, -2, "__tostring");
1154 1157
1155 // Decoda __towatch support 1158 // Decoda __towatch support
1156 lua_pushcfunction( L, LG_linda_dump); 1159 lua_pushcfunction( L, LG_linda_dump);
1157 lua_setfield( L, -2, "__towatch"); 1160 lua_setfield( L, -2, "__towatch");
1158 1161
1159 lua_pushcfunction( L, LG_linda_concat); 1162 lua_pushcfunction( L, LG_linda_concat);
1160 lua_setfield( L, -2, "__concat"); 1163 lua_setfield( L, -2, "__concat");
1161 1164
1162 // [-1]: linda metatable 1165 // [-1]: linda metatable
1163 lua_pushcfunction( L, LG_linda_send); 1166 lua_pushcfunction( L, LG_linda_send);
1164 lua_setfield( L, -2, "send"); 1167 lua_setfield( L, -2, "send");
1165 1168
1166 lua_pushcfunction( L, LG_linda_receive); 1169 lua_pushcfunction( L, LG_linda_receive);
1167 lua_setfield( L, -2, "receive"); 1170 lua_setfield( L, -2, "receive");
1168 1171
1169 lua_pushcfunction( L, LG_linda_limit); 1172 lua_pushcfunction( L, LG_linda_limit);
1170 lua_setfield( L, -2, "limit"); 1173 lua_setfield( L, -2, "limit");
1171 1174
1172 lua_pushcfunction( L, LG_linda_set); 1175 lua_pushcfunction( L, LG_linda_set);
1173 lua_setfield( L, -2, "set"); 1176 lua_setfield( L, -2, "set");
1174 1177
1175 lua_pushcfunction( L, LG_linda_count); 1178 lua_pushcfunction( L, LG_linda_count);
1176 lua_setfield( L, -2, "count"); 1179 lua_setfield( L, -2, "count");
1177 1180
1178 lua_pushcfunction( L, LG_linda_get); 1181 lua_pushcfunction( L, LG_linda_get);
1179 lua_setfield( L, -2, "get"); 1182 lua_setfield( L, -2, "get");
1180 1183
1181 lua_pushcfunction( L, LG_linda_cancel); 1184 lua_pushcfunction( L, LG_linda_cancel);
1182 lua_setfield( L, -2, "cancel"); 1185 lua_setfield( L, -2, "cancel");
1183 1186
1184 lua_pushcfunction( L, LG_linda_deep); 1187 lua_pushcfunction( L, LG_linda_deep);
1185 lua_setfield( L, -2, "deep"); 1188 lua_setfield( L, -2, "deep");
1186 1189
1187 lua_pushcfunction( L, LG_linda_dump); 1190 lua_pushcfunction( L, LG_linda_dump);
1188 lua_setfield( L, -2, "dump"); 1191 lua_setfield( L, -2, "dump");
1189 1192
1190 lua_pushliteral( L, BATCH_SENTINEL); 1193 lua_pushliteral( L, BATCH_SENTINEL);
1191 lua_setfield(L, -2, "batched"); 1194 lua_setfield(L, -2, "batched");
1192 1195
1193 STACK_END( L, 1); 1196 STACK_END( L, 1);
1194 } 1197 return NULL;
1195 else if( strcmp( which, "module") == 0) 1198 }
1196 { 1199
1200 case eDO_module:
1197 // linda is a special case because we know lanes must be loaded from the main lua state 1201 // linda is a special case because we know lanes must be loaded from the main lua state
1198 // to be able to ever get here, so we know it will remain loaded as long a the main state is around 1202 // to be able to ever get here, so we know it will remain loaded as long a the main state is around
1199 // in other words, forever. 1203 // in other words, forever.
1200 lua_pushnil( L); 1204 default:
1201 // other idfuncs must push a string naming the module they come from 1205 {
1202 //lua_pushliteral( L, "lanes.core"); 1206 return NULL;
1207 }
1203 } 1208 }
1204} 1209}
1205 1210
@@ -1214,7 +1219,7 @@ LUAG_FUNC( linda)
1214 luaL_argcheck( L, top <= 1, top, "too many arguments"); 1219 luaL_argcheck( L, top <= 1, top, "too many arguments");
1215 if( top == 1) 1220 if( top == 1)
1216 luaL_checktype( L, 1, LUA_TSTRING); 1221 luaL_checktype( L, 1, LUA_TSTRING);
1217 return luaG_deep_userdata( L, linda_id); 1222 return luaG_newdeepuserdata( L, linda_id);
1218} 1223}
1219 1224
1220/* 1225/*
@@ -2199,7 +2204,7 @@ LUAG_FUNC( thread_new)
2199 // which might not be the case if the libs list didn't include lanes.core or "*" 2204 // which might not be the case if the libs list didn't include lanes.core or "*"
2200 if( strncmp( name, "lanes.core", len) == 0) // this works both both "lanes" and "lanes.core" because of len 2205 if( strncmp( name, "lanes.core", len) == 0) // this works both both "lanes" and "lanes.core" because of len
2201 { 2206 {
2202 luaG_copy_one_time_settings( L, L2, name); 2207 luaG_copy_one_time_settings( L, L2);
2203 } 2208 }
2204 lua_pushlstring( L2, name, len); // require() name 2209 lua_pushlstring( L2, name, len); // require() name
2205 if( lua_pcall( L2, 1, 1, 0) != LUA_OK) // ret/errcode 2210 if( lua_pcall( L2, 1, 1, 0) != LUA_OK) // ret/errcode
@@ -2324,8 +2329,8 @@ LUAG_FUNC( thread_new)
2324 MUTEX_INIT( &s->done_lock); 2329 MUTEX_INIT( &s->done_lock);
2325 SIGNAL_INIT( &s->done_signal); 2330 SIGNAL_INIT( &s->done_signal);
2326#endif // THREADWAIT_METHOD == THREADWAIT_CONDVAR 2331#endif // THREADWAIT_METHOD == THREADWAIT_CONDVAR
2327 s->mstatus= NORMAL; 2332 s->mstatus = NORMAL;
2328 s->selfdestruct_next= NULL; 2333 s->selfdestruct_next = NULL;
2329#if HAVE_LANE_TRACKING 2334#if HAVE_LANE_TRACKING
2330 s->tracking_next = NULL; 2335 s->tracking_next = NULL;
2331#endif // HAVE_LANE_TRACKING 2336#endif // HAVE_LANE_TRACKING
@@ -2969,7 +2974,7 @@ static void init_once_LOCKED( lua_State* L)
2969 // proxy_ud= deep_userdata( idfunc ) 2974 // proxy_ud= deep_userdata( idfunc )
2970 // 2975 //
2971 lua_pushliteral( L, "lanes-timer"); // push a name for debug purposes 2976 lua_pushliteral( L, "lanes-timer"); // push a name for debug purposes
2972 luaG_deep_userdata( L, linda_id); 2977 luaG_newdeepuserdata( L, linda_id);
2973 STACK_MID( L, 2); 2978 STACK_MID( L, 2);
2974 lua_remove( L, -2); // remove the name as we no longer need it 2979 lua_remove( L, -2); // remove the name as we no longer need it
2975 2980
@@ -2978,7 +2983,7 @@ static void init_once_LOCKED( lua_State* L)
2978 // Proxy userdata contents is only a 'DEEP_PRELUDE*' pointer 2983 // Proxy userdata contents is only a 'DEEP_PRELUDE*' pointer
2979 // 2984 //
2980 timer_deep = * (DEEP_PRELUDE**) lua_touserdata( L, -1); 2985 timer_deep = * (DEEP_PRELUDE**) lua_touserdata( L, -1);
2981 ASSERT_L( timer_deep && (timer_deep->refcount == 1) && timer_deep->deep); 2986 ASSERT_L( timer_deep && (timer_deep->refcount == 1) && timer_deep->deep && timer_deep->idfunc == linda_id);
2982 2987
2983 // The host Lua state must always have a reference to this Linda object in order for the timer_deep pointer to be valid. 2988 // The host Lua state must always have a reference to this Linda object in order for the timer_deep pointer to be valid.
2984 // So store a reference that we will never actually use. 2989 // So store a reference that we will never actually use.
@@ -3019,7 +3024,7 @@ LUAG_FUNC( configure)
3019 DEBUGSPEW_CODE( ++ debugspew_indent_depth); 3024 DEBUGSPEW_CODE( ++ debugspew_indent_depth);
3020 3025
3021 // not in init_once_LOCKED because we can have several hosted "master" Lua states where Lanes is require()d. 3026 // not in init_once_LOCKED because we can have several hosted "master" Lua states where Lanes is require()d.
3022 lua_getfield( L, 1, "protect_allocator"); // settings protect_allocator 3027 lua_getfield( L, 1, "protect_allocator"); // settings protect_allocator
3023 if( lua_toboolean( L, -1)) 3028 if( lua_toboolean( L, -1))
3024 { 3029 {
3025 void* ud; 3030 void* ud;
@@ -3033,7 +3038,7 @@ LUAG_FUNC( configure)
3033 lua_setallocf( L, protected_lua_Alloc, s); 3038 lua_setallocf( L, protected_lua_Alloc, s);
3034 } 3039 }
3035 } 3040 }
3036 lua_pop( L, 1); // settings 3041 lua_pop( L, 1); // settings
3037 STACK_MID( L, 0); 3042 STACK_MID( L, 0);
3038 3043
3039 /* 3044 /*
@@ -3075,68 +3080,75 @@ LUAG_FUNC( configure)
3075#endif // THREADAPI == THREADAPI_PTHREAD 3080#endif // THREADAPI == THREADAPI_PTHREAD
3076 3081
3077 // Retrieve main module interface table 3082 // Retrieve main module interface table
3078 lua_pushvalue( L, lua_upvalueindex( 2)); // settings M 3083 lua_pushvalue( L, lua_upvalueindex( 2)); // settings M
3079 // remove configure() (this function) from the module interface 3084 // remove configure() (this function) from the module interface
3080 lua_pushnil( L); // settings M nil 3085 lua_pushnil( L); // settings M nil
3081 lua_setfield( L, -2, "configure"); // settings M 3086 lua_setfield( L, -2, "configure"); // settings M
3082 // add functions to the module's table 3087 // add functions to the module's table
3083 luaG_registerlibfuncs( L, lanes_functions); 3088 luaG_registerlibfuncs( L, lanes_functions);
3084#if HAVE_LANE_TRACKING 3089#if HAVE_LANE_TRACKING
3085 // register core.threads() only if settings say it should be available 3090 // register core.threads() only if settings say it should be available
3086 if( tracking_first != NULL) 3091 if( tracking_first != NULL)
3087 { 3092 {
3088 lua_pushcfunction( L, LG_threads); // settings M LG_threads() 3093 lua_pushcfunction( L, LG_threads); // settings M LG_threads()
3089 lua_setfield( L, -2, "threads"); 3094 lua_setfield( L, -2, "threads"); // settings M
3090 } 3095 }
3091#endif // HAVE_LANE_TRACKING 3096#endif // HAVE_LANE_TRACKING
3092 STACK_MID( L, 1); 3097 STACK_MID( L, 1);
3093 3098
3094 ASSERT_L( timer_deep != NULL); // initialized by init_once_LOCKED 3099 {
3095 luaG_push_proxy( L, linda_id, (DEEP_PRELUDE*) timer_deep); // settings M timer_deep 3100 char const* errmsg;
3096 lua_setfield( L, -2, "timer_gateway"); // settings M 3101 ASSERT_L( timer_deep != NULL); // initialized by init_once_LOCKED
3102 errmsg = push_deep_proxy( L, (DEEP_PRELUDE*) timer_deep, eLM_LaneBody); // settings M timer_deep
3103 if( errmsg != NULL)
3104 {
3105 luaL_error( L, errmsg);
3106 }
3107 lua_setfield( L, -2, "timer_gateway"); // settings M
3108 }
3097 STACK_MID( L, 1); 3109 STACK_MID( L, 1);
3098 3110
3099 // prepare the metatable for threads 3111 // prepare the metatable for threads
3100 // contains keys: { __gc, __index, cached_error, cached_tostring, cancel, join, get_debug_threadname } 3112 // contains keys: { __gc, __index, cached_error, cached_tostring, cancel, join, get_debug_threadname }
3101 // 3113 //
3102 if( luaL_newmetatable( L, "Lane")) // settings M mt 3114 if( luaL_newmetatable( L, "Lane")) // settings M mt
3103 { 3115 {
3104 lua_pushcfunction( L, LG_thread_gc); // settings M mt LG_thread_gc 3116 lua_pushcfunction( L, LG_thread_gc); // settings M mt LG_thread_gc
3105 lua_setfield( L, -2, "__gc"); // settings M mt 3117 lua_setfield( L, -2, "__gc"); // settings M mt
3106 lua_pushcfunction( L, LG_thread_index); // settings M mt LG_thread_index 3118 lua_pushcfunction( L, LG_thread_index); // settings M mt LG_thread_index
3107 lua_setfield( L, -2, "__index"); // settings M mt 3119 lua_setfield( L, -2, "__index"); // settings M mt
3108 lua_getglobal( L, "error"); // settings M mt error 3120 lua_getglobal( L, "error"); // settings M mt error
3109 ASSERT_L( lua_isfunction( L, -1)); 3121 ASSERT_L( lua_isfunction( L, -1));
3110 lua_setfield( L, -2, "cached_error"); // settings M mt 3122 lua_setfield( L, -2, "cached_error"); // settings M mt
3111 lua_getglobal( L, "tostring"); // settings M mt tostring 3123 lua_getglobal( L, "tostring"); // settings M mt tostring
3112 ASSERT_L( lua_isfunction( L, -1)); 3124 ASSERT_L( lua_isfunction( L, -1));
3113 lua_setfield( L, -2, "cached_tostring"); // settings M mt 3125 lua_setfield( L, -2, "cached_tostring"); // settings M mt
3114 lua_pushcfunction( L, LG_thread_join); // settings M mt LG_thread_join 3126 lua_pushcfunction( L, LG_thread_join); // settings M mt LG_thread_join
3115 lua_setfield( L, -2, "join"); // settings M mt 3127 lua_setfield( L, -2, "join"); // settings M mt
3116 lua_pushcfunction( L, LG_get_debug_threadname); // settings M mt LG_get_debug_threadname 3128 lua_pushcfunction( L, LG_get_debug_threadname); // settings M mt LG_get_debug_threadname
3117 lua_setfield( L, -2, "get_debug_threadname"); // settings M mt 3129 lua_setfield( L, -2, "get_debug_threadname"); // settings M mt
3118 lua_pushcfunction( L, LG_thread_cancel); // settings M mt LG_thread_cancel 3130 lua_pushcfunction( L, LG_thread_cancel); // settings M mt LG_thread_cancel
3119 lua_setfield( L, -2, "cancel"); // settings M mt 3131 lua_setfield( L, -2, "cancel"); // settings M mt
3120 lua_pushliteral( L, "Lane"); // settings M mt "Lane" 3132 lua_pushliteral( L, "Lane"); // settings M mt "Lane"
3121 lua_setfield( L, -2, "__metatable"); // settings M mt 3133 lua_setfield( L, -2, "__metatable"); // settings M mt
3122 } 3134 }
3123 3135
3124 lua_pushcclosure( L, LG_thread_new, 1); // settings M LG_thread_new 3136 lua_pushcclosure( L, LG_thread_new, 1); // settings M LG_thread_new
3125 lua_setfield( L, -2, "thread_new"); // settings M 3137 lua_setfield( L, -2, "thread_new"); // settings M
3126 3138
3127 // we can't register 'lanes.require' normally because we want to create an upvalued closure 3139 // we can't register 'lanes.require' normally because we want to create an upvalued closure
3128 lua_getglobal( L, "require"); // settings M require 3140 lua_getglobal( L, "require"); // settings M require
3129 lua_pushcclosure( L, LG_require, 1); // settings M lanes.require 3141 lua_pushcclosure( L, LG_require, 1); // settings M lanes.require
3130 lua_setfield( L, -2, "require"); // settings M 3142 lua_setfield( L, -2, "require"); // settings M
3131 3143
3132 lua_pushstring(L, VERSION); // settings M VERSION 3144 lua_pushstring(L, VERSION); // settings M VERSION
3133 lua_setfield(L, -2, "version"); // settings M 3145 lua_setfield(L, -2, "version"); // settings M
3134 3146
3135 lua_pushinteger(L, THREAD_PRIO_MAX); // settings M THREAD_PRIO_MAX 3147 lua_pushinteger(L, THREAD_PRIO_MAX); // settings M THREAD_PRIO_MAX
3136 lua_setfield(L, -2, "max_prio"); // settings M 3148 lua_setfield(L, -2, "max_prio"); // settings M
3137 3149
3138 lua_pushlightuserdata( L, CANCEL_ERROR); // settings M CANCEL_ERROR 3150 lua_pushlightuserdata( L, CANCEL_ERROR); // settings M CANCEL_ERROR
3139 lua_setfield(L, -2, "cancel_error"); // settings M 3151 lua_setfield(L, -2, "cancel_error"); // settings M
3140 3152
3141 // register all native functions found in that module in the transferable functions database 3153 // register all native functions found in that module in the transferable functions database
3142 // we process it before _G because we don't want to find the module when scanning _G (this would generate longer names) 3154 // we process it before _G because we don't want to find the module when scanning _G (this would generate longer names)
@@ -3151,7 +3163,7 @@ LUAG_FUNC( configure)
3151 // set _R[CONFIG_REGKEY] = settings 3163 // set _R[CONFIG_REGKEY] = settings
3152 lua_pushvalue( L, -2); // settings M settings 3164 lua_pushvalue( L, -2); // settings M settings
3153 lua_setfield( L, LUA_REGISTRYINDEX, CONFIG_REGKEY); // settings M 3165 lua_setfield( L, LUA_REGISTRYINDEX, CONFIG_REGKEY); // settings M
3154 lua_pop( L, 1); // settings 3166 lua_pop( L, 1); // settings
3155 STACK_END( L, 0); 3167 STACK_END( L, 0);
3156 DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "%p: lanes.configure() END\n" INDENT_END, L)); 3168 DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "%p: lanes.configure() END\n" INDENT_END, L));
3157 DEBUGSPEW_CODE( -- debugspew_indent_depth); 3169 DEBUGSPEW_CODE( -- debugspew_indent_depth);
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]));
diff --git a/src/tools.h b/src/tools.h
index be358db..ebe407b 100644
--- a/src/tools.h
+++ b/src/tools.h
@@ -99,11 +99,15 @@ extern int debugspew_indent_depth;
99void luaG_dump( lua_State* L ); 99void luaG_dump( lua_State* L );
100 100
101lua_State* luaG_newstate( lua_State* _from, char const* libs); 101lua_State* luaG_newstate( lua_State* _from, char const* libs);
102void luaG_copy_one_time_settings( lua_State* L, lua_State* L2, char const* name_); 102void luaG_copy_one_time_settings( lua_State* L, lua_State* L2);
103 103
104typedef struct { 104// this is pointed to by full userdata proxies, and allocated with malloc() to survive any lua_State lifetime
105 volatile int refcount; 105typedef struct
106 void *deep; 106{
107 volatile int refcount;
108 void* deep;
109 // when stored in a keeper state, the full userdata doesn't have a metatable, so we need direct access to the idfunc
110 luaG_IdFunction idfunc;
107} DEEP_PRELUDE; 111} DEEP_PRELUDE;
108 112
109enum eLookupMode 113enum eLookupMode
@@ -113,7 +117,7 @@ enum eLookupMode
113 eLM_FromKeeper // send a function from a keeper state to a lane 117 eLM_FromKeeper // send a function from a keeper state to a lane
114}; 118};
115 119
116void luaG_push_proxy( lua_State *L, luaG_IdFunction idfunc, DEEP_PRELUDE *deep_userdata); 120char const* push_deep_proxy( lua_State* L, DEEP_PRELUDE* prelude, enum eLookupMode mode_);
117void luaG_inter_copy_package( lua_State* L, lua_State* L2, int _idx, enum eLookupMode mode_); 121void luaG_inter_copy_package( lua_State* L, lua_State* L2, int _idx, enum eLookupMode mode_);
118 122
119int luaG_inter_copy( lua_State *L, lua_State *L2, uint_t n, enum eLookupMode mode_); 123int luaG_inter_copy( lua_State *L, lua_State *L2, uint_t n, enum eLookupMode mode_);
@@ -130,6 +134,8 @@ extern MUTEX_T mtid_lock;
130void populate_func_lookup_table( lua_State* L, int _i, char const* _name); 134void populate_func_lookup_table( lua_State* L, int _i, char const* _name);
131void serialize_require( lua_State *L); 135void serialize_require( lua_State *L);
132int initialize_on_state_create( lua_State *L); 136int initialize_on_state_create( lua_State *L);
137void call_on_state_create( lua_State* L, lua_State* from_, enum eLookupMode mode_);
138
133extern MUTEX_T require_cs; 139extern MUTEX_T require_cs;
134 140
135// for verbose errors 141// for verbose errors