aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/keeper.c15
-rw-r--r--src/keeper.h2
-rw-r--r--src/lanes.c134
-rw-r--r--src/lanes.lua323
-rw-r--r--src/tools.c92
-rw-r--r--src/tools.h5
6 files changed, 306 insertions, 265 deletions
diff --git a/src/keeper.c b/src/keeper.c
index 7485110..3511b56 100644
--- a/src/keeper.c
+++ b/src/keeper.c
@@ -557,7 +557,7 @@ void close_keepers( void)
557* unclosed, because it does not really matter. In production code, this 557* unclosed, because it does not really matter. In production code, this
558* function never fails. 558* function never fails.
559*/ 559*/
560char const* init_keepers( lua_State* L, int const _nbKeepers, lua_CFunction _on_state_create) 560char const* init_keepers( lua_State* L, int _on_state_create, int const _nbKeepers)
561{ 561{
562 int i; 562 int i;
563 assert( _nbKeepers >= 1); 563 assert( _nbKeepers >= 1);
@@ -572,7 +572,7 @@ char const* init_keepers( lua_State* L, int const _nbKeepers, lua_CFunction _on_
572 // 572 //
573 // 'io' for debugging messages, 'package' because we need to require modules exporting idfuncs 573 // 'io' for debugging messages, 'package' because we need to require modules exporting idfuncs
574 // the others because they export functions that we may store in a keeper for transfer between lanes 574 // the others because they export functions that we may store in a keeper for transfer between lanes
575 K = luaG_newstate( L, "*", _on_state_create); 575 K = luaG_newstate( L, _on_state_create, "*");
576 576
577 STACK_CHECK( K); 577 STACK_CHECK( K);
578 578
@@ -635,8 +635,8 @@ void populate_keepers( lua_State* L)
635 char const* name = luaL_checklstring( L, -1, &name_len); 635 char const* name = luaL_checklstring( L, -1, &name_len);
636 int i; 636 int i;
637 637
638 STACK_CHECK( L); 638 DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "populate_keepers %s BEGIN\n" INDENT_END, name));
639 STACK_GROW( L, 3); 639 DEBUGSPEW_CODE( ++ debugspew_indent_depth);
640 640
641 for( i = 0; i < GNbKeepers; ++ i) 641 for( i = 0; i < GNbKeepers; ++ i)
642 { 642 {
@@ -647,16 +647,19 @@ void populate_keepers( lua_State* L)
647 STACK_GROW( K, 2); 647 STACK_GROW( K, 2);
648 lua_getglobal( K, "require"); 648 lua_getglobal( K, "require");
649 lua_pushlstring( K, name, name_len); 649 lua_pushlstring( K, name, name_len);
650 res = lua_pcall( K, 1, 0, 0); 650 res = lua_pcall( K, 1, 1, 0);
651 if( res != LUA_OK) 651 if( res != LUA_OK)
652 { 652 {
653 char const* err = luaL_checkstring( K, -1); 653 char const* err = luaL_checkstring( K, -1);
654 luaL_error( L, "error requiring '%s' in keeper state: %s", name, err); 654 luaL_error( L, "error requiring '%s' in keeper state: %s", name, err);
655 } 655 }
656 // after requiring the module, register the functions it exported in our name<->function database
657 populate_func_lookup_table( K, -1, name);
658 lua_pop( K, 1);
656 STACK_END( K, 0); 659 STACK_END( K, 0);
657 MUTEX_UNLOCK( &GKeepers[i].lock_); 660 MUTEX_UNLOCK( &GKeepers[i].lock_);
658 } 661 }
659 STACK_END( L, 0); 662 DEBUGSPEW_CODE( -- debugspew_indent_depth);
660} 663}
661 664
662struct s_Keeper* keeper_acquire( void const* ptr) 665struct s_Keeper* keeper_acquire( void const* ptr)
diff --git a/src/keeper.h b/src/keeper.h
index 15a5a41..29a19a9 100644
--- a/src/keeper.h
+++ b/src/keeper.h
@@ -13,7 +13,7 @@ struct s_Keeper
13// problem: maybe on some platforms (linux) atexit() is called after DLL/so are unloaded... 13// problem: maybe on some platforms (linux) atexit() is called after DLL/so are unloaded...
14#define HAVE_KEEPER_ATEXIT_DESINIT 0 14#define HAVE_KEEPER_ATEXIT_DESINIT 0
15 15
16char const* init_keepers( lua_State* L, int const _nbKeepers, lua_CFunction _on_state_create); 16char const* init_keepers( lua_State* L, int _on_state_create, int const _nbKeepers);
17#if !HAVE_KEEPER_ATEXIT_DESINIT 17#if !HAVE_KEEPER_ATEXIT_DESINIT
18void close_keepers( void); 18void close_keepers( void);
19#endif // HAVE_KEEPER_ATEXIT_DESINIT 19#endif // HAVE_KEEPER_ATEXIT_DESINIT
diff --git a/src/lanes.c b/src/lanes.c
index 80f5b15..2b3d8ac 100644
--- a/src/lanes.c
+++ b/src/lanes.c
@@ -52,7 +52,7 @@
52 * ... 52 * ...
53 */ 53 */
54 54
55char const* VERSION = "3.4.4"; 55char const* VERSION = "3.5.0";
56 56
57/* 57/*
58=============================================================================== 58===============================================================================
@@ -1529,7 +1529,6 @@ LUAG_FUNC( set_singlethreaded)
1529# define STACK_TRACE_KEY ((void*)lane_error) // used as registry key 1529# define STACK_TRACE_KEY ((void*)lane_error) // used as registry key
1530# define EXTENDED_STACK_TRACE_KEY ((void*)LG_set_error_reporting) // used as registry key 1530# define EXTENDED_STACK_TRACE_KEY ((void*)LG_set_error_reporting) // used as registry key
1531 1531
1532#ifdef ERROR_FULL_STACK
1533LUAG_FUNC( set_error_reporting) 1532LUAG_FUNC( set_error_reporting)
1534{ 1533{
1535 bool_t equal; 1534 bool_t equal;
@@ -1554,7 +1553,6 @@ done:
1554 lua_rawset( L, LUA_REGISTRYINDEX); 1553 lua_rawset( L, LUA_REGISTRYINDEX);
1555 return 0; 1554 return 0;
1556} 1555}
1557#endif // ERROR_FULL_STACK
1558 1556
1559static int lane_error( lua_State* L) 1557static int lane_error( lua_State* L)
1560{ 1558{
@@ -1735,8 +1733,8 @@ static THREAD_RETURN_T THREAD_CALLCONV lane_main( void *vs)
1735 // [3..top]: parameters 1733 // [3..top]: parameters
1736 // 1734 //
1737 rc= lua_pcall( L, lua_gettop(L)-2, LUA_MULTRET, 1 /*error handler*/ ); 1735 rc= lua_pcall( L, lua_gettop(L)-2, LUA_MULTRET, 1 /*error handler*/ );
1738 // 0: no error 1736 // 0: no error, body return values are on the stack
1739 // LUA_ERRRUN: a runtime error (error pushed on stack) 1737 // LUA_ERRRUN: cancellation or a runtime error (error pushed on stack)
1740 // LUA_ERRMEM: memory allocation error 1738 // LUA_ERRMEM: memory allocation error
1741 // LUA_ERRERR: error while running the error handler (if any) 1739 // LUA_ERRERR: error while running the error handler (if any)
1742 1740
@@ -1744,14 +1742,12 @@ static THREAD_RETURN_T THREAD_CALLCONV lane_main( void *vs)
1744 1742
1745 lua_remove(L,1); // remove error handler 1743 lua_remove(L,1); // remove error handler
1746 1744
1747 // Lua 5.1 error handler is limited to one return value; taking stack trace 1745 // Lua 5.1 error handler is limited to one return value; taking stack trace via registry
1748 // via registry 1746 if( rc != LUA_OK)
1749 //
1750 if( rc != 0)
1751 { 1747 {
1752 STACK_GROW(L,1); 1748 STACK_GROW(L,1);
1753 lua_pushlightuserdata( L, STACK_TRACE_KEY ); 1749 lua_pushlightuserdata( L, STACK_TRACE_KEY );
1754 lua_gettable(L, LUA_REGISTRYINDEX); 1750 lua_gettable(L, LUA_REGISTRYINDEX); // yields nil if no stack was generated (in case of cancellation for example)
1755 1751
1756 // For cancellation, a stack trace isn't placed 1752 // For cancellation, a stack trace isn't placed
1757 // 1753 //
@@ -1773,7 +1769,7 @@ static THREAD_RETURN_T THREAD_CALLCONV lane_main( void *vs)
1773 // LUA_ERRMEM(4): memory allocation error 1769 // LUA_ERRMEM(4): memory allocation error
1774#endif 1770#endif
1775 1771
1776 DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "Lane %p body: %s\n" INDENT_END, L, get_errcode_name( rc))); 1772 DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "Lane %p body: %s (%s)\n" INDENT_END, L, get_errcode_name( rc), (lua_touserdata(L,1)==CANCEL_ERROR) ? "cancelled" : lua_typename( L, lua_type( L, 1))));
1777 //STACK_DUMP(L); 1773 //STACK_DUMP(L);
1778 // Call finalizers, if the script has set them up. 1774 // Call finalizers, if the script has set them up.
1779 // 1775 //
@@ -1831,6 +1827,26 @@ static THREAD_RETURN_T THREAD_CALLCONV lane_main( void *vs)
1831 return 0; // ignored 1827 return 0; // ignored
1832} 1828}
1833 1829
1830// --- If a client wants to transfer stuff of a given module from the current state to another Lane, the module must be required
1831// with lanes.require, that will call the regular 'require', then populate lookup databases in source and keeper states
1832// module = lanes.require( "modname")
1833// upvalue[1]: _G.require
1834LUAG_FUNC( require)
1835{
1836 char const* name = lua_tostring( L, 1);
1837 DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "lanes.require %s BEGIN\n" INDENT_END, name));
1838 DEBUGSPEW_CODE( ++ debugspew_indent_depth);
1839 lua_pushvalue( L, lua_upvalueindex(1)); // "name" require
1840 lua_pushvalue( L, 1); // "name" require "name"
1841 lua_call( L, 1, 1); // "name" module
1842 populate_func_lookup_table( L, -1, name);
1843 lua_insert( L, -2); // module "name"
1844 populate_keepers( L);
1845 lua_pop( L, 1); // module
1846 DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "lanes.require %s END\n" INDENT_END, name));
1847 DEBUGSPEW_CODE( -- debugspew_indent_depth);
1848 return 1;
1849}
1834 1850
1835//--- 1851//---
1836// lane_ud= thread_new( function, [libs_str], 1852// lane_ud= thread_new( function, [libs_str],
@@ -1844,32 +1860,6 @@ static THREAD_RETURN_T THREAD_CALLCONV lane_main( void *vs)
1844// Upvalues: metatable to use for 'lane_ud' 1860// Upvalues: metatable to use for 'lane_ud'
1845// 1861//
1846 1862
1847// helper function to require a module in the keeper states and in the target state
1848// source state contains module name at the top of the stack
1849static void require_one_module( lua_State* L, lua_State* L2, bool_t _fatal)
1850{
1851 size_t len;
1852 char const* name = lua_tolstring( L, -1, &len);
1853 // require the module in the target lane
1854 STACK_GROW( L2, 2);
1855 lua_getglobal( L2, "require");
1856 if( lua_isnil( L2, -1))
1857 {
1858 lua_pop( L2, 1);
1859 if( _fatal)
1860 {
1861 luaL_error( L, "cannot pre-require modules without loading 'package' library first");
1862 }
1863 }
1864 else
1865 {
1866 lua_pushlstring( L2, name, len);
1867 lua_pcall( L2, 1, 0, 0);
1868 // we need to require this module in the keeper states as well
1869 populate_keepers( L);
1870 }
1871}
1872
1873LUAG_FUNC( thread_new) 1863LUAG_FUNC( thread_new)
1874{ 1864{
1875 lua_State* L2; 1865 lua_State* L2;
@@ -1877,17 +1867,17 @@ LUAG_FUNC( thread_new)
1877 struct s_lane** ud; 1867 struct s_lane** ud;
1878 1868
1879 char const* libs = lua_tostring( L, 2); 1869 char const* libs = lua_tostring( L, 2);
1880 lua_CFunction on_state_create = lua_iscfunction( L, 3) ? lua_tocfunction( L, 3) : NULL; 1870 int const on_state_create = lua_isfunction( L, 3) ? 3 : 0;
1881 uint_t cs = luaG_optunsigned( L, 4, 0); 1871 uint_t cs = luaG_optunsigned( L, 4, 0);
1882 int prio = (int) luaL_optinteger( L, 5, 0); 1872 int prio = (int) luaL_optinteger( L, 5, 0);
1883 uint_t glob = luaG_isany( L, 6) ? 6 : 0; 1873 uint_t glob = lua_isnoneornil( L, 6) ? 0 : 6;
1884 uint_t package = luaG_isany( L,7) ? 7 : 0; 1874 uint_t package = lua_isnoneornil( L,7) ? 0 : 7;
1885 uint_t required = luaG_isany( L, 8) ? 8 : 0; 1875 uint_t required = lua_isnoneornil( L, 8) ? 0 : 8;
1886 1876
1887#define FIXED_ARGS 8 1877#define FIXED_ARGS 8
1888 uint_t args= lua_gettop(L) - FIXED_ARGS; 1878 uint_t args= lua_gettop(L) - FIXED_ARGS;
1889 1879
1890 if (prio < THREAD_PRIO_MIN || prio > THREAD_PRIO_MAX) 1880 if( prio < THREAD_PRIO_MIN || prio > THREAD_PRIO_MAX)
1891 { 1881 {
1892 return luaL_error( L, "Priority out of range: %d..+%d (%d)", THREAD_PRIO_MIN, THREAD_PRIO_MAX, prio); 1882 return luaL_error( L, "Priority out of range: %d..+%d (%d)", THREAD_PRIO_MIN, THREAD_PRIO_MAX, prio);
1893 } 1883 }
@@ -1898,7 +1888,7 @@ LUAG_FUNC( thread_new)
1898 1888
1899 // populate with selected libraries at the same time 1889 // populate with selected libraries at the same time
1900 // 1890 //
1901 L2 = luaG_newstate( L, libs, on_state_create); 1891 L2 = luaG_newstate( L, on_state_create, libs);
1902 1892
1903 STACK_GROW( L, 2); 1893 STACK_GROW( L, 2);
1904 STACK_GROW( L2, 3); 1894 STACK_GROW( L2, 3);
@@ -1918,17 +1908,6 @@ LUAG_FUNC( thread_new)
1918 1908
1919 // modules to require in the target lane *before* the function is transfered! 1909 // modules to require in the target lane *before* the function is transfered!
1920 1910
1921 DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "thread_new: require 'lanes.core'\n" INDENT_END));
1922 //start by requiring lanes.core, since it is a bit special
1923 // it is not fatal if 'require' isn't loaded, just ignore (may cause function transfer errors later on if the lane pulls the lanes module itself)
1924 STACK_CHECK( L);
1925 STACK_CHECK( L2);
1926 lua_pushliteral( L, "lanes.core");
1927 require_one_module( L, L2, FALSE);
1928 lua_pop( L, 1);
1929 STACK_END( L2, 0);
1930 STACK_END (L, 0);
1931
1932 STACK_CHECK( L); 1911 STACK_CHECK( L);
1933 STACK_CHECK( L2); 1912 STACK_CHECK( L2);
1934 if( required) 1913 if( required)
@@ -1941,6 +1920,7 @@ LUAG_FUNC( thread_new)
1941 { 1920 {
1942 return luaL_error( L, "expected required module list as a table, got %s", luaL_typename( L, required)); 1921 return luaL_error( L, "expected required module list as a table, got %s", luaL_typename( L, required));
1943 } 1922 }
1923
1944 lua_pushnil( L); 1924 lua_pushnil( L);
1945 while( lua_next( L, required) != 0) 1925 while( lua_next( L, required) != 0)
1946 { 1926 {
@@ -1950,7 +1930,32 @@ LUAG_FUNC( thread_new)
1950 } 1930 }
1951 else 1931 else
1952 { 1932 {
1953 require_one_module( L, L2, TRUE); 1933 // require the module in the target state, and populate the lookup table there too
1934 size_t len;
1935 char const* name = lua_tolstring( L, -1, &len);
1936
1937 // require the module in the target lane
1938 STACK_GROW( L2, 2);
1939 STACK_CHECK( L2);
1940 lua_getglobal( L2, "require"); // require()?
1941 if( lua_isnil( L2, -1))
1942 {
1943 lua_pop( L2, 1); //
1944 luaL_error( L, "cannot pre-require modules without loading 'package' library first");
1945 }
1946 else
1947 {
1948 lua_pushlstring( L2, name, len); // require() name
1949 lua_pcall( L2, 1, 1, 0); // ret
1950 STACK_MID( L2, 1);
1951 // after requiring the module, register the functions it exported in our name<->function database
1952 populate_func_lookup_table( L2, -1, name);
1953 STACK_MID( L2, 1);
1954 lua_pop( L2, 1);
1955 // don't require this module in the keeper states as well, use lanes.require() for that!
1956 //populate_keepers( L);
1957 }
1958 STACK_END( L2, 0);
1954 } 1959 }
1955 lua_pop( L, 1); 1960 lua_pop( L, 1);
1956 ++ nbRequired; 1961 ++ nbRequired;
@@ -2578,7 +2583,7 @@ static const struct luaL_Reg lanes_functions [] = {
2578/* 2583/*
2579* One-time initializations 2584* One-time initializations
2580*/ 2585*/
2581static void init_once_LOCKED( lua_State* L, int const nbKeepers, lua_CFunction _on_state_create, lua_Number _shutdown_timeout, bool_t _track_lanes) 2586static void init_once_LOCKED( lua_State* L, int const _on_state_create, int const nbKeepers, lua_Number _shutdown_timeout, bool_t _track_lanes)
2582{ 2587{
2583 char const* err; 2588 char const* err;
2584 2589
@@ -2603,7 +2608,7 @@ static void init_once_LOCKED( lua_State* L, int const nbKeepers, lua_CFunction _
2603 // 2608 //
2604 MUTEX_RECURSIVE_INIT( &require_cs ); 2609 MUTEX_RECURSIVE_INIT( &require_cs );
2605 2610
2606 serialize_require( L ); 2611 serialize_require( L);
2607 2612
2608 // Linked chains handling 2613 // Linked chains handling
2609 // 2614 //
@@ -2635,7 +2640,7 @@ static void init_once_LOCKED( lua_State* L, int const nbKeepers, lua_CFunction _
2635 } 2640 }
2636 #endif 2641 #endif
2637#endif 2642#endif
2638 err = init_keepers( L, nbKeepers, _on_state_create); 2643 err = init_keepers( L, _on_state_create, nbKeepers);
2639 if (err) 2644 if (err)
2640 { 2645 {
2641 (void) luaL_error( L, "Unable to initialize: %s", err ); 2646 (void) luaL_error( L, "Unable to initialize: %s", err );
@@ -2691,7 +2696,7 @@ LUAG_FUNC( configure)
2691 char const* name = luaL_checkstring( L, lua_upvalueindex( 1)); 2696 char const* name = luaL_checkstring( L, lua_upvalueindex( 1));
2692 // all parameter checks are done lua-side 2697 // all parameter checks are done lua-side
2693 int const nbKeepers = (int)lua_tointeger( L, 1); 2698 int const nbKeepers = (int)lua_tointeger( L, 1);
2694 lua_CFunction on_state_create = lua_iscfunction( L, 2) ? lua_tocfunction( L, 2) : NULL; 2699 int const on_state_create = lua_isfunction( L, 2) ? 2 : 0;
2695 lua_Number shutdown_timeout = lua_tonumber( L, 3); 2700 lua_Number shutdown_timeout = lua_tonumber( L, 3);
2696 bool_t track_lanes = lua_toboolean( L, 4); 2701 bool_t track_lanes = lua_toboolean( L, 4);
2697 2702
@@ -2732,6 +2737,11 @@ LUAG_FUNC( configure)
2732 lua_pushcclosure( L, LG_thread_new, 1); // ... M LG_thread_new 2737 lua_pushcclosure( L, LG_thread_new, 1); // ... M LG_thread_new
2733 lua_setfield(L, -2, "thread_new"); // ... M 2738 lua_setfield(L, -2, "thread_new"); // ... M
2734 2739
2740 // we can't register 'lanes.require' normally because we want to create an upvalued closure
2741 lua_getglobal( L, "require"); // ... M require
2742 lua_pushcclosure( L, LG_require, 1); // ... M lanes.require
2743 lua_setfield( L, -2, "require"); // ... M
2744
2735 lua_pushstring(L, VERSION); // ... M VERSION 2745 lua_pushstring(L, VERSION); // ... M VERSION
2736 lua_setfield(L, -2, "version"); // ... M 2746 lua_setfield(L, -2, "version"); // ... M
2737 2747
@@ -2743,7 +2753,7 @@ LUAG_FUNC( configure)
2743 2753
2744 // register all native functions found in that module in the transferable functions database 2754 // register all native functions found in that module in the transferable functions database
2745 // we process it before _G because we don't want to find the module when scanning _G (this would generate longer names) 2755 // we process it before _G because we don't want to find the module when scanning _G (this would generate longer names)
2746 // for example in package.loaded.lanes.core.* 2756 // for example in package.loaded["lanes.core"].*
2747 populate_func_lookup_table( L, -1, name); 2757 populate_func_lookup_table( L, -1, name);
2748 2758
2749 // record all existing C/JIT-fast functions 2759 // record all existing C/JIT-fast functions
@@ -2768,7 +2778,7 @@ LUAG_FUNC( configure)
2768 static volatile int /*bool*/ go_ahead; // = 0 2778 static volatile int /*bool*/ go_ahead; // = 0
2769 if( InterlockedCompareExchange( &s_initCount, 1, 0) == 0) 2779 if( InterlockedCompareExchange( &s_initCount, 1, 0) == 0)
2770 { 2780 {
2771 init_once_LOCKED( L, nbKeepers, on_state_create, shutdown_timeout, track_lanes); 2781 init_once_LOCKED( L, on_state_create, nbKeepers, shutdown_timeout, track_lanes);
2772 go_ahead = 1; // let others pass 2782 go_ahead = 1; // let others pass
2773 } 2783 }
2774 else 2784 else
@@ -2786,7 +2796,7 @@ LUAG_FUNC( configure)
2786 // 2796 //
2787 if( s_initCount == 0) 2797 if( s_initCount == 0)
2788 { 2798 {
2789 init_once_LOCKED( L, nbKeepers, on_state_create, shutdown_timeout, track_lanes); 2799 init_once_LOCKED( L, on_state_create, nbKeepers, shutdown_timeout, track_lanes);
2790 s_initCount = 1; 2800 s_initCount = 1;
2791 } 2801 }
2792 } 2802 }
diff --git a/src/lanes.lua b/src/lanes.lua
index 1d50f97..f4eef81 100644
--- a/src/lanes.lua
+++ b/src/lanes.lua
@@ -123,9 +123,6 @@ lanes.configure = function( _params)
123 123
124 local set_singlethreaded = assert( core.set_singlethreaded) 124 local set_singlethreaded = assert( core.set_singlethreaded)
125 125
126 local now_secs = assert( core.now_secs)
127 local wakeup_conv = assert( core.wakeup_conv)
128
129 local max_prio = assert( core.max_prio) 126 local max_prio = assert( core.max_prio)
130 127
131lanes.ABOUT= 128lanes.ABOUT=
@@ -311,6 +308,7 @@ local linda = core.linda
311 308
312-- PUBLIC LANES API 309-- PUBLIC LANES API
313local timer = function() error "timers are not active" end 310local timer = function() error "timers are not active" end
311local timer_lane = nil
314local timers = timer 312local timers = timer
315 313
316if _params.with_timers ~= false then 314if _params.with_timers ~= false then
@@ -338,158 +336,161 @@ timer_gateway:set(first_time_key,true)
338-- has 'table' always declared) 336-- has 'table' always declared)
339-- 337--
340if first_time then 338if first_time then
341 local table_remove= assert( table.remove )
342 local table_insert= assert( table.insert )
343 339
344 -- 340 -----
345 -- { [deep_linda_lightuserdata]= { [deep_linda_lightuserdata]=linda_h, 341 -- Snore loop (run as a lane on the background)
346 -- [key]= { wakeup_secs [,period_secs] } [, ...] }, 342 --
347 -- } 343 -- High priority, to get trustworthy timings.
348 -- 344 --
349 -- Collection of all running timers, indexed with linda's & key. 345 -- We let the timer lane be a "free running" thread; no handle to it
350 -- 346 -- remains.
351 -- Note that we need to use the deep lightuserdata identifiers, instead 347 --
352 -- of 'linda_h' themselves as table indices. Otherwise, we'd get multiple 348 local timer_body = function()
353 -- entries for the same timer. 349 -- require lanes.core inside the timer body to prevent pulling now_secs() through an uvpvalue
354 -- 350 local core = require "lanes.core"
355 -- The 'hidden' reference to Linda proxy is used in 'check_timers()' but 351
356 -- also important to keep the Linda alive, even if all outside world threw 352 --
357 -- away pointers to it (which would ruin uniqueness of the deep pointer). 353 -- { [deep_linda_lightuserdata]= { [deep_linda_lightuserdata]=linda_h,
358 -- Now we're safe. 354 -- [key]= { wakeup_secs [,period_secs] } [, ...] },
359 -- 355 -- }
360 local collection= {} 356 --
361 357 -- Collection of all running timers, indexed with linda's & key.
362 local function get_timers() 358 --
363 local r = {} 359 -- Note that we need to use the deep lightuserdata identifiers, instead
364 for deep, t in pairs( collection) do 360 -- of 'linda_h' themselves as table indices. Otherwise, we'd get multiple
365 -- WR( tostring( deep)) 361 -- entries for the same timer.
366 local l = t[deep] 362 --
367 for key, timer_data in pairs( t) do 363 -- The 'hidden' reference to Linda proxy is used in 'check_timers()' but
368 if key ~= deep then 364 -- also important to keep the Linda alive, even if all outside world threw
369 table_insert( r, {l, key, timer_data}) 365 -- away pointers to it (which would ruin uniqueness of the deep pointer).
370 end 366 -- Now we're safe.
371 end 367 --
372 end 368 local collection = {}
373 return r 369 local table_insert = assert( table.insert)
374 end 370
375 -- 371 local get_timers = function()
376 -- set_timer( linda_h, key [,wakeup_at_secs [,period_secs]] ) 372 local r = {}
377 -- 373 for deep, t in pairs( collection) do
378 local function set_timer( linda, key, wakeup_at, period ) 374 -- WR( tostring( deep))
379 assert( wakeup_at==nil or wakeup_at>0.0 ) 375 local l = t[deep]
380 assert( period==nil or period>0.0 ) 376 for key, timer_data in pairs( t) do
377 if key ~= deep then
378 table_insert( r, {l, key, timer_data})
379 end
380 end
381 end
382 return r
383 end -- get_timers()
381 384
382 local linda_deep= linda:deep() 385 --
383 assert( linda_deep ) 386 -- set_timer( linda_h, key [,wakeup_at_secs [,period_secs]] )
387 --
388 local set_timer = function( linda, key, wakeup_at, period)
389 assert( wakeup_at == nil or wakeup_at > 0.0)
390 assert( period == nil or period > 0.0)
384 391
385 -- Find or make a lookup for this timer 392 local linda_deep = linda:deep()
386 -- 393 assert( linda_deep)
387 local t1= collection[linda_deep] 394
388 if not t1 then 395 -- Find or make a lookup for this timer
389 t1= { [linda_deep]= linda } -- proxy to use the Linda 396 --
390 collection[linda_deep]= t1 397 local t1 = collection[linda_deep]
391 end 398 if not t1 then
392 399 t1 = { [linda_deep] = linda} -- proxy to use the Linda
393 if wakeup_at==nil then 400 collection[linda_deep] = t1
394 -- Clear the timer 401 end
395 -- 402
396 t1[key]= nil 403 if wakeup_at == nil then
397 404 -- Clear the timer
398 -- Remove empty tables from collection; speeds timer checks and 405 --
399 -- lets our 'safety reference' proxy be gc:ed as well. 406 t1[key]= nil
400 -- 407
401 local empty= true 408 -- Remove empty tables from collection; speeds timer checks and
402 for k,_ in pairs(t1) do 409 -- lets our 'safety reference' proxy be gc:ed as well.
403 if k~= linda_deep then 410 --
404 empty= false; break 411 local empty = true
405 end 412 for k, _ in pairs( t1) do
406 end 413 if k ~= linda_deep then
407 if empty then 414 empty = false
408 collection[linda_deep]= nil 415 break
409 end 416 end
410 417 end
411 -- Note: any unread timer value is left at 'linda[key]' intensionally; 418 if empty then
412 -- clearing a timer just stops it. 419 collection[linda_deep] = nil
413 else 420 end
414 -- New timer or changing the timings 421
415 -- 422 -- Note: any unread timer value is left at 'linda[key]' intensionally;
416 local t2= t1[key] 423 -- clearing a timer just stops it.
417 if not t2 then 424 else
418 t2= {}; t1[key]= t2 425 -- New timer or changing the timings
419 end 426 --
420 427 local t2 = t1[key]
421 t2[1]= wakeup_at 428 if not t2 then
422 t2[2]= period -- can be 'nil' 429 t2= {}
423 end 430 t1[key]= t2
424 end 431 end
432
433 t2[1] = wakeup_at
434 t2[2] = period -- can be 'nil'
435 end
436 end -- set_timer()
437
438 local now_secs = core.now_secs
439 assert( type( now_secs) == "function")
440 -----
441 -- [next_wakeup_at]= check_timers()
442 -- Check timers, and wake up the ones expired (if any)
443 -- Returns the closest upcoming (remaining) wakeup time (or 'nil' if none).
444 local check_timers = function()
445 local now = now_secs()
446 local next_wakeup
447
448 for linda_deep,t1 in pairs(collection) do
449 for key,t2 in pairs(t1) do
450 --
451 if key==linda_deep then
452 -- no 'continue' in Lua :/
453 else
454 -- 't2': { wakeup_at_secs [,period_secs] }
455 --
456 local wakeup_at= t2[1]
457 local period= t2[2] -- may be 'nil'
458
459 if wakeup_at <= now then
460 local linda= t1[linda_deep]
461 assert(linda)
462
463 linda:set( key, now )
464
465 -- 'pairs()' allows the values to be modified (and even
466 -- removed) as far as keys are not touched
467
468 if not period then
469 -- one-time timer; gone
470 --
471 t1[key]= nil
472 wakeup_at= nil -- no 'continue' in Lua :/
473 else
474 -- repeating timer; find next wakeup (may jump multiple repeats)
475 --
476 repeat
477 wakeup_at= wakeup_at+period
478 until wakeup_at > now
479
480 t2[1]= wakeup_at
481 end
482 end
483
484 if wakeup_at and ((not next_wakeup) or (wakeup_at < next_wakeup)) then
485 next_wakeup= wakeup_at
486 end
487 end
488 end -- t2 loop
489 end -- t1 loop
490
491 return next_wakeup -- may be 'nil'
492 end -- check_timers()
425 493
426 -----
427 -- [next_wakeup_at]= check_timers()
428 --
429 -- Check timers, and wake up the ones expired (if any)
430 --
431 -- Returns the closest upcoming (remaining) wakeup time (or 'nil' if none).
432 --
433 local function check_timers()
434
435 local now= now_secs()
436 local next_wakeup
437
438 for linda_deep,t1 in pairs(collection) do
439 for key,t2 in pairs(t1) do
440 --
441 if key==linda_deep then
442 -- no 'continue' in Lua :/
443 else
444 -- 't2': { wakeup_at_secs [,period_secs] }
445 --
446 local wakeup_at= t2[1]
447 local period= t2[2] -- may be 'nil'
448
449 if wakeup_at <= now then
450 local linda= t1[linda_deep]
451 assert(linda)
452
453 linda:set( key, now )
454
455 -- 'pairs()' allows the values to be modified (and even
456 -- removed) as far as keys are not touched
457
458 if not period then
459 -- one-time timer; gone
460 --
461 t1[key]= nil
462 wakeup_at= nil -- no 'continue' in Lua :/
463 else
464 -- repeating timer; find next wakeup (may jump multiple repeats)
465 --
466 repeat
467 wakeup_at= wakeup_at+period
468 until wakeup_at > now
469
470 t2[1]= wakeup_at
471 end
472 end
473
474 if wakeup_at and ((not next_wakeup) or (wakeup_at < next_wakeup)) then
475 next_wakeup= wakeup_at
476 end
477 end
478 end -- t2 loop
479 end -- t1 loop
480
481 return next_wakeup -- may be 'nil'
482 end
483
484 -----
485 -- Snore loop (run as a lane on the background)
486 --
487 -- High priority, to get trustworthy timings.
488 --
489 -- We let the timer lane be a "free running" thread; no handle to it
490 -- remains.
491 --
492 local timer_body = function()
493 local timer_gateway_batched = timer_gateway.batched 494 local timer_gateway_batched = timer_gateway.batched
494 set_debug_threadname( "LanesTimer") 495 set_debug_threadname( "LanesTimer")
495 set_finalizer( function( err, stk) 496 set_finalizer( function( err, stk)
@@ -502,7 +503,7 @@ if first_time then
502 end 503 end
503 end) 504 end)
504 while true do 505 while true do
505 local next_wakeup= check_timers() 506 local next_wakeup = check_timers()
506 507
507 -- Sleep until next timer to wake up, or a set/clear command 508 -- Sleep until next timer to wake up, or a set/clear command
508 -- 509 --
@@ -528,9 +529,9 @@ if first_time then
528 -- WR( "timer lane: no linda, aborted?") 529 -- WR( "timer lane: no linda, aborted?")
529 end 530 end
530 end 531 end
531 end 532 end -- timer_body()
532 gen( "*", { package= {}, priority = max_prio}, timer_body)() -- "*" instead of "io,package" for LuaJIT compatibility... 533 timer_lane = gen( "*", { package= {}, priority = max_prio}, timer_body)() -- "*" instead of "io,package" for LuaJIT compatibility...
533end 534end -- first_time
534 535
535----- 536-----
536-- = timer( linda_h, key_val, date_tbl|first_secs [,period_secs] ) 537-- = timer( linda_h, key_val, date_tbl|first_secs [,period_secs] )
@@ -540,13 +541,13 @@ timer = function( linda, key, a, period )
540 if getmetatable( linda) ~= "Linda" then 541 if getmetatable( linda) ~= "Linda" then
541 error "expecting a Linda" 542 error "expecting a Linda"
542 end 543 end
543 if a==0.0 then 544 if a == 0.0 then
544 -- Caller expects to get current time stamp in Linda, on return 545 -- Caller expects to get current time stamp in Linda, on return
545 -- (like the timer had expired instantly); it would be good to set this 546 -- (like the timer had expired instantly); it would be good to set this
546 -- as late as possible (to give most current time) but also we want it 547 -- as late as possible (to give most current time) but also we want it
547 -- to precede any possible timers that might start striking. 548 -- to precede any possible timers that might start striking.
548 -- 549 --
549 linda:set( key, now_secs() ) 550 linda:set( key, core.now_secs())
550 551
551 if not period or period==0.0 then 552 if not period or period==0.0 then
552 timer_gateway:send( TGW_KEY, linda, key, nil, nil ) -- clear the timer 553 timer_gateway:send( TGW_KEY, linda, key, nil, nil ) -- clear the timer
@@ -555,8 +556,8 @@ timer = function( linda, key, a, period )
555 a= period 556 a= period
556 end 557 end
557 558
558 local wakeup_at= type(a)=="table" and wakeup_conv(a) -- given point of time 559 local wakeup_at= type(a)=="table" and core.wakeup_conv(a) -- given point of time
559 or (a and now_secs()+a or nil) 560 or (a and core.now_secs()+a or nil)
560 -- queue to timer 561 -- queue to timer
561 -- 562 --
562 timer_gateway:send( TGW_KEY, linda, key, wakeup_at, period ) 563 timer_gateway:send( TGW_KEY, linda, key, wakeup_at, period )
@@ -639,15 +640,17 @@ local function genatomic( linda, key, initial_val )
639end 640end
640 641
641 -- activate full interface 642 -- activate full interface
643 lanes.require = core.require
642 lanes.gen = gen 644 lanes.gen = gen
643 lanes.linda = core.linda 645 lanes.linda = core.linda
644 lanes.cancel_error = core.cancel_error 646 lanes.cancel_error = core.cancel_error
645 lanes.nameof = core.nameof 647 lanes.nameof = core.nameof
646 lanes.threads = (_params.track_lanes and core.threads) and core.threads or function() error "lane tracking is not available" end 648 lanes.threads = (_params.track_lanes and core.threads) and core.threads or function() error "lane tracking is not available" end
647 lanes.timer = timer 649 lanes.timer = timer
650 lanes.timer_lane = timer_lane
648 lanes.timers = timers 651 lanes.timers = timers
649 lanes.genlock = genlock 652 lanes.genlock = genlock
650 lanes.now_secs = now_secs 653 lanes.now_secs = core.now_secs
651 lanes.genatomic = genatomic 654 lanes.genatomic = genatomic
652 -- from now on, calling configure does nothing but checking that we don't call it with parameters that changed compared to the first invocation 655 -- from now on, calling configure does nothing but checking that we don't call it with parameters that changed compared to the first invocation
653 lanes.configure = function( _params2) 656 lanes.configure = function( _params2)
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
diff --git a/src/tools.h b/src/tools.h
index f79d2ad..a06e23f 100644
--- a/src/tools.h
+++ b/src/tools.h
@@ -78,11 +78,9 @@ extern int debugspew_indent_depth;
78#define luaG_optunsigned(L,i,d) ((uint_t) luaL_optinteger(L,i,d)) 78#define luaG_optunsigned(L,i,d) ((uint_t) luaL_optinteger(L,i,d))
79#define luaG_tounsigned(L,i) ((uint_t) lua_tointeger(L,i)) 79#define luaG_tounsigned(L,i) ((uint_t) lua_tointeger(L,i))
80 80
81#define luaG_isany(L,i) (!lua_isnil(L,i))
82
83void luaG_dump( lua_State* L ); 81void luaG_dump( lua_State* L );
84 82
85lua_State* luaG_newstate( lua_State* _from, char const* libs, lua_CFunction _on_state_create); 83lua_State* luaG_newstate( lua_State* _from, int const _on_state_create, char const* libs);
86 84
87typedef struct { 85typedef struct {
88 volatile int refcount; 86 volatile int refcount;
@@ -96,6 +94,7 @@ int luaG_inter_copy( lua_State *L, lua_State *L2, uint_t n);
96int luaG_inter_move( lua_State *L, lua_State *L2, uint_t n); 94int luaG_inter_move( lua_State *L, lua_State *L2, uint_t n);
97 95
98int luaG_nameof( lua_State* L); 96int luaG_nameof( lua_State* L);
97int luaG_new_require( lua_State* L);
99 98
100// Lock for reference counter inc/dec locks (to be initialized by outside code) 99// Lock for reference counter inc/dec locks (to be initialized by outside code)
101// 100//