aboutsummaryrefslogtreecommitdiff
path: root/src/lanes.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lanes.c')
-rw-r--r--src/lanes.c251
1 files changed, 145 insertions, 106 deletions
diff --git a/src/lanes.c b/src/lanes.c
index 5ccc05a..3a3cdf0 100644
--- a/src/lanes.c
+++ b/src/lanes.c
@@ -52,7 +52,7 @@
52 * ... 52 * ...
53 */ 53 */
54 54
55char const* VERSION = "3.6.6"; 55char const* VERSION = "3.7.0";
56 56
57/* 57/*
58=============================================================================== 58===============================================================================
@@ -1932,7 +1932,7 @@ LUAG_FUNC( thread_new)
1932 uint_t required = lua_isnoneornil( L, 8) ? 0 : 8; 1932 uint_t required = lua_isnoneornil( L, 8) ? 0 : 8;
1933 1933
1934#define FIXED_ARGS 8 1934#define FIXED_ARGS 8
1935 uint_t args= lua_gettop(L) - FIXED_ARGS; 1935 uint_t args = lua_gettop(L) - FIXED_ARGS;
1936 1936
1937 if( prio < THREAD_PRIO_MIN || prio > THREAD_PRIO_MAX) 1937 if( prio < THREAD_PRIO_MIN || prio > THREAD_PRIO_MAX)
1938 { 1938 {
@@ -2002,8 +2002,19 @@ LUAG_FUNC( thread_new)
2002 } 2002 }
2003 else 2003 else
2004 { 2004 {
2005 // if is it "lanes" or "lanes.core", make sure we have copied the initial settings over
2006 // which might not be the case if the libs list didn't include lanes.core or "*"
2007 if( strncmp( name, "lanes.core", len) == 0) // this works both both "lanes" and "lanes.core" because of len
2008 {
2009 luaG_copy_one_time_settings( L, L2, name);
2010 }
2005 lua_pushlstring( L2, name, len); // require() name 2011 lua_pushlstring( L2, name, len); // require() name
2006 lua_pcall( L2, 1, 1, 0); // ret 2012 if( lua_pcall( L2, 1, 1, 0) != LUA_OK) // ret/errcode
2013 {
2014 // propagate error to main state if any
2015 luaG_inter_move( L2, L, 1, eLM_LaneBody); //
2016 return lua_error( L);
2017 }
2007 STACK_MID( L2, 1); 2018 STACK_MID( L2, 1);
2008 // after requiring the module, register the functions it exported in our name<->function database 2019 // after requiring the module, register the functions it exported in our name<->function database
2009 populate_func_lookup_table( L2, -1, name); 2020 populate_func_lookup_table( L2, -1, name);
@@ -2110,7 +2121,7 @@ LUAG_FUNC( thread_new)
2110 ASSERT_L( s); 2121 ASSERT_L( s);
2111 2122
2112 //memset( s, 0, sizeof(struct s_lane) ); 2123 //memset( s, 0, sizeof(struct s_lane) );
2113 s->L= L2; 2124 s->L = L2;
2114 s->status= PENDING; 2125 s->status= PENDING;
2115 s->waiting_on = NULL; 2126 s->waiting_on = NULL;
2116 s->debug_name = NULL; 2127 s->debug_name = NULL;
@@ -2128,8 +2139,8 @@ LUAG_FUNC( thread_new)
2128 2139
2129 // Set metatable for the userdata 2140 // Set metatable for the userdata
2130 // 2141 //
2131 lua_pushvalue( L, lua_upvalueindex(1) ); 2142 lua_pushvalue( L, lua_upvalueindex( 1));
2132 lua_setmetatable( L, -2 ); 2143 lua_setmetatable( L, -2);
2133 STACK_MID( L, 1); 2144 STACK_MID( L, 1);
2134 2145
2135 // Clear environment for the userdata 2146 // Clear environment for the userdata
@@ -2140,11 +2151,11 @@ LUAG_FUNC( thread_new)
2140 // Place 's' in registry, for 'cancel_test()' (even if 'cs'==0 we still 2151 // Place 's' in registry, for 'cancel_test()' (even if 'cs'==0 we still
2141 // do cancel tests at pending send/receive). 2152 // do cancel tests at pending send/receive).
2142 // 2153 //
2143 lua_pushlightuserdata( L2, CANCEL_TEST_KEY ); 2154 lua_pushlightuserdata( L2, CANCEL_TEST_KEY);
2144 lua_pushlightuserdata( L2, s ); 2155 lua_pushlightuserdata( L2, s);
2145 lua_rawset( L2, LUA_REGISTRYINDEX ); 2156 lua_rawset( L2, LUA_REGISTRYINDEX);
2146 2157
2147 if (cs) 2158 if( cs)
2148 { 2159 {
2149 lua_sethook( L2, cancel_hook, LUA_MASKCOUNT, cs ); 2160 lua_sethook( L2, cancel_hook, LUA_MASKCOUNT, cs );
2150 } 2161 }
@@ -2632,9 +2643,6 @@ LUAG_FUNC( wakeup_conv )
2632static const struct luaL_Reg lanes_functions [] = { 2643static const struct luaL_Reg lanes_functions [] = {
2633 {"linda", LG_linda}, 2644 {"linda", LG_linda},
2634 {"now_secs", LG_now_secs}, 2645 {"now_secs", LG_now_secs},
2635#if HAVE_LANE_TRACKING
2636 {"threads", LG_threads},
2637#endif // HAVE_LANE_TRACKING
2638 {"wakeup_conv", LG_wakeup_conv}, 2646 {"wakeup_conv", LG_wakeup_conv},
2639 {"nameof", luaG_nameof}, 2647 {"nameof", luaG_nameof},
2640 {"set_singlethreaded", LG_set_singlethreaded}, 2648 {"set_singlethreaded", LG_set_singlethreaded},
@@ -2644,10 +2652,18 @@ static const struct luaL_Reg lanes_functions [] = {
2644 2652
2645/* 2653/*
2646** One-time initializations 2654** One-time initializations
2655 * settings table it at position 1 on the stack
2647*/ 2656*/
2648static void init_once_LOCKED( lua_State* L, int const _on_state_create, int const nbKeepers, lua_Number _shutdown_timeout, bool_t _track_lanes, bool_t verbose_errors) 2657static void init_once_LOCKED( lua_State* L)
2649{ 2658{
2650 GVerboseErrors = verbose_errors; 2659 STACK_CHECK( L);
2660
2661 lua_getfield( L, 1, "verbose_errors");
2662 GVerboseErrors = lua_toboolean( L, -1);
2663 lua_pop( L, 1);
2664
2665 STACK_MID( L, 0);
2666
2651#if (defined PLATFORM_WIN32) || (defined PLATFORM_POCKETPC) 2667#if (defined PLATFORM_WIN32) || (defined PLATFORM_POCKETPC)
2652 now_secs(); // initialize 'now_secs()' internal offset 2668 now_secs(); // initialize 'now_secs()' internal offset
2653#endif 2669#endif
@@ -2657,26 +2673,27 @@ static void init_once_LOCKED( lua_State* L, int const _on_state_create, int cons
2657#endif 2673#endif
2658 2674
2659#if HAVE_LANE_TRACKING 2675#if HAVE_LANE_TRACKING
2660 tracking_first = _track_lanes ? TRACKING_END : NULL; 2676 MUTEX_INIT( &tracking_cs);
2677 lua_getfield( L, 1, "track_lanes");
2678 tracking_first = lua_toboolean( L, -1) ? TRACKING_END : NULL;
2679 lua_pop( L, 1);
2680 STACK_MID( L, 0);
2661#endif // HAVE_LANE_TRACKING 2681#endif // HAVE_LANE_TRACKING
2662 2682
2663 // Locks for 'tools.c' inc/dec counters 2683 // Locks for 'tools.c' inc/dec counters
2664 // 2684 //
2665 MUTEX_INIT( &deep_lock ); 2685 MUTEX_INIT( &deep_lock);
2666 MUTEX_INIT( &mtid_lock ); 2686 MUTEX_INIT( &mtid_lock);
2667 2687
2668 // Serialize calls to 'require' from now on, also in the primary state 2688 // Serialize calls to 'require' from now on, also in the primary state
2669 // 2689 //
2670 MUTEX_RECURSIVE_INIT( &require_cs ); 2690 MUTEX_RECURSIVE_INIT( &require_cs);
2671 2691
2672 serialize_require( L); 2692 serialize_require( L);
2673 2693
2674 // Linked chains handling 2694 // Linked chains handling
2675 // 2695 //
2676 MUTEX_INIT( &selfdestruct_cs ); 2696 MUTEX_INIT( &selfdestruct_cs);
2677#if HAVE_LANE_TRACKING
2678 MUTEX_INIT( &tracking_cs);
2679#endif // HAVE_LANE_TRACKING
2680 2697
2681 //--- 2698 //---
2682 // Linux needs SCHED_RR to change thread priorities, and that is only 2699 // Linux needs SCHED_RR to change thread priorities, and that is only
@@ -2702,7 +2719,7 @@ static void init_once_LOCKED( lua_State* L, int const _on_state_create, int cons
2702#endif // LINUX_SCHED_RR 2719#endif // LINUX_SCHED_RR
2703#endif // PLATFORM_LINUX 2720#endif // PLATFORM_LINUX
2704 { 2721 {
2705 char const* err = init_keepers( L, _on_state_create, nbKeepers); 2722 char const* err = init_keepers( L);
2706 if (err) 2723 if (err)
2707 { 2724 {
2708 (void) luaL_error( L, "Unable to initialize: %s", err ); 2725 (void) luaL_error( L, "Unable to initialize: %s", err );
@@ -2713,40 +2730,41 @@ static void init_once_LOCKED( lua_State* L, int const _on_state_create, int cons
2713 // 2730 //
2714 ASSERT_L( timer_deep == NULL); 2731 ASSERT_L( timer_deep == NULL);
2715 2732
2716 STACK_CHECK( L); 2733 // proxy_ud= deep_userdata( idfunc )
2717 { 2734 //
2718 // proxy_ud= deep_userdata( idfunc ) 2735 lua_pushliteral( L, "lanes-timer"); // push a name for debug purposes
2719 // 2736 luaG_deep_userdata( L, linda_id);
2720 lua_pushliteral( L, "lanes-timer"); // push a name for debug purposes 2737 STACK_MID( L, 2);
2721 luaG_deep_userdata( L, linda_id); 2738 lua_remove( L, -2); // remove the name as we no longer need it
2722 STACK_MID( L, 2);
2723 lua_remove( L, -2); // remove the name as we no longer need it
2724
2725 ASSERT_L( lua_isuserdata(L,-1) );
2726 2739
2727 // Proxy userdata contents is only a 'DEEP_PRELUDE*' pointer 2740 ASSERT_L( lua_isuserdata(L,-1));
2728 //
2729 timer_deep = * (DEEP_PRELUDE**) lua_touserdata( L, -1);
2730 ASSERT_L( timer_deep && (timer_deep->refcount == 1) && timer_deep->deep);
2731 2741
2732 // The host Lua state must always have a reference to this Linda object in order for the timer_deep pointer to be valid. 2742 // Proxy userdata contents is only a 'DEEP_PRELUDE*' pointer
2733 // So store a reference that we will never actually use. 2743 //
2734 // at the same time, use this object as a 'desinit' marker: 2744 timer_deep = * (DEEP_PRELUDE**) lua_touserdata( L, -1);
2735 // when the main lua State is closed, this object will be GC'ed 2745 ASSERT_L( timer_deep && (timer_deep->refcount == 1) && timer_deep->deep);
2736 {
2737 lua_newuserdata( L, 1);
2738 lua_newtable( L);
2739 lua_pushnumber( L, _shutdown_timeout);
2740 lua_pushcclosure( L, selfdestruct_gc, 1);
2741 lua_setfield( L, -2, "__gc");
2742 lua_pushliteral( L, "AtExit");
2743 lua_setfield( L, -2, "__metatable");
2744 lua_setmetatable( L, -2);
2745 }
2746 lua_insert( L, -2); // Swap key with the Linda object
2747 lua_rawset( L, LUA_REGISTRYINDEX);
2748 2746
2747 // The host Lua state must always have a reference to this Linda object in order for the timer_deep pointer to be valid.
2748 // So store a reference that we will never actually use.
2749 // at the same time, use this object as a 'desinit' marker:
2750 // when the main lua State is closed, this object will be GC'ed
2751 {
2752 lua_newuserdata( L, 1);
2753 lua_newtable( L);
2754 lua_getfield( L, 1, "shutdown_timeout");
2755 lua_pushcclosure( L, selfdestruct_gc, 1);
2756 lua_setfield( L, -2, "__gc");
2757 lua_pushliteral( L, "AtExit");
2758 lua_setfield( L, -2, "__metatable");
2759 lua_setmetatable( L, -2);
2749 } 2760 }
2761 lua_insert( L, -2); // Swap key with the Linda object
2762 lua_rawset( L, LUA_REGISTRYINDEX);
2763
2764 // we'll need this everytime we transfer some C function from/to this state
2765 lua_newtable( L);
2766 lua_setfield( L, LUA_REGISTRYINDEX, LOOKUP_REGKEY);
2767
2750 STACK_END( L, 0); 2768 STACK_END( L, 0);
2751} 2769}
2752 2770
@@ -2754,23 +2772,19 @@ static volatile long s_initCount = 0;
2754 2772
2755// upvalue 1: module name 2773// upvalue 1: module name
2756// upvalue 2: module table 2774// upvalue 2: module table
2775// param 1: settings table
2757LUAG_FUNC( configure) 2776LUAG_FUNC( configure)
2758{ 2777{
2759 char const* name = luaL_checkstring( L, lua_upvalueindex( 1)); 2778 char const* name = luaL_checkstring( L, lua_upvalueindex( 1));
2760 // all parameter checks are done lua-side 2779 _ASSERT_L( L, lua_type( L, 1) == LUA_TTABLE);
2761 int const nbKeepers = (int)lua_tointeger( L, 1); 2780 STACK_CHECK( L);
2762 int const on_state_create = lua_isfunction( L, 2) ? 2 : 0;
2763 lua_Number shutdown_timeout = lua_tonumber( L, 3);
2764 bool_t track_lanes = lua_toboolean( L, 4);
2765 bool_t protect_allocator = lua_toboolean( L, 5);
2766 bool_t verbose_errors = lua_toboolean( L, 6);
2767 2781
2768 DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "%p: lanes.configure() BEGIN\n" INDENT_END, L)); 2782 DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "%p: lanes.configure() BEGIN\n" INDENT_END, L));
2769 DEBUGSPEW_CODE( ++ debugspew_indent_depth); 2783 DEBUGSPEW_CODE( ++ debugspew_indent_depth);
2770 STACK_CHECK( L);
2771 2784
2772 // not in init_once_LOCKED because we can have several hosted "master" Lua states where Lanes is require()d. 2785 // not in init_once_LOCKED because we can have several hosted "master" Lua states where Lanes is require()d.
2773 if( protect_allocator) 2786 lua_getfield( L, 1, "protect_allocator"); // settings protect_allocator
2787 if( lua_toboolean( L, -1))
2774 { 2788 {
2775 void* ud; 2789 void* ud;
2776 lua_Alloc allocf = lua_getallocf( L, &ud); 2790 lua_Alloc allocf = lua_getallocf( L, &ud);
@@ -2783,6 +2797,7 @@ LUAG_FUNC( configure)
2783 lua_setallocf( L, protected_lua_Alloc, s); 2797 lua_setallocf( L, protected_lua_Alloc, s);
2784 } 2798 }
2785 } 2799 }
2800 lua_pop( L, 1); // settings
2786 STACK_MID( L, 0); 2801 STACK_MID( L, 0);
2787 2802
2788 /* 2803 /*
@@ -2797,7 +2812,7 @@ LUAG_FUNC( configure)
2797 static volatile int /*bool*/ go_ahead; // = 0 2812 static volatile int /*bool*/ go_ahead; // = 0
2798 if( InterlockedCompareExchange( &s_initCount, 1, 0) == 0) 2813 if( InterlockedCompareExchange( &s_initCount, 1, 0) == 0)
2799 { 2814 {
2800 init_once_LOCKED( L, on_state_create, nbKeepers, shutdown_timeout, track_lanes, verbose_errors); 2815 init_once_LOCKED( L);
2801 go_ahead = 1; // let others pass 2816 go_ahead = 1; // let others pass
2802 } 2817 }
2803 else 2818 else
@@ -2815,7 +2830,7 @@ LUAG_FUNC( configure)
2815 // 2830 //
2816 if( s_initCount == 0) 2831 if( s_initCount == 0)
2817 { 2832 {
2818 init_once_LOCKED( L, on_state_create, nbKeepers, shutdown_timeout, track_lanes, verbose_errors); 2833 init_once_LOCKED( L);
2819 s_initCount = 1; 2834 s_initCount = 1;
2820 } 2835 }
2821 } 2836 }
@@ -2824,56 +2839,64 @@ LUAG_FUNC( configure)
2824#endif // THREADAPI == THREADAPI_PTHREAD 2839#endif // THREADAPI == THREADAPI_PTHREAD
2825 2840
2826 // Retrieve main module interface table 2841 // Retrieve main module interface table
2827 lua_pushvalue( L, lua_upvalueindex( 2)); // ... M 2842 lua_pushvalue( L, lua_upvalueindex( 2)); // settings M
2828 // remove configure() (this function) from the module interface 2843 // remove configure() (this function) from the module interface
2829 lua_pushnil( L); // ... M nil 2844 lua_pushnil( L); // settings M nil
2830 lua_setfield( L, -2, "configure"); // ... M 2845 lua_setfield( L, -2, "configure"); // settings M
2831 // add functions to the module's table 2846 // add functions to the module's table
2832 luaG_registerlibfuncs( L, lanes_functions); 2847 luaG_registerlibfuncs( L, lanes_functions);
2848#if HAVE_LANE_TRACKING
2849 // register core.threads() only if settings say it should be available
2850 if( tracking_first != NULL)
2851 {
2852 lua_pushcfunction( L, LG_threads); // settings M LG_threads()
2853 lua_setfield( L, -2, "threads");
2854 }
2855#endif // HAVE_LANE_TRACKING
2833 STACK_MID( L, 1); 2856 STACK_MID( L, 1);
2834 2857
2835 ASSERT_L( timer_deep != NULL); // initialized by init_once_LOCKED 2858 ASSERT_L( timer_deep != NULL); // initialized by init_once_LOCKED
2836 luaG_push_proxy( L, linda_id, (DEEP_PRELUDE*) timer_deep); // ... M timer_deep 2859 luaG_push_proxy( L, linda_id, (DEEP_PRELUDE*) timer_deep); // settings M timer_deep
2837 lua_setfield( L, -2, "timer_gateway"); // ... M 2860 lua_setfield( L, -2, "timer_gateway"); // settings M
2838 STACK_MID( L, 1); 2861 STACK_MID( L, 1);
2839 2862
2840 // prepare the metatable for threads 2863 // prepare the metatable for threads
2841 // contains keys: { __gc, __index, cached_error, cached_tostring, cancel, join } 2864 // contains keys: { __gc, __index, cached_error, cached_tostring, cancel, join }
2842 // 2865 //
2843 lua_newtable( L); // ... M mt 2866 lua_newtable( L); // settings M mt
2844 lua_pushcfunction( L, LG_thread_gc); // ... M mt LG_thread_gc 2867 lua_pushcfunction( L, LG_thread_gc); // settings M mt LG_thread_gc
2845 lua_setfield( L, -2, "__gc"); // ... M mt 2868 lua_setfield( L, -2, "__gc"); // settings M mt
2846 lua_pushcfunction( L, LG_thread_index); // ... M mt LG_thread_index 2869 lua_pushcfunction( L, LG_thread_index); // settings M mt LG_thread_index
2847 lua_setfield( L, -2, "__index"); // ... M mt 2870 lua_setfield( L, -2, "__index"); // settings M mt
2848 lua_getglobal( L, "error"); // ... M mt error 2871 lua_getglobal( L, "error"); // settings M mt error
2849 ASSERT_L( lua_isfunction( L, -1)); 2872 ASSERT_L( lua_isfunction( L, -1));
2850 lua_setfield( L, -2, "cached_error"); // ... M mt 2873 lua_setfield( L, -2, "cached_error"); // settings M mt
2851 lua_getglobal( L, "tostring"); // ... M mt tostring 2874 lua_getglobal( L, "tostring"); // settings M mt tostring
2852 ASSERT_L( lua_isfunction( L, -1)); 2875 ASSERT_L( lua_isfunction( L, -1));
2853 lua_setfield( L, -2, "cached_tostring"); // ... M mt 2876 lua_setfield( L, -2, "cached_tostring"); // settings M mt
2854 lua_pushcfunction( L, LG_thread_join); // ... M mt LG_thread_join 2877 lua_pushcfunction( L, LG_thread_join); // settings M mt LG_thread_join
2855 lua_setfield( L, -2, "join"); // ... M mt 2878 lua_setfield( L, -2, "join"); // settings M mt
2856 lua_pushcfunction( L, LG_thread_cancel); // ... M mt LG_thread_cancel 2879 lua_pushcfunction( L, LG_thread_cancel); // settings M mt LG_thread_cancel
2857 lua_setfield( L, -2, "cancel"); // ... M mt 2880 lua_setfield( L, -2, "cancel"); // settings M mt
2858 lua_pushliteral( L, "Lane"); // ... M mt "Lane" 2881 lua_pushliteral( L, "Lane"); // settings M mt "Lane"
2859 lua_setfield( L, -2, "__metatable"); // ... M mt 2882 lua_setfield( L, -2, "__metatable"); // settings M mt
2860 2883
2861 lua_pushcclosure( L, LG_thread_new, 1); // ... M LG_thread_new 2884 lua_pushcclosure( L, LG_thread_new, 1); // settings M LG_thread_new
2862 lua_setfield(L, -2, "thread_new"); // ... M 2885 lua_setfield(L, -2, "thread_new"); // settings M
2863 2886
2864 // we can't register 'lanes.require' normally because we want to create an upvalued closure 2887 // we can't register 'lanes.require' normally because we want to create an upvalued closure
2865 lua_getglobal( L, "require"); // ... M require 2888 lua_getglobal( L, "require"); // settings M require
2866 lua_pushcclosure( L, LG_require, 1); // ... M lanes.require 2889 lua_pushcclosure( L, LG_require, 1); // settings M lanes.require
2867 lua_setfield( L, -2, "require"); // ... M 2890 lua_setfield( L, -2, "require"); // settings M
2868 2891
2869 lua_pushstring(L, VERSION); // ... M VERSION 2892 lua_pushstring(L, VERSION); // settings M VERSION
2870 lua_setfield(L, -2, "version"); // ... M 2893 lua_setfield(L, -2, "version"); // settings M
2871 2894
2872 lua_pushinteger(L, THREAD_PRIO_MAX); // ... M THREAD_PRIO_MAX 2895 lua_pushinteger(L, THREAD_PRIO_MAX); // settings M THREAD_PRIO_MAX
2873 lua_setfield(L, -2, "max_prio"); // ... M 2896 lua_setfield(L, -2, "max_prio"); // settings M
2874 2897
2875 lua_pushlightuserdata( L, CANCEL_ERROR); // ... M CANCEL_ERROR 2898 lua_pushlightuserdata( L, CANCEL_ERROR); // settings M CANCEL_ERROR
2876 lua_setfield(L, -2, "cancel_error"); // ... M 2899 lua_setfield(L, -2, "cancel_error"); // settings M
2877 2900
2878 // register all native functions found in that module in the transferable functions database 2901 // register all native functions found in that module in the transferable functions database
2879 // we process it before _G because we don't want to find the module when scanning _G (this would generate longer names) 2902 // we process it before _G because we don't want to find the module when scanning _G (this would generate longer names)
@@ -2882,14 +2905,18 @@ LUAG_FUNC( configure)
2882 2905
2883 // record all existing C/JIT-fast functions 2906 // record all existing C/JIT-fast functions
2884 // Lua 5.2 no longer has LUA_GLOBALSINDEX: we must push globals table on the stack 2907 // Lua 5.2 no longer has LUA_GLOBALSINDEX: we must push globals table on the stack
2885 lua_pushglobaltable( L); // ... M _G 2908 lua_pushglobaltable( L); // settings M _G
2886 populate_func_lookup_table( L, -1, NULL); 2909 populate_func_lookup_table( L, -1, NULL);
2887 lua_pop( L, 2); // ... 2910 lua_pop( L, 1); // settings M
2911 // set _R[CONFIG_REGKEY] = settings
2912 lua_pushvalue( L, -2); // settings M settings
2913 lua_setfield( L, LUA_REGISTRYINDEX, CONFIG_REGKEY); // settings M
2914 lua_pop( L, 1); // settings
2888 STACK_END( L, 0); 2915 STACK_END( L, 0);
2889 DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "%p: lanes.configure() END\n" INDENT_END, L)); 2916 DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "%p: lanes.configure() END\n" INDENT_END, L));
2890 DEBUGSPEW_CODE( -- debugspew_indent_depth); 2917 DEBUGSPEW_CODE( -- debugspew_indent_depth);
2891 // Return nothing 2918 // Return the settings table
2892 return 0; 2919 return 1;
2893} 2920}
2894 2921
2895// helper to have correct callstacks when crashing a Win32 running on 64 bits Windows 2922// helper to have correct callstacks when crashing a Win32 running on 64 bits Windows
@@ -2920,16 +2947,28 @@ int LANES_API luaopen_lanes_core( lua_State* L)
2920{ 2947{
2921 EnableCrashingOnCrashes(); 2948 EnableCrashingOnCrashes();
2922 2949
2923 STACK_GROW( L, 3); 2950 STACK_GROW( L, 4);
2924 STACK_CHECK( L); 2951 STACK_CHECK( L);
2925 2952
2926 // Create main module interface table 2953 // Create main module interface table
2927 // we only have 1 closure, which must be called to configure Lanes 2954 // we only have 1 closure, which must be called to configure Lanes
2928 lua_newtable( L); // M 2955 lua_newtable( L); // M
2929 lua_pushvalue( L, 1); // M "lanes.core" 2956 lua_pushvalue( L, 1); // M "lanes.core"
2930 lua_pushvalue( L, -2); // M "lanes.core" M 2957 lua_pushvalue( L, -2); // M "lanes.core" M
2931 lua_pushcclosure( L, LG_configure, 2); // M LG_configure() 2958 lua_pushcclosure( L, LG_configure, 2); // M LG_configure()
2932 lua_setfield( L, -2, "configure"); // M 2959 lua_getfield( L, LUA_REGISTRYINDEX, CONFIG_REGKEY); // M LG_configure() settings
2960 if( !lua_isnil( L, -1)) // this is not the first require "lanes.core": call configure() immediately
2961 {
2962 lua_pushvalue( L, -1); // M LG_configure() settings settings
2963 lua_setfield( L, -4, "settings"); // M LG_configure() settings
2964 lua_call( L, 1, 0); // M
2965 }
2966 else
2967 {
2968 // will do nothing on first invocation, as we haven't stored settings in the registry yet
2969 lua_setfield( L, -3, "settings"); // M LG_configure()
2970 lua_setfield( L, -2, "configure"); // M
2971 }
2933 2972
2934 STACK_END( L, 1); 2973 STACK_END( L, 1);
2935 return 1; 2974 return 1;