diff options
author | Benoit Germain <b n t DOT g e r m a i n AT g m a i l DOT c o m> | 2013-10-11 20:08:32 +0200 |
---|---|---|
committer | Benoit Germain <b n t DOT g e r m a i n AT g m a i l DOT c o m> | 2013-10-11 20:08:32 +0200 |
commit | 44540b9335f3bbd2f6fda3e13329b28ec76b6d7a (patch) | |
tree | 4b6d659c0976e58f6cbd907b673c2b9d769b9e88 /src/tools.c | |
parent | 938ee19cfcac09bfcfa1dd2a7861690436024410 (diff) | |
download | lanes-44540b9335f3bbd2f6fda3e13329b28ec76b6d7a.tar.gz lanes-44540b9335f3bbd2f6fda3e13329b28ec76b6d7a.tar.bz2 lanes-44540b9335f3bbd2f6fda3e13329b28ec76b6d7a.zip |
version 3.7.0
* fix lanes.threads() not being available in a lane where
lanes.configure() settings didn't contain track_lanes although the
initial configure() call did.
* require "lanes".configure() sequence is only necessary at the first
require "lanes".
* fix a crash at application shutdown where in some situations we could
deinitialize the protected allocator mutex while a lane was still using
it.
* fix timers broken by change 69
Diffstat (limited to 'src/tools.c')
-rw-r--r-- | src/tools.c | 96 |
1 files changed, 68 insertions, 28 deletions
diff --git a/src/tools.c b/src/tools.c index b02177b..95104d6 100644 --- a/src/tools.c +++ b/src/tools.c | |||
@@ -44,9 +44,31 @@ THE SOFTWARE. | |||
44 | #include <stdlib.h> | 44 | #include <stdlib.h> |
45 | #include <malloc.h> | 45 | #include <malloc.h> |
46 | 46 | ||
47 | /* | ||
48 | * ############################################################################################### | ||
49 | * ########################################### ASSERT ############################################ | ||
50 | * ############################################################################################### | ||
51 | */ | ||
52 | void ASSERT_IMPL( lua_State* L, bool_t cond_, char const* file_, int const line_, char const* text_) | ||
53 | { | ||
54 | if ( !cond_) | ||
55 | { | ||
56 | (void) luaL_error( L, "ASSERT failed: %s:%d '%s'", file_, line_, text_); | ||
57 | } | ||
58 | } | ||
59 | |||
47 | // for verbose errors | 60 | // for verbose errors |
48 | bool_t GVerboseErrors = FALSE; | 61 | bool_t GVerboseErrors = FALSE; |
49 | 62 | ||
63 | char const* const CONFIG_REGKEY = "ee932492-a654-4506-9da8-f16540bdb5d4"; | ||
64 | char const* const LOOKUP_REGKEY = "ddea37aa-50c7-4d3f-8e0b-fb7a9d62bac5"; | ||
65 | |||
66 | /* | ||
67 | * ############################################################################################### | ||
68 | * ######################################### Lua 5.1/5.2 ######################################### | ||
69 | * ############################################################################################### | ||
70 | */ | ||
71 | |||
50 | /* | 72 | /* |
51 | ** Copied from Lua 5.2 loadlib.c | 73 | ** Copied from Lua 5.2 loadlib.c |
52 | */ | 74 | */ |
@@ -137,6 +159,19 @@ void luaG_dump( lua_State* L ) { | |||
137 | fprintf( stderr, "\n" ); | 159 | fprintf( stderr, "\n" ); |
138 | } | 160 | } |
139 | 161 | ||
162 | // just like lua_xmove, args are (from, to) | ||
163 | void luaG_copy_one_time_settings( lua_State* L, lua_State* L2, char const* name_) | ||
164 | { | ||
165 | STACK_GROW( L, 1); | ||
166 | // copy settings from from source to destination registry | ||
167 | lua_getfield( L, LUA_REGISTRYINDEX, CONFIG_REGKEY); | ||
168 | if( luaG_inter_move( L, L2, 1, eLM_LaneBody) < 0) // error? | ||
169 | { | ||
170 | (void) luaL_error( L, "failed to copy settings when loading %s", name_); | ||
171 | } | ||
172 | lua_setfield( L2, LUA_REGISTRYINDEX, CONFIG_REGKEY); | ||
173 | } | ||
174 | |||
140 | 175 | ||
141 | /*---=== luaG_newstate ===---*/ | 176 | /*---=== luaG_newstate ===---*/ |
142 | 177 | ||
@@ -171,24 +206,31 @@ static const luaL_Reg libs[] = | |||
171 | { NULL, NULL } | 206 | { NULL, NULL } |
172 | }; | 207 | }; |
173 | 208 | ||
174 | static void open1lib( lua_State* L, char const* name, size_t len) | 209 | static void open1lib( lua_State* L, char const* name_, size_t len_, lua_State* from_) |
175 | { | 210 | { |
176 | int i; | 211 | int i; |
177 | for( i = 0; libs[i].name; ++ i) | 212 | for( i = 0; libs[i].name; ++ i) |
178 | { | 213 | { |
179 | if( strncmp( name, libs[i].name, len) == 0) | 214 | if( strncmp( name_, libs[i].name, len_) == 0) |
180 | { | 215 | { |
181 | lua_CFunction libfunc = libs[i].func; | 216 | lua_CFunction libfunc = libs[i].func; |
182 | if( libfunc) | 217 | name_ = libs[i].name; // note that the provided name_ doesn't necessarily ends with '\0', hence len_ |
218 | if( libfunc != NULL) | ||
183 | { | 219 | { |
184 | bool_t createGlobal = (libfunc != require_lanes_core) ? TRUE : FALSE; // don't want to create a global for "lanes.core" | 220 | bool_t const isLanesCore = (libfunc == require_lanes_core) ? TRUE : FALSE; // don't want to create a global for "lanes.core" |
185 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "opening %.*s library\n" INDENT_END, len, name)); | 221 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "opening %.*s library\n" INDENT_END, len_, name_)); |
186 | STACK_CHECK( L); | 222 | STACK_CHECK( L); |
223 | if( isLanesCore == TRUE) | ||
224 | { | ||
225 | // copy settings from from source to destination registry | ||
226 | luaG_copy_one_time_settings( from_, L, name_); | ||
227 | } | ||
187 | // open the library as if through require(), and create a global as well if necessary (the library table is left on the stack) | 228 | // open the library as if through require(), and create a global as well if necessary (the library table is left on the stack) |
188 | luaL_requiref( L, libs[i].name, libfunc, createGlobal); | 229 | luaL_requiref( L, name_, libfunc, !isLanesCore); |
189 | if( createGlobal == FALSE) | 230 | // lanes.core doesn't declare a global, so scan it here and now |
231 | if( isLanesCore == TRUE) | ||
190 | { | 232 | { |
191 | populate_func_lookup_table( L, -1, name); | 233 | populate_func_lookup_table( L, -1, name_); |
192 | } | 234 | } |
193 | lua_pop( L, 1); | 235 | lua_pop( L, 1); |
194 | STACK_END( L, 0); | 236 | STACK_END( L, 0); |
@@ -473,14 +515,8 @@ void populate_func_lookup_table( lua_State* L, int _i, char const* name_) | |||
473 | DEBUGSPEW_CODE( ++ debugspew_indent_depth); | 515 | DEBUGSPEW_CODE( ++ debugspew_indent_depth); |
474 | STACK_GROW( L, 3); | 516 | STACK_GROW( L, 3); |
475 | STACK_CHECK( L); | 517 | STACK_CHECK( L); |
476 | lua_getfield( L, LUA_REGISTRYINDEX, LOOKUP_KEY); // {}? | 518 | lua_getfield( L, LUA_REGISTRYINDEX, LOOKUP_REGKEY); // {} |
477 | if( lua_isnil( L, -1)) // nil | 519 | ASSERT_L( lua_istable( L, -1)); |
478 | { | ||
479 | lua_pop( L, 1); // | ||
480 | lua_newtable( L); // {} | ||
481 | lua_pushvalue( L, -1); // {} {} | ||
482 | lua_setfield( L, LUA_REGISTRYINDEX, LOOKUP_KEY); // {} | ||
483 | } | ||
484 | if( lua_type( L, in_base) == LUA_TFUNCTION) // for example when a module is a simple function | 520 | if( lua_type( L, in_base) == LUA_TFUNCTION) // for example when a module is a simple function |
485 | { | 521 | { |
486 | name_ = name_ ? name_ : "NULL"; | 522 | name_ = name_ ? name_ : "NULL"; |
@@ -538,17 +574,18 @@ lua_State* luaG_newstate( lua_State* _from, int const _on_state_create, char con | |||
538 | lua_Alloc allocF = lua_getallocf( _from, &allocUD); | 574 | lua_Alloc allocF = lua_getallocf( _from, &allocUD); |
539 | lua_State* L = lua_newstate( allocF, allocUD); | 575 | lua_State* L = lua_newstate( allocF, allocUD); |
540 | 576 | ||
541 | if( !L) | 577 | if( L == NULL) |
542 | { | 578 | { |
543 | luaL_error( _from, "'lua_newstate()' failed; out of memory"); | 579 | (void) luaL_error( _from, "'lua_newstate()' failed; out of memory"); |
544 | } | 580 | } |
545 | 581 | ||
546 | // neither libs (not even 'base') nor special init func: we are done | 582 | // neither libs (not even 'base') nor special init func: we are done |
547 | if( libs == NULL && _on_state_create <= 0) | 583 | if( libs == NULL && _on_state_create <= 0) |
548 | { | 584 | { |
585 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "luaG_newstate(NULL)\n" INDENT_END)); | ||
549 | return L; | 586 | return L; |
550 | } | 587 | } |
551 | // if we are here, no keeper state is involved (because libs == NULL when we init keepers) | 588 | // from this point, we are not creating a keeper state (because libs == NULL when we init keepers) |
552 | 589 | ||
553 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "luaG_newstate()\n" INDENT_END)); | 590 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "luaG_newstate()\n" INDENT_END)); |
554 | DEBUGSPEW_CODE( ++ debugspew_indent_depth); | 591 | DEBUGSPEW_CODE( ++ debugspew_indent_depth); |
@@ -556,12 +593,15 @@ lua_State* luaG_newstate( lua_State* _from, int const _on_state_create, char con | |||
556 | STACK_GROW( L, 2); | 593 | STACK_GROW( L, 2); |
557 | STACK_CHECK( L); | 594 | STACK_CHECK( L); |
558 | // 'lua.c' stops GC during initialization so perhaps its a good idea. :) | 595 | // 'lua.c' stops GC during initialization so perhaps its a good idea. :) |
559 | // but do it after _on_state_create in case it does a lot of stuff... | ||
560 | lua_gc( L, LUA_GCSTOP, 0); | 596 | lua_gc( L, LUA_GCSTOP, 0); |
561 | 597 | ||
598 | // we'll need this everytime we transfer some C function from/to this state | ||
599 | lua_newtable( L); | ||
600 | lua_setfield( L, LUA_REGISTRYINDEX, LOOKUP_REGKEY); | ||
601 | |||
562 | // Anything causes 'base' to be taken in | 602 | // Anything causes 'base' to be taken in |
563 | // | 603 | // |
564 | if( libs) | 604 | if( libs != NULL) |
565 | { | 605 | { |
566 | // special "*" case (mainly to help with LuaJIT compatibility) | 606 | // special "*" case (mainly to help with LuaJIT compatibility) |
567 | // as we are called from luaopen_lanes_core() already, and that would deadlock | 607 | // as we are called from luaopen_lanes_core() already, and that would deadlock |
@@ -570,7 +610,7 @@ lua_State* luaG_newstate( lua_State* _from, int const _on_state_create, char con | |||
570 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "opening ALL standard libraries\n" INDENT_END)); | 610 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "opening ALL standard libraries\n" INDENT_END)); |
571 | luaL_openlibs( L); | 611 | luaL_openlibs( L); |
572 | // don't forget lanes.core for regular lane states | 612 | // don't forget lanes.core for regular lane states |
573 | open1lib( L, "lanes.core", 10); | 613 | open1lib( L, "lanes.core", 10, _from); |
574 | libs = NULL; // done with libs | 614 | libs = NULL; // done with libs |
575 | } | 615 | } |
576 | else | 616 | else |
@@ -604,7 +644,7 @@ lua_State* luaG_newstate( lua_State* _from, int const _on_state_create, char con | |||
604 | while( isalnum( p[len]) || p[len] == '.') | 644 | while( isalnum( p[len]) || p[len] == '.') |
605 | ++ len; | 645 | ++ len; |
606 | // open library | 646 | // open library |
607 | open1lib( L, p, len); | 647 | open1lib( L, p, len, _from); |
608 | } | 648 | } |
609 | serialize_require( L); | 649 | serialize_require( L); |
610 | } | 650 | } |
@@ -612,7 +652,7 @@ lua_State* luaG_newstate( lua_State* _from, int const _on_state_create, char con | |||
612 | lua_gc( L, LUA_GCRESTART, 0); | 652 | lua_gc( L, LUA_GCRESTART, 0); |
613 | 653 | ||
614 | STACK_CHECK( L); | 654 | STACK_CHECK( L); |
615 | // call this after the base libraries are loaded! | 655 | // call this after the base libraries are loaded and GC is restarted |
616 | if( _on_state_create > 0) | 656 | if( _on_state_create > 0) |
617 | { | 657 | { |
618 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "calling on_state_create()\n" INDENT_END)); | 658 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "calling on_state_create()\n" INDENT_END)); |
@@ -633,7 +673,7 @@ lua_State* luaG_newstate( lua_State* _from, int const _on_state_create, char con | |||
633 | // capture error and forward it to main state | 673 | // capture error and forward it to main state |
634 | if( lua_pcall( L, 0, 0, 0) != LUA_OK) | 674 | if( lua_pcall( L, 0, 0, 0) != LUA_OK) |
635 | { | 675 | { |
636 | luaL_error( _from, "on_state_create failed: \"%s\"", lua_isstring( L, -1) ? lua_tostring( L, -1) : lua_typename( L, lua_type( L, -1))); | 676 | (void) luaL_error( _from, "on_state_create failed: \"%s\"", lua_isstring( L, -1) ? lua_tostring( L, -1) : lua_typename( L, lua_type( L, -1))); |
637 | } | 677 | } |
638 | STACK_MID( L, 0); | 678 | STACK_MID( L, 0); |
639 | } | 679 | } |
@@ -1486,7 +1526,7 @@ static void lookup_native_func( lua_State* L2, lua_State* L, uint_t i, enum eLoo | |||
1486 | else | 1526 | else |
1487 | { | 1527 | { |
1488 | // fetch the name from the source state's lookup table | 1528 | // fetch the name from the source state's lookup table |
1489 | lua_getfield( L, LUA_REGISTRYINDEX, LOOKUP_KEY); // ... f ... {} | 1529 | lua_getfield( L, LUA_REGISTRYINDEX, LOOKUP_REGKEY); // ... f ... {} |
1490 | ASSERT_L( lua_istable( L, -1)); | 1530 | ASSERT_L( lua_istable( L, -1)); |
1491 | lua_pushvalue( L, i); // ... f ... {} f | 1531 | lua_pushvalue( L, i); // ... f ... {} f |
1492 | lua_rawget( L, -2); // ... f ... {} "f.q.n" | 1532 | lua_rawget( L, -2); // ... f ... {} "f.q.n" |
@@ -1533,7 +1573,7 @@ static void lookup_native_func( lua_State* L2, lua_State* L, uint_t i, enum eLoo | |||
1533 | } | 1573 | } |
1534 | else | 1574 | else |
1535 | { | 1575 | { |
1536 | lua_getfield( L2, LUA_REGISTRYINDEX, LOOKUP_KEY); // {} | 1576 | lua_getfield( L2, LUA_REGISTRYINDEX, LOOKUP_REGKEY); // {} |
1537 | ASSERT_L( lua_istable( L2, -1)); | 1577 | ASSERT_L( lua_istable( L2, -1)); |
1538 | lua_pushlstring( L2, fqn, len); // {} "f.q.n" | 1578 | lua_pushlstring( L2, fqn, len); // {} "f.q.n" |
1539 | lua_rawget( L2, -2); // {} f | 1579 | lua_rawget( L2, -2); // {} f |
@@ -1923,7 +1963,7 @@ static bool_t inter_copy_one_( lua_State* L2, uint_t L2_cache_i, lua_State* L, u | |||
1923 | */ | 1963 | */ |
1924 | if( inter_copy_one_( L2, L2_cache_i, L, val_i, VT_NORMAL, mode_, valPath)) | 1964 | if( inter_copy_one_( L2, L2_cache_i, L, val_i, VT_NORMAL, mode_, valPath)) |
1925 | { | 1965 | { |
1926 | ASSERT_L( lua_istable(L2,-3)); | 1966 | ASSERT_L( lua_istable( L2, -3)); |
1927 | lua_rawset( L2, -3); // add to table (pops key & val) | 1967 | lua_rawset( L2, -3); // add to table (pops key & val) |
1928 | } | 1968 | } |
1929 | else | 1969 | else |