aboutsummaryrefslogtreecommitdiff
path: root/src/lanes.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/lanes.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/lanes.c')
-rw-r--r--src/lanes.c134
1 files changed, 72 insertions, 62 deletions
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 }