diff options
Diffstat (limited to 'src/lanes.c')
-rw-r--r-- | src/lanes.c | 251 |
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 | ||
55 | char const* VERSION = "3.6.6"; | 55 | char 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 ) | |||
2632 | static const struct luaL_Reg lanes_functions [] = { | 2643 | static 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 | */ |
2648 | static 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) | 2657 | static 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 | ||
2757 | LUAG_FUNC( configure) | 2776 | LUAG_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; |