aboutsummaryrefslogtreecommitdiff
path: root/src/tools.c
diff options
context:
space:
mode:
authorBenoit Germain <bnt.germain@gmail.com>2013-01-30 20:28:47 +0100
committerBenoit Germain <bnt.germain@gmail.com>2013-01-30 20:28:47 +0100
commitb657f38535c3c27a848353ef853d6667d6acc917 (patch)
tree8679a62c0b6343eae4781cff10a0ea60460d9cb4 /src/tools.c
parent3377b95704e611a288791fee6a7bc59c5ecebf2d (diff)
downloadlanes-b657f38535c3c27a848353ef853d6667d6acc917.tar.gz
lanes-b657f38535c3c27a848353ef853d6667d6acc917.tar.bz2
lanes-b657f38535c3c27a848353ef853d6667d6acc917.zip
version 3.5.0
* new: API lanes.require(), use it instead of regular require() for modules that export C functions you need to send over. * new: lanes no longer require 'lanes.core' by default in every created state. Use {required={"lanes.core"}} if you need to transfer lanes functions. * internal: because of the above, reworked the timer implementation to remove upvalue-dependency on lanes.core * new: API lanes.timer_lane, to be able to operate on timer lane if need be * improved: if a module is a full userdata, scan its metatable for function database population * improved: on_state_create can be a Lua function * changed: on_state_create is called after the base libraries are loaded * package[loaders|searchers] is no longer transfered as function naming depends on slot order * internal: changed separator from '.' to '/' in lookup databases to be able to distinguish search levels and dot coming from module names * added some mode debug spew * updated tests to reflect the above changes
Diffstat (limited to 'src/tools.c')
-rw-r--r--src/tools.c92
1 files changed, 59 insertions, 33 deletions
diff --git a/src/tools.c b/src/tools.c
index 552e61e..9961c1a 100644
--- a/src/tools.c
+++ b/src/tools.c
@@ -224,7 +224,7 @@ static char const* luaG_pushFQN(lua_State *L, int t, int last)
224 { 224 {
225 lua_rawgeti( L, t, i); 225 lua_rawgeti( L, t, i);
226 luaL_addvalue( &b); 226 luaL_addvalue( &b);
227 luaL_addlstring(&b, ".", 1); 227 luaL_addlstring(&b, "/", 1);
228 } 228 }
229 if( i == last) // add last value (if interval was not empty) 229 if( i == last) // add last value (if interval was not empty)
230 { 230 {
@@ -250,9 +250,16 @@ static void populate_func_lookup_table_recur( lua_State* L, int _ctx_base, int _
250 int const breadth_first_cache = lua_gettop( L) + 1; 250 int const breadth_first_cache = lua_gettop( L) + 1;
251 251
252 STACK_GROW( L, 6); 252 STACK_GROW( L, 6);
253 // slot _i contains a table where we search for functions 253 // slot _i contains a table where we search for functions (or a full userdata with a metatable)
254 STACK_CHECK( L); // ... {_i} 254 STACK_CHECK( L); // ... {_i}
255 255
256 // if object is a userdata, replace it by its metatable
257 if( lua_type( L, _i) == LUA_TUSERDATA)
258 {
259 lua_getmetatable( L, _i); // ... {_i} mt
260 lua_replace( L, _i); // ... {_i}
261 }
262
256 // if table is already visited, we are done 263 // if table is already visited, we are done
257 lua_pushvalue( L, _i); // ... {_i} {} 264 lua_pushvalue( L, _i); // ... {_i} {}
258 lua_rawget( L, cache); // ... {_i} nil|n 265 lua_rawget( L, cache); // ... {_i} nil|n
@@ -437,7 +444,7 @@ void populate_func_lookup_table( lua_State* L, int _i, char const* _name)
437* 444*
438*/ 445*/
439 446
440lua_State* luaG_newstate( lua_State* _from, char const* libs, lua_CFunction _on_state_create) 447lua_State* luaG_newstate( lua_State* _from, int const _on_state_create, char const* libs)
441{ 448{
442 // reuse alloc function from the originating state 449 // reuse alloc function from the originating state
443 void* allocUD; 450 void* allocUD;
@@ -450,7 +457,7 @@ lua_State* luaG_newstate( lua_State* _from, char const* libs, lua_CFunction _on_
450 } 457 }
451 458
452 // neither libs (not even 'base') nor special init func: we are done 459 // neither libs (not even 'base') nor special init func: we are done
453 if( !libs && !_on_state_create) 460 if( libs == NULL && _on_state_create <= 0)
454 { 461 {
455 return L; 462 return L;
456 } 463 }
@@ -460,13 +467,6 @@ lua_State* luaG_newstate( lua_State* _from, char const* libs, lua_CFunction _on_
460 467
461 STACK_GROW( L, 2); 468 STACK_GROW( L, 2);
462 STACK_CHECK( L); 469 STACK_CHECK( L);
463 if( _on_state_create)
464 {
465 DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "calling on_state_create()\n" INDENT_END));
466 lua_pushcfunction( L, _on_state_create);
467 lua_call( L, 0, 0);
468 }
469
470 // 'lua.c' stops GC during initialization so perhaps its a good idea. :) 470 // 'lua.c' stops GC during initialization so perhaps its a good idea. :)
471 // but do it after _on_state_create in case it does a lot of stuff... 471 // but do it after _on_state_create in case it does a lot of stuff...
472 lua_gc( L, LUA_GCSTOP, 0); 472 lua_gc( L, LUA_GCSTOP, 0);
@@ -520,7 +520,29 @@ lua_State* luaG_newstate( lua_State* _from, char const* libs, lua_CFunction _on_
520 lua_gc( L, LUA_GCRESTART, 0); 520 lua_gc( L, LUA_GCRESTART, 0);
521 521
522 STACK_CHECK( L); 522 STACK_CHECK( L);
523 // after opening base, register the functions it exported in our name<->function database 523 // call this after the base libraries are loaded!
524 if( _on_state_create > 0)
525 {
526 DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "calling on_state_create()\n" INDENT_END));
527 if( lua_iscfunction( _from, _on_state_create))
528 {
529 // C function: recreate a closure in the new state, bypassing the lookup scheme
530 lua_CFunction osc = lua_tocfunction( _from, _on_state_create);
531 lua_pushcfunction( L, osc);
532 }
533 else
534 {
535 STACK_CHECK( _from);
536 // Lua function: transfer as usual (should work as long as it only uses base libraries)
537 lua_pushvalue( _from, _on_state_create);
538 luaG_inter_move( _from, L, 1);
539 STACK_END( _from, 0);
540 }
541 lua_call( L, 0, 0);
542 STACK_MID( L, 0);
543 }
544
545 // after all this, register everything we find in our name<->function database
524 lua_pushglobaltable( L); // Lua 5.2 no longer has LUA_GLOBALSINDEX: we must push globals table on the stack 546 lua_pushglobaltable( L); // Lua 5.2 no longer has LUA_GLOBALSINDEX: we must push globals table on the stack
525 populate_func_lookup_table( L, -1, NULL); 547 populate_func_lookup_table( L, -1, NULL);
526 lua_pop( L, 1); 548 lua_pop( L, 1);
@@ -1180,9 +1202,9 @@ static void inter_copy_func( lua_State* L2, uint_t L2_cache_i, lua_State* L, uin
1180 1202
1181static void push_cached_func( lua_State* L2, uint_t L2_cache_i, lua_State* L, uint_t i) 1203static void push_cached_func( lua_State* L2, uint_t L2_cache_i, lua_State* L, uint_t i)
1182{ 1204{
1183 void * const aspointer = (void*)lua_topointer( L, i); 1205 void* const aspointer = (void*)lua_topointer( L, i);
1184 // TBD: Merge this and same code for tables 1206 // TBD: Merge this and same code for tables
1185 ASSERT_L( L2_cache_i != 0 ); 1207 ASSERT_L( L2_cache_i != 0);
1186 1208
1187 STACK_GROW( L2, 2); 1209 STACK_GROW( L2, 2);
1188 1210
@@ -1199,8 +1221,8 @@ static void push_cached_func( lua_State* L2, uint_t L2_cache_i, lua_State* L, ui
1199 1221
1200 //fprintf( stderr, "<< ID: %s >>\n", lua_tostring(L2,-1) ); 1222 //fprintf( stderr, "<< ID: %s >>\n", lua_tostring(L2,-1) );
1201 1223
1202 lua_pushvalue( L2, -1 ); // ... {cache} ... p p 1224 lua_pushvalue( L2, -1); // ... {cache} ... p p
1203 lua_rawget( L2, L2_cache_i ); // ... {cache} ... p function|nil|true 1225 lua_rawget( L2, L2_cache_i); // ... {cache} ... p function|nil|true
1204 1226
1205 if( lua_isnil(L2,-1)) // function is unknown 1227 if( lua_isnil(L2,-1)) // function is unknown
1206 { 1228 {
@@ -1209,7 +1231,7 @@ static void push_cached_func( lua_State* L2, uint_t L2_cache_i, lua_State* L, ui
1209 // Set to 'true' for the duration of creation; need to find self-references 1231 // Set to 'true' for the duration of creation; need to find self-references
1210 // via upvalues 1232 // via upvalues
1211 // 1233 //
1212 // pushes a copy of the func, a stores a reference in the cache 1234 // pushes a copy of the func, stores a reference in the cache
1213 inter_copy_func( L2, L2_cache_i, L, i); // ... {cache} ... function 1235 inter_copy_func( L2, L2_cache_i, L, i); // ... {cache} ... function
1214 } 1236 }
1215 else // found function in the cache 1237 else // found function in the cache
@@ -1426,7 +1448,9 @@ static void inter_copy_func( lua_State* L2, uint_t L2_cache_i, lua_State* L, uin
1426 // if already on top of the stack, no need to push again 1448 // if already on top of the stack, no need to push again
1427 int needToPush = (i != (uint_t)lua_gettop( L)); 1449 int needToPush = (i != (uint_t)lua_gettop( L));
1428 if( needToPush) 1450 if( needToPush)
1451 {
1429 lua_pushvalue( L, i); // ... f 1452 lua_pushvalue( L, i); // ... f
1453 }
1430 1454
1431 luaL_buffinit( L, &b); 1455 luaL_buffinit( L, &b);
1432 // 1456 //
@@ -1568,11 +1592,11 @@ static void inter_copy_func( lua_State* L2, uint_t L2_cache_i, lua_State* L, uin
1568* 1592*
1569* Returns TRUE if value was pushed, FALSE if its type is non-supported. 1593* Returns TRUE if value was pushed, FALSE if its type is non-supported.
1570*/ 1594*/
1571static bool_t inter_copy_one_( lua_State *L2, uint_t L2_cache_i, lua_State *L, uint_t i, enum e_vt vt ) 1595static bool_t inter_copy_one_( lua_State* L2, uint_t L2_cache_i, lua_State* L, uint_t i, enum e_vt vt)
1572{ 1596{
1573 bool_t ret= TRUE; 1597 bool_t ret = TRUE;
1574 1598
1575 STACK_GROW( L2, 1 ); 1599 STACK_GROW( L2, 1);
1576 1600
1577 STACK_CHECK( L2); 1601 STACK_CHECK( L2);
1578 1602
@@ -1626,6 +1650,7 @@ static bool_t inter_copy_one_( lua_State *L2, uint_t L2_cache_i, lua_State *L, u
1626 } 1650 }
1627 /* Allow only deep userdata entities to be copied across 1651 /* Allow only deep userdata entities to be copied across
1628 */ 1652 */
1653 DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "USERDATA\n" INDENT_END));
1629 if( !luaG_copydeep( L, L2, i)) 1654 if( !luaG_copydeep( L, L2, i))
1630 { 1655 {
1631 // Cannot copy it full; copy as light userdata 1656 // Cannot copy it full; copy as light userdata
@@ -1669,7 +1694,6 @@ static bool_t inter_copy_one_( lua_State *L2, uint_t L2_cache_i, lua_State *L, u
1669#endif 1694#endif
1670 STACK_CHECK( L2); 1695 STACK_CHECK( L2);
1671 push_cached_func( L2, L2_cache_i, L, i); 1696 push_cached_func( L2, L2_cache_i, L, i);
1672 ASSERT_L( lua_isfunction( L2, -1));
1673 STACK_END( L2, 1); 1697 STACK_END( L2, 1);
1674 } 1698 }
1675 break; 1699 break;
@@ -1827,7 +1851,7 @@ static bool_t inter_copy_one_( lua_State *L2, uint_t L2_cache_i, lua_State *L, u
1827* 1851*
1828* Note: Parameters are in this order ('L' = from first) to be same as 'lua_xmove'. 1852* Note: Parameters are in this order ('L' = from first) to be same as 'lua_xmove'.
1829*/ 1853*/
1830int luaG_inter_copy( lua_State* L, lua_State *L2, uint_t n) 1854int luaG_inter_copy( lua_State* L, lua_State* L2, uint_t n)
1831{ 1855{
1832 uint_t top_L = lua_gettop( L); 1856 uint_t top_L = lua_gettop( L);
1833 uint_t top_L2 = lua_gettop( L2); 1857 uint_t top_L2 = lua_gettop( L2);
@@ -1903,7 +1927,9 @@ void luaG_inter_copy_package( lua_State* L, lua_State* L2, int _idx)
1903 { 1927 {
1904 int i; 1928 int i;
1905 // package.loaders is renamed package.searchers in Lua 5.2 1929 // package.loaders is renamed package.searchers in Lua 5.2
1906 char const* entries[] = { "path", "cpath", "preload", (LUA_VERSION_NUM == 501) ? "loaders" : "searchers", NULL}; 1930 // but don't copy it anyway, as the function names change depending on the slot index!
1931 // users should provide an on_state_create function to setup custom loaders instead
1932 char const* entries[] = { "path", "cpath", "preload"/*, (LUA_VERSION_NUM == 501) ? "loaders" : "searchers"*/, NULL};
1907 for( i = 0; entries[i]; ++ i) 1933 for( i = 0; entries[i]; ++ i)
1908 { 1934 {
1909 DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "%s\n" INDENT_END, entries[i])); 1935 DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "%s\n" INDENT_END, entries[i]));
@@ -1944,7 +1970,7 @@ MUTEX_T require_cs;
1944// 1970//
1945// Upvalues: [1]: original 'require' function 1971// Upvalues: [1]: original 'require' function
1946// 1972//
1947static int new_require( lua_State *L) 1973int luaG_new_require( lua_State* L)
1948{ 1974{
1949 int rc, i; 1975 int rc, i;
1950 int args = lua_gettop( L); 1976 int args = lua_gettop( L);
@@ -1955,24 +1981,24 @@ static int new_require( lua_State *L)
1955 1981
1956 lua_pushvalue( L, lua_upvalueindex(1)); 1982 lua_pushvalue( L, lua_upvalueindex(1));
1957 for( i = 1; i <= args; ++ i) 1983 for( i = 1; i <= args; ++ i)
1984 {
1958 lua_pushvalue( L, i); 1985 lua_pushvalue( L, i);
1986 }
1959 1987
1960 // Using 'lua_pcall()' to catch errors; otherwise a failing 'require' would 1988 // Using 'lua_pcall()' to catch errors; otherwise a failing 'require' would
1961 // leave us locked, blocking any future 'require' calls from other lanes. 1989 // leave us locked, blocking any future 'require' calls from other lanes.
1962 // 1990 //
1963 MUTEX_LOCK( &require_cs); 1991 MUTEX_LOCK( &require_cs);
1964 { 1992 rc = lua_pcall( L, args, 1 /*retvals*/, 0 /*errfunc*/ );
1965 rc = lua_pcall( L, args, 1 /*retvals*/, 0 /*errfunc*/ );
1966 //
1967 // LUA_ERRRUN / LUA_ERRMEM
1968 }
1969 MUTEX_UNLOCK( &require_cs); 1993 MUTEX_UNLOCK( &require_cs);
1970 1994
1971 // the required module (or an error message) is left on the stack as returned value by original require function 1995 // the required module (or an error message) is left on the stack as returned value by original require function
1972 STACK_END( L, 1); 1996 STACK_END( L, 1);
1973 1997
1974 if (rc) 1998 if( rc != LUA_OK) // LUA_ERRRUN / LUA_ERRMEM ?
1975 lua_error(L); // error message already at [-1] 1999 {
2000 return lua_error( L); // error message already at [-1]
2001 }
1976 2002
1977 return 1; 2003 return 1;
1978} 2004}
@@ -1980,7 +2006,7 @@ static int new_require( lua_State *L)
1980/* 2006/*
1981* Serialize calls to 'require', if it exists 2007* Serialize calls to 'require', if it exists
1982*/ 2008*/
1983void serialize_require( lua_State *L ) 2009void serialize_require( lua_State* L)
1984{ 2010{
1985 STACK_GROW( L, 1); 2011 STACK_GROW( L, 1);
1986 STACK_CHECK( L); 2012 STACK_CHECK( L);
@@ -1991,7 +2017,7 @@ void serialize_require( lua_State *L )
1991 if( lua_isfunction( L, -1)) 2017 if( lua_isfunction( L, -1))
1992 { 2018 {
1993 // [-1]: original 'require' function 2019 // [-1]: original 'require' function
1994 lua_pushcclosure( L, new_require, 1 /*upvalues*/); 2020 lua_pushcclosure( L, luaG_new_require, 1 /*upvalues*/);
1995 lua_setglobal( L, "require"); 2021 lua_setglobal( L, "require");
1996 } 2022 }
1997 else 2023 else