diff options
| author | Benoit Germain <bnt period germain arrobase gmail period com> | 2014-02-17 11:05:19 +0100 |
|---|---|---|
| committer | Benoit Germain <bnt period germain arrobase gmail period com> | 2014-02-17 11:05:19 +0100 |
| commit | 47eb3f94373a13ac9f204ca65dfde602f53bdc1a (patch) | |
| tree | 95d7d7a52ca92e6527d46d97207d3f079611a355 /src | |
| parent | 32ad991eb8c590472607d61e9a831d2ca9db05c5 (diff) | |
| download | lanes-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')
| -rw-r--r-- | src/deep.h | 12 | ||||
| -rw-r--r-- | src/keeper.c | 44 | ||||
| -rw-r--r-- | src/lanes.c | 286 | ||||
| -rw-r--r-- | src/tools.c | 791 | ||||
| -rw-r--r-- | src/tools.h | 16 |
5 files changed, 575 insertions, 574 deletions
| @@ -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 | ||
| 18 | typedef void (*luaG_IdFunction)( lua_State* L, char const* const which); | 18 | enum eDeepOp |
| 19 | { | ||
| 20 | eDO_new, | ||
| 21 | eDO_delete, | ||
| 22 | eDO_metatable, | ||
| 23 | eDO_module, | ||
| 24 | }; | ||
| 19 | 25 | ||
| 20 | extern LANES_API int luaG_deep_userdata( lua_State* L, luaG_IdFunction idfunc); | 26 | typedef void* (*luaG_IdFunction)( lua_State* L, enum eDeepOp op_); |
| 27 | |||
| 28 | extern LANES_API int luaG_newdeepuserdata( lua_State* L, luaG_IdFunction idfunc); | ||
| 21 | extern LANES_API void* luaG_todeep( lua_State* L, luaG_IdFunction idfunc, int index); | 29 | extern 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 | ||
| 55 | char const* VERSION = "3.8.5"; | 55 | char 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 | ||
| 425 | static void linda_id( lua_State*, char const * const which); | 425 | static void* linda_id( lua_State*, enum eDeepOp); |
| 426 | 426 | ||
| 427 | static inline struct s_Linda* lua_toLinda( lua_State* L, int idx_) | 427 | static 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 | ||
| 997 | static int linda_tostring( lua_State* L, int idx_, bool_t opt_) | 997 | static 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 | */ |
| 1087 | static void linda_id( lua_State* L, char const* const which) | 1087 | static 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) |
| 198 | void luaG_copy_one_time_settings( lua_State* L, lua_State* L2, char const* name_) | 198 | void 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 | ||
| 594 | void 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! |
| 605 | lua_State* luaG_newstate( lua_State* _from, char const* libs) | 636 | * |
| 637 | */ | ||
| 638 | lua_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 | ||
| 748 | static void push_registry_subtable_mode( lua_State *L, void *token, const char* mode ); | 761 | static void push_registry_subtable_mode( lua_State *L, void *token, const char* mode ); |
| 749 | static void push_registry_subtable( lua_State *L, void *token ); | 762 | static 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 | */ |
| 755 | void set_deep_lookup( lua_State *L ) { | 768 | static 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 | */ |
| 806 | void get_deep_lookup( lua_State *L ) { | 787 | static 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 | */ |
| 833 | static | 807 | static inline luaG_IdFunction get_idfunc( lua_State* L, int index, enum eLookupMode mode_) |
| 834 | luaG_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 | */ |
| 865 | static | 847 | static int deep_userdata_gc( lua_State* L) |
| 866 | int 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 |
| 909 | void luaG_push_proxy( lua_State *L, luaG_IdFunction idfunc, DEEP_PRELUDE *prelude ) | 886 | * reference count. |
| 887 | */ | ||
| 888 | char 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 | */ |
| 1089 | int luaG_deep_userdata( lua_State *L, luaG_IdFunction idfunc) | 1056 | int 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 | */ |
| 1131 | void *luaG_todeep( lua_State *L, luaG_IdFunction idfunc, int index ) | 1093 | void* 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 | */ |
| 1153 | static | 1118 | static luaG_IdFunction copydeep( lua_State* L, lua_State* L2, int index, enum eLookupMode mode_) |
| 1154 | luaG_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 | */ |
| 1193 | static | 1154 | static void push_registry_subtable_mode( lua_State* L, void* key_, const char* mode_) |
| 1194 | void 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 | */ |
| 1235 | static | 1190 | static inline void push_registry_subtable( lua_State* L, void* key_) |
| 1236 | void 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 | |||
| 1864 | static 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_) | 1819 | static 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; | |||
| 99 | void luaG_dump( lua_State* L ); | 99 | void luaG_dump( lua_State* L ); |
| 100 | 100 | ||
| 101 | lua_State* luaG_newstate( lua_State* _from, char const* libs); | 101 | lua_State* luaG_newstate( lua_State* _from, char const* libs); |
| 102 | void luaG_copy_one_time_settings( lua_State* L, lua_State* L2, char const* name_); | 102 | void luaG_copy_one_time_settings( lua_State* L, lua_State* L2); |
| 103 | 103 | ||
| 104 | typedef struct { | 104 | // this is pointed to by full userdata proxies, and allocated with malloc() to survive any lua_State lifetime |
| 105 | volatile int refcount; | 105 | typedef 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 | ||
| 109 | enum eLookupMode | 113 | enum 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 | ||
| 116 | void luaG_push_proxy( lua_State *L, luaG_IdFunction idfunc, DEEP_PRELUDE *deep_userdata); | 120 | char const* push_deep_proxy( lua_State* L, DEEP_PRELUDE* prelude, enum eLookupMode mode_); |
| 117 | void luaG_inter_copy_package( lua_State* L, lua_State* L2, int _idx, enum eLookupMode mode_); | 121 | void luaG_inter_copy_package( lua_State* L, lua_State* L2, int _idx, enum eLookupMode mode_); |
| 118 | 122 | ||
| 119 | int luaG_inter_copy( lua_State *L, lua_State *L2, uint_t n, enum eLookupMode mode_); | 123 | int luaG_inter_copy( lua_State *L, lua_State *L2, uint_t n, enum eLookupMode mode_); |
| @@ -130,6 +134,8 @@ extern MUTEX_T mtid_lock; | |||
| 130 | void populate_func_lookup_table( lua_State* L, int _i, char const* _name); | 134 | void populate_func_lookup_table( lua_State* L, int _i, char const* _name); |
| 131 | void serialize_require( lua_State *L); | 135 | void serialize_require( lua_State *L); |
| 132 | int initialize_on_state_create( lua_State *L); | 136 | int initialize_on_state_create( lua_State *L); |
| 137 | void call_on_state_create( lua_State* L, lua_State* from_, enum eLookupMode mode_); | ||
| 138 | |||
| 133 | extern MUTEX_T require_cs; | 139 | extern MUTEX_T require_cs; |
| 134 | 140 | ||
| 135 | // for verbose errors | 141 | // for verbose errors |
