aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBenoit Germain <bnt period germain arrobase gmail period com>2014-02-17 11:05:19 +0100
committerBenoit Germain <bnt period germain arrobase gmail period com>2014-02-17 11:05:19 +0100
commit47eb3f94373a13ac9f204ca65dfde602f53bdc1a (patch)
tree95d7d7a52ca92e6527d46d97207d3f079611a355
parent32ad991eb8c590472607d61e9a831d2ca9db05c5 (diff)
downloadlanes-47eb3f94373a13ac9f204ca65dfde602f53bdc1a.tar.gz
lanes-47eb3f94373a13ac9f204ca65dfde602f53bdc1a.tar.bz2
lanes-47eb3f94373a13ac9f204ca65dfde602f53bdc1a.zip
Deep userdata support improvements
* bumped version to 3.9.0 * keepers now require "package", receive package.path & package.cpath, and call on_state_create() if it is a C function * changed the deep public API (improved deep idfunc signature, renamed luaG_deep_userdata to luaG_newdeepuserdata) * if an error occurs while copying a deep userdata, don't raise inside the keeper state * fixed situations where raised errors could lead to memory leaks (deep gc)
-rw-r--r--CHANGES7
-rw-r--r--docs/index.html32
-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
7 files changed, 604 insertions, 584 deletions
diff --git a/CHANGES b/CHANGES
index 329c53f..dd0917f 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,5 +1,12 @@
1CHANGES: 1CHANGES:
2 2
3CHANGE 99: BGe 17-Feb-14
4 * version 3.9.0
5 * keepers now require "package", receive package.path & package.cpath, and call on_state_create() if it is a C function
6 * changed the deep public API (improved deep idfunc signature, renamed luaG_deep_userdata to luaG_newdeepuserdata)
7 * if an error occurs while copying a deep userdata, don't raise inside the keeper state
8 * fixed situations where raised errors could lead to memory leaks (deep gc)
9
3CHANGE 98: BGe 13-Feb-14 10CHANGE 98: BGe 13-Feb-14
4 * version 3.8.5 11 * version 3.8.5
5 * linda:limit() returns lanes.cancel_error on a limited linda 12 * linda:limit() returns lanes.cancel_error on a limited linda
diff --git a/docs/index.html b/docs/index.html
index 2468ad8..051f9d0 100644
--- a/docs/index.html
+++ b/docs/index.html
@@ -70,7 +70,7 @@
70 </p> 70 </p>
71 71
72 <p> 72 <p>
73 This document was revised on 13-Feb-14, and applies to version <tt>3.8.5</tt>. 73 This document was revised on 17-Feb-14, and applies to version <tt>3.9.0</tt>.
74 </p> 74 </p>
75 </font> 75 </font>
76 </center> 76 </center>
@@ -355,7 +355,9 @@
355 function/<tt>nil</tt> 355 function/<tt>nil</tt>
356 </td> 356 </td>
357 <td> 357 <td>
358 If provided, will be called in every created Lua state (keepers and lanes) right after initializing the base libraries. 358 If provided, will be called in every created Lua state right after initializing the base libraries.
359 <br/>
360 Keeper states will call it as well, but only if it is a C function (keeper states are not able to execute any user Lua code).
359 <br/> 361 <br/>
360 Typical usage is twofold: 362 Typical usage is twofold:
361 <ul> 363 <ul>
@@ -1493,18 +1495,18 @@ events to a common Linda, but... :).</font>
1493<ol> 1495<ol>
1494 <li> 1496 <li>
1495 Provide an <i>identity function</i> for your userdata, in C. This function is used for creation and deletion of your deep userdata (the shared resource), and for making metatables for the state-specific proxies for accessing it. The prototype is 1497 Provide an <i>identity function</i> for your userdata, in C. This function is used for creation and deletion of your deep userdata (the shared resource), and for making metatables for the state-specific proxies for accessing it. The prototype is
1496 <table border="1" bgcolor="#E0E0FF" cellpadding="10" style="width:50%"><tr><td><pre> void idfunc( lua_State *L, char const * const which);</pre></td></tr></table> 1498 <table border="1" bgcolor="#E0E0FF" cellpadding="10" style="width:50%"><tr><td><pre> void* idfunc( lua_State* L, enum eDeepOp op_);</pre></td></tr></table>
1497 <tt>which</tt> can be one of: 1499 <tt>op_</tt> can be one of:
1498 <ul> 1500 <ul>
1499 <li><tt>"new"</tt>: requests the creation of a new object, whose pointer is pushed on the stack as a light userdata.</li> 1501 <li><tt>eDO_new</tt>: requests the creation of a new object, whose pointer is returned.</li>
1500 <li><tt>"delete"</tt>: receives this same pointer on the stack, and should cleanup the object.</li> 1502 <li><tt>eDO_delete</tt>: receives this same pointer on the stack as a light userdata, and should cleanup the object.</li>
1501 <li><tt>"metatable"</tt>: should build a metatable for the object. Don't cache the metatable yourself, Lanes takes care of it ("metatable" should only be invoked once).</li> 1503 <li><tt>eDO_metatable</tt>: should build a metatable for the object. Don't cache the metatable yourself, Lanes takes care of it (<tt>eDO_metatable</tt> should only be invoked once per state).</li>
1502 <li><tt>"module"</tt>: is the name of the module that exports the idfunc, to be pushed on the stack as a string. It is necessary so that Lanes can require it in any Lane and keeper state that receives a userdata. This is to prevent crashes in situations where the module could be unloaded while the idfunc pointer is still held.</li> 1504 <li><tt>eDO_module</tt>: requests the name of the module that exports the idfunc, to be returned. It is necessary so that Lanes can require it in any lane state that receives a userdata. This is to prevent crashes in situations where the module could be unloaded while the idfunc pointer is still held.</li>
1503 </ul> 1505 </ul>
1504 Take a look at <tt>linda_id</tt> in <tt>lanes.c</tt>. 1506 Take a look at <tt>linda_id</tt> in <tt>lanes.c</tt>.
1505 </li> 1507 </li>
1506 <li>Include <tt>"deep.h"</tt> and link against Lanes. 1508 <li>Include <tt>"deep.h"</tt> and link against Lanes.
1507 <li>Instanciate your userdata using <tt>luaG_deep_userdata()</tt>, instead of the regular <tt>lua_newuserdata()</tt>. Given an <tt>idfunc</tt>, it sets up the support structures and returns a state-specific proxy userdata for accessing your data. This proxy can also be copied over to other lanes.</li> 1509 <li>Instanciate your userdata using <tt>luaG_newdeepuserdata()</tt>, instead of the regular <tt>lua_newuserdata()</tt>. Given an <tt>idfunc</tt>, it sets up the support structures and returns a state-specific proxy userdata for accessing your data. This proxy can also be copied over to other lanes.</li>
1508 <li>Accessing the deep userdata from your C code, use <tt>luaG_todeep()</tt> instead of the regular <tt>lua_touserdata()</tt>.</li> 1510 <li>Accessing the deep userdata from your C code, use <tt>luaG_todeep()</tt> instead of the regular <tt>lua_touserdata()</tt>.</li>
1509</ol> 1511</ol>
1510 1512
@@ -1513,7 +1515,17 @@ events to a common Linda, but... :).</font>
1513</p> 1515</p>
1514 1516
1515<p> 1517<p>
1516 <b>NOTE</b>: The lifespan of deep userdata may exceed that of the Lua state that created it. The allocation of the data storage should not be tied to the Lua state used. In other words, use <tt>malloc</tt>/<tt>free</tt> or similar memory handling mechanism. 1518 Deep userdata in transit inside keeper states (sent in a linda but not yet consumed) don't call <tt>idfunc(eDO_delete)</tt> and aren't considered by reference counting. The rationale is the following:
1519 <br/>
1520 If some non-keeper state holds a deep userdata for some deep object, then even if the keeper collects its own deep userdata, it shouldn't be cleaned up since the refcount is not 0.
1521 <br/>
1522 OTOH, if a keeper state holds the last deep userdata for some deep object, then no lane can do actual work with it. But as it happens, deep userdata are only copied to and from keeper states. Most notably, the object's <tt>idfunc()</tt> is never called from a keeper state.
1523 <br/>
1524 Therefore, Lanes can just call <tt>idfunc(eDO_delete)</tt> when the last non-keeper-held deep userdata is collected, as long as it doens't do the same in a keeper state after that, since any remaining deep userdata in keeper states now hold stale pointers.
1525</p>
1526
1527<p>
1528 <b>NOTE</b>: The lifespan of deep userdata may exceed that of the Lua state that created it. The allocation of the data storage should not be tied to the Lua state used. In other words, use <tt>malloc()</tt>/<tt>free()</tt> or similar memory handling mechanism.
1517</p> 1529</p>
1518 1530
1519 1531
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