diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/lanes.cpp | 50 | ||||
-rw-r--r-- | src/macros_and_utils.h | 2 | ||||
-rw-r--r-- | src/state.cpp | 34 | ||||
-rw-r--r-- | src/tools.cpp | 95 | ||||
-rw-r--r-- | src/universe.h | 4 |
5 files changed, 94 insertions, 91 deletions
diff --git a/src/lanes.cpp b/src/lanes.cpp index 47ca79a..5fb81a3 100644 --- a/src/lanes.cpp +++ b/src/lanes.cpp | |||
@@ -434,7 +434,7 @@ static bool selfdestruct_remove(Lane* lane_) | |||
434 | *ref = lane_->selfdestruct_next; | 434 | *ref = lane_->selfdestruct_next; |
435 | lane_->selfdestruct_next = nullptr; | 435 | lane_->selfdestruct_next = nullptr; |
436 | // the terminal shutdown should wait until the lane is done with its lua_close() | 436 | // the terminal shutdown should wait until the lane is done with its lua_close() |
437 | ++lane_->U->selfdestructing_count; | 437 | lane_->U->selfdestructing_count.fetch_add(1, std::memory_order_release); |
438 | found = true; | 438 | found = true; |
439 | break; | 439 | break; |
440 | } | 440 | } |
@@ -526,7 +526,7 @@ static int universe_gc( lua_State* L) | |||
526 | 526 | ||
527 | // If some lanes are currently cleaning after themselves, wait until they are done. | 527 | // If some lanes are currently cleaning after themselves, wait until they are done. |
528 | // They are no longer listed in the selfdestruct chain, but they still have to lua_close(). | 528 | // They are no longer listed in the selfdestruct chain, but they still have to lua_close(). |
529 | while (U->selfdestructing_count > 0) | 529 | while (U->selfdestructing_count.load(std::memory_order_acquire) > 0) |
530 | { | 530 | { |
531 | YIELD(); | 531 | YIELD(); |
532 | } | 532 | } |
@@ -569,7 +569,7 @@ static int universe_gc( lua_State* L) | |||
569 | 569 | ||
570 | // If some lanes are currently cleaning after themselves, wait until they are done. | 570 | // If some lanes are currently cleaning after themselves, wait until they are done. |
571 | // They are no longer listed in the selfdestruct chain, but they still have to lua_close(). | 571 | // They are no longer listed in the selfdestruct chain, but they still have to lua_close(). |
572 | while( U->selfdestructing_count > 0) | 572 | while (U->selfdestructing_count.load(std::memory_order_acquire) > 0) |
573 | { | 573 | { |
574 | YIELD(); | 574 | YIELD(); |
575 | } | 575 | } |
@@ -956,7 +956,7 @@ static THREAD_RETURN_T THREAD_CALLCONV lane_main(void* vs) | |||
956 | 956 | ||
957 | lane->U->selfdestruct_cs.lock(); | 957 | lane->U->selfdestruct_cs.lock(); |
958 | // done with lua_close(), terminal shutdown sequence may proceed | 958 | // done with lua_close(), terminal shutdown sequence may proceed |
959 | --lane->U->selfdestructing_count; | 959 | lane->U->selfdestructing_count.fetch_sub(1, std::memory_order_release); |
960 | lane->U->selfdestruct_cs.unlock(); | 960 | lane->U->selfdestruct_cs.unlock(); |
961 | 961 | ||
962 | delete lane; | 962 | delete lane; |
@@ -1000,13 +1000,13 @@ LUAG_FUNC(require) | |||
1000 | DEBUGSPEW_CODE(Universe* U = universe_get(L)); | 1000 | DEBUGSPEW_CODE(Universe* U = universe_get(L)); |
1001 | STACK_CHECK_START_REL(L, 0); | 1001 | STACK_CHECK_START_REL(L, 0); |
1002 | DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "lanes.require %s BEGIN\n" INDENT_END, name)); | 1002 | DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "lanes.require %s BEGIN\n" INDENT_END, name)); |
1003 | DEBUGSPEW_CODE(++U->debugspew_indent_depth); | 1003 | DEBUGSPEW_CODE(U->debugspew_indent_depth.fetch_add(1, std::memory_order_relaxed)); |
1004 | lua_pushvalue(L, lua_upvalueindex(1)); // "name" require | 1004 | lua_pushvalue(L, lua_upvalueindex(1)); // "name" require |
1005 | lua_insert(L, 1); // require "name" | 1005 | lua_insert(L, 1); // require "name" |
1006 | lua_call(L, nargs, 1); // module | 1006 | lua_call(L, nargs, 1); // module |
1007 | populate_func_lookup_table(L, -1, name); | 1007 | populate_func_lookup_table(L, -1, name); |
1008 | DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "lanes.require %s END\n" INDENT_END, name)); | 1008 | DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "lanes.require %s END\n" INDENT_END, name)); |
1009 | DEBUGSPEW_CODE(--U->debugspew_indent_depth); | 1009 | DEBUGSPEW_CODE(U->debugspew_indent_depth.fetch_sub(1, std::memory_order_relaxed)); |
1010 | STACK_CHECK(L, 0); | 1010 | STACK_CHECK(L, 0); |
1011 | return 1; | 1011 | return 1; |
1012 | } | 1012 | } |
@@ -1026,10 +1026,10 @@ LUAG_FUNC(register) | |||
1026 | DEBUGSPEW_CODE(Universe* U = universe_get(L)); | 1026 | DEBUGSPEW_CODE(Universe* U = universe_get(L)); |
1027 | STACK_CHECK_START_REL(L, 0); // "name" mod_table | 1027 | STACK_CHECK_START_REL(L, 0); // "name" mod_table |
1028 | DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "lanes.register %s BEGIN\n" INDENT_END, name)); | 1028 | DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "lanes.register %s BEGIN\n" INDENT_END, name)); |
1029 | DEBUGSPEW_CODE(++U->debugspew_indent_depth); | 1029 | DEBUGSPEW_CODE(U->debugspew_indent_depth.fetch_add(1, std::memory_order_relaxed)); |
1030 | populate_func_lookup_table(L, -1, name); | 1030 | populate_func_lookup_table(L, -1, name); |
1031 | DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "lanes.register %s END\n" INDENT_END, name)); | 1031 | DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "lanes.register %s END\n" INDENT_END, name)); |
1032 | DEBUGSPEW_CODE(--U->debugspew_indent_depth); | 1032 | DEBUGSPEW_CODE(U->debugspew_indent_depth.fetch_sub(1, std::memory_order_relaxed)); |
1033 | STACK_CHECK(L, 0); | 1033 | STACK_CHECK(L, 0); |
1034 | return 0; | 1034 | return 0; |
1035 | } | 1035 | } |
@@ -1076,7 +1076,7 @@ LUAG_FUNC(lane_new) | |||
1076 | 1076 | ||
1077 | /* --- Create and prepare the sub state --- */ | 1077 | /* --- Create and prepare the sub state --- */ |
1078 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "lane_new: setup\n" INDENT_END)); | 1078 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "lane_new: setup\n" INDENT_END)); |
1079 | DEBUGSPEW_CODE( ++ U->debugspew_indent_depth); | 1079 | DEBUGSPEW_CODE(U->debugspew_indent_depth.fetch_add(1, std::memory_order_relaxed)); |
1080 | 1080 | ||
1081 | // populate with selected libraries at the same time | 1081 | // populate with selected libraries at the same time |
1082 | lua_State* const L2{ luaG_newstate(U, L, libs_str) }; // L // L2 | 1082 | lua_State* const L2{ luaG_newstate(U, L, libs_str) }; // L // L2 |
@@ -1162,6 +1162,7 @@ LUAG_FUNC(lane_new) | |||
1162 | void success() | 1162 | void success() |
1163 | { | 1163 | { |
1164 | prepareUserData(); | 1164 | prepareUserData(); |
1165 | m_lane->m_ready.count_down(); | ||
1165 | m_lane = nullptr; | 1166 | m_lane = nullptr; |
1166 | } | 1167 | } |
1167 | } onExit{ L, lane, gc_cb_idx }; | 1168 | } onExit{ L, lane, gc_cb_idx }; |
@@ -1193,7 +1194,7 @@ LUAG_FUNC(lane_new) | |||
1193 | { | 1194 | { |
1194 | int nbRequired = 1; | 1195 | int nbRequired = 1; |
1195 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "lane_new: require 'required' list\n" INDENT_END)); | 1196 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "lane_new: require 'required' list\n" INDENT_END)); |
1196 | DEBUGSPEW_CODE( ++ U->debugspew_indent_depth); | 1197 | DEBUGSPEW_CODE(U->debugspew_indent_depth.fetch_add(1, std::memory_order_relaxed)); |
1197 | // should not happen, was checked in lanes.lua before calling lane_new() | 1198 | // should not happen, was checked in lanes.lua before calling lane_new() |
1198 | if (lua_type(L, required_idx) != LUA_TTABLE) | 1199 | if (lua_type(L, required_idx) != LUA_TTABLE) |
1199 | { | 1200 | { |
@@ -1238,7 +1239,7 @@ LUAG_FUNC(lane_new) | |||
1238 | lua_pop(L, 1); // func libs priority globals package required gc_cb [... args ...] n | 1239 | lua_pop(L, 1); // func libs priority globals package required gc_cb [... args ...] n |
1239 | ++ nbRequired; | 1240 | ++ nbRequired; |
1240 | } // func libs priority globals package required gc_cb [... args ...] | 1241 | } // func libs priority globals package required gc_cb [... args ...] |
1241 | DEBUGSPEW_CODE( -- U->debugspew_indent_depth); | 1242 | DEBUGSPEW_CODE(U->debugspew_indent_depth.fetch_sub(1, std::memory_order_relaxed)); |
1242 | } | 1243 | } |
1243 | STACK_CHECK(L, 0); | 1244 | STACK_CHECK(L, 0); |
1244 | STACK_CHECK(L2, 0); // | 1245 | STACK_CHECK(L2, 0); // |
@@ -1254,7 +1255,7 @@ LUAG_FUNC(lane_new) | |||
1254 | return luaL_error(L, "Expected table, got %s", luaL_typename(L, globals_idx)); | 1255 | return luaL_error(L, "Expected table, got %s", luaL_typename(L, globals_idx)); |
1255 | } | 1256 | } |
1256 | 1257 | ||
1257 | DEBUGSPEW_CODE( ++ U->debugspew_indent_depth); | 1258 | DEBUGSPEW_CODE(U->debugspew_indent_depth.fetch_add(1, std::memory_order_relaxed)); |
1258 | lua_pushnil(L); // func libs priority globals package required gc_cb [... args ...] nil | 1259 | lua_pushnil(L); // func libs priority globals package required gc_cb [... args ...] nil |
1259 | // Lua 5.2 wants us to push the globals table on the stack | 1260 | // Lua 5.2 wants us to push the globals table on the stack |
1260 | lua_pushglobaltable(L2); // _G | 1261 | lua_pushglobaltable(L2); // _G |
@@ -1267,7 +1268,7 @@ LUAG_FUNC(lane_new) | |||
1267 | } // func libs priority globals package required gc_cb [... args ...] | 1268 | } // func libs priority globals package required gc_cb [... args ...] |
1268 | lua_pop( L2, 1); // | 1269 | lua_pop( L2, 1); // |
1269 | 1270 | ||
1270 | DEBUGSPEW_CODE( -- U->debugspew_indent_depth); | 1271 | DEBUGSPEW_CODE(U->debugspew_indent_depth.fetch_sub(1, std::memory_order_relaxed)); |
1271 | } | 1272 | } |
1272 | STACK_CHECK(L, 0); | 1273 | STACK_CHECK(L, 0); |
1273 | STACK_CHECK(L2, 0); | 1274 | STACK_CHECK(L2, 0); |
@@ -1275,11 +1276,11 @@ LUAG_FUNC(lane_new) | |||
1275 | // Lane main function | 1276 | // Lane main function |
1276 | if (lua_type(L, 1) == LUA_TFUNCTION) | 1277 | if (lua_type(L, 1) == LUA_TFUNCTION) |
1277 | { | 1278 | { |
1278 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "lane_new: transfer lane body\n" INDENT_END)); | 1279 | DEBUGSPEW_CODE(fprintf( stderr, INDENT_BEGIN "lane_new: transfer lane body\n" INDENT_END)); |
1279 | DEBUGSPEW_CODE( ++ U->debugspew_indent_depth); | 1280 | DEBUGSPEW_CODE(U->debugspew_indent_depth.fetch_add(1, std::memory_order_relaxed)); |
1280 | lua_pushvalue(L, 1); // func libs priority globals package required gc_cb [... args ...] func | 1281 | lua_pushvalue(L, 1); // func libs priority globals package required gc_cb [... args ...] func |
1281 | int const res{ luaG_inter_move(U, L, L2, 1, LookupMode::LaneBody) };// func libs priority globals package required gc_cb [... args ...] // func | 1282 | int const res{ luaG_inter_move(U, L, L2, 1, LookupMode::LaneBody) };// func libs priority globals package required gc_cb [... args ...] // func |
1282 | DEBUGSPEW_CODE( -- U->debugspew_indent_depth); | 1283 | DEBUGSPEW_CODE(U->debugspew_indent_depth.fetch_sub(1, std::memory_order_relaxed)); |
1283 | if (res != 0) | 1284 | if (res != 0) |
1284 | { | 1285 | { |
1285 | return luaL_error(L, "tried to copy unsupported types"); | 1286 | return luaL_error(L, "tried to copy unsupported types"); |
@@ -1302,10 +1303,10 @@ LUAG_FUNC(lane_new) | |||
1302 | if (nargs > 0) | 1303 | if (nargs > 0) |
1303 | { | 1304 | { |
1304 | int res; | 1305 | int res; |
1305 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "lane_new: transfer lane arguments\n" INDENT_END)); | 1306 | DEBUGSPEW_CODE(fprintf( stderr, INDENT_BEGIN "lane_new: transfer lane arguments\n" INDENT_END)); |
1306 | DEBUGSPEW_CODE( ++ U->debugspew_indent_depth); | 1307 | DEBUGSPEW_CODE(U->debugspew_indent_depth.fetch_add(1, std::memory_order_relaxed)); |
1307 | res = luaG_inter_move(U, L, L2, nargs, LookupMode::LaneBody); // func libs priority globals package required gc_cb // func [... args ...] | 1308 | res = luaG_inter_move(U, L, L2, nargs, LookupMode::LaneBody); // func libs priority globals package required gc_cb // func [... args ...] |
1308 | DEBUGSPEW_CODE( -- U->debugspew_indent_depth); | 1309 | DEBUGSPEW_CODE(U->debugspew_indent_depth.fetch_sub(1, std::memory_order_relaxed)); |
1309 | if (res != 0) | 1310 | if (res != 0) |
1310 | { | 1311 | { |
1311 | return luaL_error(L, "tried to copy unsupported types"); | 1312 | return luaL_error(L, "tried to copy unsupported types"); |
@@ -1323,8 +1324,7 @@ LUAG_FUNC(lane_new) | |||
1323 | onExit.success(); | 1324 | onExit.success(); |
1324 | // we should have the lane userdata on top of the stack | 1325 | // we should have the lane userdata on top of the stack |
1325 | STACK_CHECK(L, 1); | 1326 | STACK_CHECK(L, 1); |
1326 | lane->m_ready.count_down(); | 1327 | DEBUGSPEW_CODE(U->debugspew_indent_depth.fetch_sub(1, std::memory_order_relaxed)); |
1327 | DEBUGSPEW_CODE(--U->debugspew_indent_depth); | ||
1328 | return 1; | 1328 | return 1; |
1329 | } | 1329 | } |
1330 | 1330 | ||
@@ -1922,13 +1922,13 @@ LUAG_FUNC(configure) | |||
1922 | STACK_GROW(L, 4); | 1922 | STACK_GROW(L, 4); |
1923 | STACK_CHECK_START_ABS(L, 1); // settings | 1923 | STACK_CHECK_START_ABS(L, 1); // settings |
1924 | 1924 | ||
1925 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "%p: lanes.configure() BEGIN\n" INDENT_END, L)); | 1925 | DEBUGSPEW_CODE(fprintf( stderr, INDENT_BEGIN "%p: lanes.configure() BEGIN\n" INDENT_END, L)); |
1926 | DEBUGSPEW_CODE( if (U) ++ U->debugspew_indent_depth); | 1926 | DEBUGSPEW_CODE(if (U) U->debugspew_indent_depth.fetch_add(1, std::memory_order_relaxed)); |
1927 | 1927 | ||
1928 | if(U == nullptr) | 1928 | if(U == nullptr) |
1929 | { | 1929 | { |
1930 | U = universe_create( L); // settings universe | 1930 | U = universe_create( L); // settings universe |
1931 | DEBUGSPEW_CODE( ++ U->debugspew_indent_depth); | 1931 | DEBUGSPEW_CODE(U->debugspew_indent_depth.fetch_add(1, std::memory_order_relaxed)); |
1932 | lua_newtable( L); // settings universe mt | 1932 | lua_newtable( L); // settings universe mt |
1933 | lua_getfield(L, 1, "shutdown_timeout"); // settings universe mt shutdown_timeout | 1933 | lua_getfield(L, 1, "shutdown_timeout"); // settings universe mt shutdown_timeout |
1934 | lua_pushcclosure(L, universe_gc, 1); // settings universe mt universe_gc | 1934 | lua_pushcclosure(L, universe_gc, 1); // settings universe mt universe_gc |
@@ -2070,7 +2070,7 @@ LUAG_FUNC(configure) | |||
2070 | CONFIG_REGKEY.setValue(L, [](lua_State* L) { lua_pushvalue(L, -2); }); | 2070 | CONFIG_REGKEY.setValue(L, [](lua_State* L) { lua_pushvalue(L, -2); }); |
2071 | STACK_CHECK(L, 1); | 2071 | STACK_CHECK(L, 1); |
2072 | DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "%p: lanes.configure() END\n" INDENT_END, L)); | 2072 | DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "%p: lanes.configure() END\n" INDENT_END, L)); |
2073 | DEBUGSPEW_CODE(--U->debugspew_indent_depth); | 2073 | DEBUGSPEW_CODE(U->debugspew_indent_depth.fetch_sub(1, std::memory_order_relaxed)); |
2074 | // Return the settings table | 2074 | // Return the settings table |
2075 | return 1; | 2075 | return 1; |
2076 | } | 2076 | } |
diff --git a/src/macros_and_utils.h b/src/macros_and_utils.h index 31027d6..e29e7fb 100644 --- a/src/macros_and_utils.h +++ b/src/macros_and_utils.h | |||
@@ -18,7 +18,7 @@ extern "C" { | |||
18 | #if USE_DEBUG_SPEW() | 18 | #if USE_DEBUG_SPEW() |
19 | extern char const* debugspew_indent; | 19 | extern char const* debugspew_indent; |
20 | #define INDENT_BEGIN "%.*s " | 20 | #define INDENT_BEGIN "%.*s " |
21 | #define INDENT_END , (U ? U->debugspew_indent_depth : 0), debugspew_indent | 21 | #define INDENT_END , (U ? U->debugspew_indent_depth.load(std::memory_order_relaxed) : 0), debugspew_indent |
22 | #define DEBUGSPEW_CODE(_code) _code | 22 | #define DEBUGSPEW_CODE(_code) _code |
23 | #define DEBUGSPEW_PARAM_COMMA( param_) param_, | 23 | #define DEBUGSPEW_PARAM_COMMA( param_) param_, |
24 | #define DEBUGSPEW_COMMA_PARAM( param_) , param_ | 24 | #define DEBUGSPEW_COMMA_PARAM( param_) , param_ |
diff --git a/src/state.cpp b/src/state.cpp index 55540c8..512009a 100644 --- a/src/state.cpp +++ b/src/state.cpp | |||
@@ -200,8 +200,8 @@ static void copy_one_time_settings( Universe* U, lua_State* L, lua_State* L2) | |||
200 | STACK_CHECK_START_REL(L, 0); | 200 | STACK_CHECK_START_REL(L, 0); |
201 | STACK_CHECK_START_REL(L2, 0); | 201 | STACK_CHECK_START_REL(L2, 0); |
202 | 202 | ||
203 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "copy_one_time_settings()\n" INDENT_END)); | 203 | DEBUGSPEW_CODE(fprintf( stderr, INDENT_BEGIN "copy_one_time_settings()\n" INDENT_END)); |
204 | DEBUGSPEW_CODE( ++ U->debugspew_indent_depth); | 204 | DEBUGSPEW_CODE(U->debugspew_indent_depth.fetch_add(1, std::memory_order_relaxed)); |
205 | 205 | ||
206 | CONFIG_REGKEY.pushValue(L); // config | 206 | CONFIG_REGKEY.pushValue(L); // config |
207 | // copy settings from from source to destination registry | 207 | // copy settings from from source to destination registry |
@@ -213,7 +213,7 @@ static void copy_one_time_settings( Universe* U, lua_State* L, lua_State* L2) | |||
213 | CONFIG_REGKEY.setValue(L2, [](lua_State* L) { lua_insert(L, -2); }); // config | 213 | CONFIG_REGKEY.setValue(L2, [](lua_State* L) { lua_insert(L, -2); }); // config |
214 | STACK_CHECK( L2, 0); | 214 | STACK_CHECK( L2, 0); |
215 | STACK_CHECK( L, 0); | 215 | STACK_CHECK( L, 0); |
216 | DEBUGSPEW_CODE( -- U->debugspew_indent_depth); | 216 | DEBUGSPEW_CODE(U->debugspew_indent_depth.fetch_sub(1, std::memory_order_relaxed)); |
217 | } | 217 | } |
218 | 218 | ||
219 | void initialize_on_state_create( Universe* U, lua_State* L) | 219 | void initialize_on_state_create( Universe* U, lua_State* L) |
@@ -349,8 +349,8 @@ lua_State* luaG_newstate( Universe* U, lua_State* from_, char const* libs_) | |||
349 | return L; | 349 | return L; |
350 | } | 350 | } |
351 | 351 | ||
352 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "luaG_newstate()\n" INDENT_END)); | 352 | DEBUGSPEW_CODE(fprintf( stderr, INDENT_BEGIN "luaG_newstate()\n" INDENT_END)); |
353 | DEBUGSPEW_CODE( ++ U->debugspew_indent_depth); | 353 | DEBUGSPEW_CODE(U->debugspew_indent_depth.fetch_add(1, std::memory_order_relaxed)); |
354 | 354 | ||
355 | // copy settings (for example because it may contain a Lua on_state_create function) | 355 | // copy settings (for example because it may contain a Lua on_state_create function) |
356 | copy_one_time_settings( U, from_, L); | 356 | copy_one_time_settings( U, from_, L); |
@@ -423,22 +423,22 @@ lua_State* luaG_newstate( Universe* U, lua_State* from_, char const* libs_) | |||
423 | 423 | ||
424 | #if 0 && USE_DEBUG_SPEW() | 424 | #if 0 && USE_DEBUG_SPEW() |
425 | // dump the lookup database contents | 425 | // dump the lookup database contents |
426 | lua_getfield( L, LUA_REGISTRYINDEX, LOOKUP_REGKEY); // {} | 426 | lua_getfield(L, LUA_REGISTRYINDEX, LOOKUP_REGKEY); // {} |
427 | lua_pushnil( L); // {} nil | 427 | lua_pushnil(L); // {} nil |
428 | while( lua_next( L, -2)) // {} k v | 428 | while (lua_next(L, -2)) // {} k v |
429 | { | 429 | { |
430 | lua_getglobal( L, "print"); // {} k v print | 430 | lua_getglobal(L, "print"); // {} k v print |
431 | lua_pushlstring( L, debugspew_indent, U->debugspew_indent_depth); // {} k v print " " | 431 | lua_pushlstring(L, debugspew_indent, U->debugspew_indent_depth.load(std::memory_order_relaxed)); // {} k v print " " |
432 | lua_pushvalue( L, -4); // {} k v print " " k | 432 | lua_pushvalue(L, -4); // {} k v print " " k |
433 | lua_pushvalue( L, -4); // {} k v print " " k v | 433 | lua_pushvalue(L, -4); // {} k v print " " k v |
434 | lua_call( L, 3, 0); // {} k v | 434 | lua_call(L, 3, 0); // {} k v |
435 | lua_pop( L, 1); // {} k | 435 | lua_pop(L, 1); // {} k |
436 | } | 436 | } |
437 | lua_pop( L, 1); // {} | 437 | lua_pop(L, 1); // {} |
438 | #endif // USE_DEBUG_SPEW() | 438 | #endif // USE_DEBUG_SPEW() |
439 | 439 | ||
440 | lua_pop( L, 1); | 440 | lua_pop(L, 1); |
441 | STACK_CHECK(L, 0); | 441 | STACK_CHECK(L, 0); |
442 | DEBUGSPEW_CODE(--U->debugspew_indent_depth); | 442 | DEBUGSPEW_CODE(U->debugspew_indent_depth.fetch_sub(1, std::memory_order_relaxed)); |
443 | return L; | 443 | return L; |
444 | } | 444 | } |
diff --git a/src/tools.cpp b/src/tools.cpp index df7602e..ac5f7c5 100644 --- a/src/tools.cpp +++ b/src/tools.cpp | |||
@@ -359,9 +359,9 @@ static void update_lookup_entry( DEBUGSPEW_PARAM_COMMA( Universe* U) lua_State* | |||
359 | 359 | ||
360 | size_t prevNameLength, newNameLength; | 360 | size_t prevNameLength, newNameLength; |
361 | char const* prevName; | 361 | char const* prevName; |
362 | DEBUGSPEW_CODE( char const *newName); | 362 | DEBUGSPEW_CODE(char const *newName); |
363 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "update_lookup_entry()\n" INDENT_END)); | 363 | DEBUGSPEW_CODE(fprintf( stderr, INDENT_BEGIN "update_lookup_entry()\n" INDENT_END)); |
364 | DEBUGSPEW_CODE( ++ U->debugspew_indent_depth); | 364 | DEBUGSPEW_CODE(U->debugspew_indent_depth.fetch_add(1, std::memory_order_relaxed)); |
365 | 365 | ||
366 | STACK_CHECK_START_REL(L, 0); | 366 | STACK_CHECK_START_REL(L, 0); |
367 | // first, raise an error if the function is already known | 367 | // first, raise an error if the function is already known |
@@ -420,8 +420,8 @@ static void update_lookup_entry( DEBUGSPEW_PARAM_COMMA( Universe* U) lua_State* | |||
420 | lua_rawseti( L, fqn, _depth); // ... {bfc} k | 420 | lua_rawseti( L, fqn, _depth); // ... {bfc} k |
421 | } | 421 | } |
422 | -- _depth; | 422 | -- _depth; |
423 | STACK_CHECK( L, -1); | 423 | STACK_CHECK(L, -1); |
424 | DEBUGSPEW_CODE( -- U->debugspew_indent_depth); | 424 | DEBUGSPEW_CODE(U->debugspew_indent_depth.fetch_sub(1, std::memory_order_relaxed)); |
425 | } | 425 | } |
426 | 426 | ||
427 | // ################################################################################################# | 427 | // ################################################################################################# |
@@ -435,8 +435,8 @@ static void populate_func_lookup_table_recur(DEBUGSPEW_PARAM_COMMA(Universe* U) | |||
435 | int const cache = _ctx_base + 2; | 435 | int const cache = _ctx_base + 2; |
436 | // we need to remember subtables to process them after functions encountered at the current depth (breadth-first search) | 436 | // we need to remember subtables to process them after functions encountered at the current depth (breadth-first search) |
437 | int const breadth_first_cache = lua_gettop( L) + 1; | 437 | int const breadth_first_cache = lua_gettop( L) + 1; |
438 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "populate_func_lookup_table_recur()\n" INDENT_END)); | 438 | DEBUGSPEW_CODE(fprintf( stderr, INDENT_BEGIN "populate_func_lookup_table_recur()\n" INDENT_END)); |
439 | DEBUGSPEW_CODE( ++ U->debugspew_indent_depth); | 439 | DEBUGSPEW_CODE(U->debugspew_indent_depth.fetch_add(1, std::memory_order_relaxed)); |
440 | 440 | ||
441 | STACK_GROW( L, 6); | 441 | STACK_GROW( L, 6); |
442 | // slot _i contains a table where we search for functions (or a full userdata with a metatable) | 442 | // slot _i contains a table where we search for functions (or a full userdata with a metatable) |
@@ -457,8 +457,8 @@ static void populate_func_lookup_table_recur(DEBUGSPEW_PARAM_COMMA(Universe* U) | |||
457 | STACK_CHECK( L, 0); | 457 | STACK_CHECK( L, 0); |
458 | if( visit_count > 0) | 458 | if( visit_count > 0) |
459 | { | 459 | { |
460 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "already visited\n" INDENT_END)); | 460 | DEBUGSPEW_CODE(fprintf( stderr, INDENT_BEGIN "already visited\n" INDENT_END)); |
461 | DEBUGSPEW_CODE( -- U->debugspew_indent_depth); | 461 | DEBUGSPEW_CODE(U->debugspew_indent_depth.fetch_sub(1, std::memory_order_relaxed)); |
462 | return; | 462 | return; |
463 | } | 463 | } |
464 | 464 | ||
@@ -513,7 +513,7 @@ static void populate_func_lookup_table_recur(DEBUGSPEW_PARAM_COMMA(Universe* U) | |||
513 | { | 513 | { |
514 | DEBUGSPEW_CODE( char const* key = (lua_type( L, -2) == LUA_TSTRING) ? lua_tostring( L, -2) : "not a string"); | 514 | DEBUGSPEW_CODE( char const* key = (lua_type( L, -2) == LUA_TSTRING) ? lua_tostring( L, -2) : "not a string"); |
515 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "table '%s'\n" INDENT_END, key)); | 515 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "table '%s'\n" INDENT_END, key)); |
516 | DEBUGSPEW_CODE( ++ U->debugspew_indent_depth); | 516 | DEBUGSPEW_CODE(U->debugspew_indent_depth.fetch_add(1, std::memory_order_relaxed)); |
517 | // un-visit this table in case we do need to process it | 517 | // un-visit this table in case we do need to process it |
518 | lua_pushvalue( L, -1); // ... {_i} {bfc} k {} {} | 518 | lua_pushvalue( L, -1); // ... {_i} {bfc} k {} {} |
519 | lua_rawget( L, cache); // ... {_i} {bfc} k {} n | 519 | lua_rawget( L, cache); // ... {_i} {bfc} k {} n |
@@ -536,7 +536,7 @@ static void populate_func_lookup_table_recur(DEBUGSPEW_PARAM_COMMA(Universe* U) | |||
536 | populate_func_lookup_table_recur( DEBUGSPEW_PARAM_COMMA( U) L, _ctx_base, lua_gettop( L), _depth); | 536 | populate_func_lookup_table_recur( DEBUGSPEW_PARAM_COMMA( U) L, _ctx_base, lua_gettop( L), _depth); |
537 | lua_pop( L, 1); // ... {_i} {bfc} k | 537 | lua_pop( L, 1); // ... {_i} {bfc} k |
538 | STACK_CHECK( L, 2); | 538 | STACK_CHECK( L, 2); |
539 | DEBUGSPEW_CODE( -- U->debugspew_indent_depth); | 539 | DEBUGSPEW_CODE(U->debugspew_indent_depth.fetch_sub(1, std::memory_order_relaxed)); |
540 | } | 540 | } |
541 | // remove table name from fqn stack | 541 | // remove table name from fqn stack |
542 | lua_pushnil( L); // ... {_i} {bfc} nil | 542 | lua_pushnil( L); // ... {_i} {bfc} nil |
@@ -546,7 +546,7 @@ static void populate_func_lookup_table_recur(DEBUGSPEW_PARAM_COMMA(Universe* U) | |||
546 | lua_pop( L, 1); // ... {_i} | 546 | lua_pop( L, 1); // ... {_i} |
547 | STACK_CHECK( L, 0); | 547 | STACK_CHECK( L, 0); |
548 | // we are done // ... {_i} {bfc} | 548 | // we are done // ... {_i} {bfc} |
549 | DEBUGSPEW_CODE( -- U->debugspew_indent_depth); | 549 | DEBUGSPEW_CODE(U->debugspew_indent_depth.fetch_sub(1, std::memory_order_relaxed)); |
550 | } | 550 | } |
551 | 551 | ||
552 | // ################################################################################################# | 552 | // ################################################################################################# |
@@ -561,7 +561,7 @@ void populate_func_lookup_table( lua_State* L, int _i, char const* name_) | |||
561 | int start_depth = 0; | 561 | int start_depth = 0; |
562 | DEBUGSPEW_CODE( Universe* U = universe_get( L)); | 562 | DEBUGSPEW_CODE( Universe* U = universe_get( L)); |
563 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "%p: populate_func_lookup_table('%s')\n" INDENT_END, L, name_ ? name_ : "nullptr")); | 563 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "%p: populate_func_lookup_table('%s')\n" INDENT_END, L, name_ ? name_ : "nullptr")); |
564 | DEBUGSPEW_CODE( ++ U->debugspew_indent_depth); | 564 | DEBUGSPEW_CODE(U->debugspew_indent_depth.fetch_add(1, std::memory_order_relaxed)); |
565 | STACK_GROW( L, 3); | 565 | STACK_GROW( L, 3); |
566 | STACK_CHECK_START_REL(L, 0); | 566 | STACK_CHECK_START_REL(L, 0); |
567 | LOOKUP_REGKEY.pushValue(L); // {} | 567 | LOOKUP_REGKEY.pushValue(L); // {} |
@@ -612,7 +612,7 @@ void populate_func_lookup_table( lua_State* L, int _i, char const* name_) | |||
612 | (void) luaL_error( L, "unsupported module type %s", lua_typename( L, lua_type( L, in_base))); | 612 | (void) luaL_error( L, "unsupported module type %s", lua_typename( L, lua_type( L, in_base))); |
613 | } | 613 | } |
614 | STACK_CHECK( L, 0); | 614 | STACK_CHECK( L, 0); |
615 | DEBUGSPEW_CODE( -- U->debugspew_indent_depth); | 615 | DEBUGSPEW_CODE(U->debugspew_indent_depth.fetch_sub(1, std::memory_order_relaxed)); |
616 | } | 616 | } |
617 | 617 | ||
618 | // ################################################################################################# | 618 | // ################################################################################################# |
@@ -1774,10 +1774,10 @@ static bool inter_copy_function(Universe* U, lua_State* L2, int L2_cache_i, lua_ | |||
1774 | } | 1774 | } |
1775 | else // regular function | 1775 | else // regular function |
1776 | { | 1776 | { |
1777 | DEBUGSPEW_CODE( fprintf( stderr, "FUNCTION %s\n", upName_)); | 1777 | DEBUGSPEW_CODE(fprintf( stderr, "FUNCTION %s\n", upName_)); |
1778 | DEBUGSPEW_CODE( ++ U->debugspew_indent_depth); | 1778 | DEBUGSPEW_CODE(U->debugspew_indent_depth.fetch_add(1, std::memory_order_relaxed)); |
1779 | copy_cached_func( U, L2, L2_cache_i, L, source_i_, mode_, upName_); // ... f | 1779 | copy_cached_func( U, L2, L2_cache_i, L, source_i_, mode_, upName_); // ... f |
1780 | DEBUGSPEW_CODE( -- U->debugspew_indent_depth); | 1780 | DEBUGSPEW_CODE(U->debugspew_indent_depth.fetch_sub(1, std::memory_order_relaxed)); |
1781 | } | 1781 | } |
1782 | STACK_CHECK( L2, 1); | 1782 | STACK_CHECK( L2, 1); |
1783 | STACK_CHECK( L, 0); | 1783 | STACK_CHECK( L, 0); |
@@ -1868,7 +1868,7 @@ bool inter_copy_one(Universe* U, lua_State* L2, int L2_cache_i, lua_State* L, in | |||
1868 | STACK_CHECK_START_REL(L2, 0); // L // L2 | 1868 | STACK_CHECK_START_REL(L2, 0); // L // L2 |
1869 | 1869 | ||
1870 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "inter_copy_one()\n" INDENT_END)); | 1870 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "inter_copy_one()\n" INDENT_END)); |
1871 | DEBUGSPEW_CODE( ++ U->debugspew_indent_depth); | 1871 | DEBUGSPEW_CODE(U->debugspew_indent_depth.fetch_add(1, std::memory_order_relaxed)); |
1872 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "%s %s: " INDENT_END, lua_type_names[val_type], vt_names[static_cast<int>(vt_)])); | 1872 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "%s %s: " INDENT_END, lua_type_names[val_type], vt_names[static_cast<int>(vt_)])); |
1873 | 1873 | ||
1874 | // Non-POD can be skipped if its metatable contains { __lanesignore = true } | 1874 | // Non-POD can be skipped if its metatable contains { __lanesignore = true } |
@@ -1967,7 +1967,7 @@ bool inter_copy_one(Universe* U, lua_State* L2, int L2_cache_i, lua_State* L, in | |||
1967 | break; | 1967 | break; |
1968 | } | 1968 | } |
1969 | 1969 | ||
1970 | DEBUGSPEW_CODE( -- U->debugspew_indent_depth); | 1970 | DEBUGSPEW_CODE(U->debugspew_indent_depth.fetch_sub(1, std::memory_order_relaxed)); |
1971 | 1971 | ||
1972 | STACK_CHECK( L2, ret ? 1 : 0); | 1972 | STACK_CHECK( L2, ret ? 1 : 0); |
1973 | STACK_CHECK( L, 0); | 1973 | STACK_CHECK( L, 0); |
@@ -1991,13 +1991,13 @@ int luaG_inter_copy(Universe* U, lua_State* L, lua_State* L2, int n, LookupMode | |||
1991 | bool copyok{ true }; | 1991 | bool copyok{ true }; |
1992 | 1992 | ||
1993 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "luaG_inter_copy()\n" INDENT_END)); | 1993 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "luaG_inter_copy()\n" INDENT_END)); |
1994 | DEBUGSPEW_CODE( ++ U->debugspew_indent_depth); | 1994 | DEBUGSPEW_CODE(U->debugspew_indent_depth.fetch_add(1, std::memory_order_relaxed)); |
1995 | 1995 | ||
1996 | if( n > top_L) | 1996 | if( n > top_L) |
1997 | { | 1997 | { |
1998 | // requesting to copy more than is available? | 1998 | // requesting to copy more than is available? |
1999 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "nothing to copy()\n" INDENT_END)); | 1999 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "nothing to copy()\n" INDENT_END)); |
2000 | DEBUGSPEW_CODE( -- U->debugspew_indent_depth); | 2000 | DEBUGSPEW_CODE(U->debugspew_indent_depth.fetch_sub(1, std::memory_order_relaxed)); |
2001 | return -1; | 2001 | return -1; |
2002 | } | 2002 | } |
2003 | 2003 | ||
@@ -2026,7 +2026,7 @@ int luaG_inter_copy(Universe* U, lua_State* L, lua_State* L2, int n, LookupMode | |||
2026 | } | 2026 | } |
2027 | STACK_CHECK( L, 0); | 2027 | STACK_CHECK( L, 0); |
2028 | 2028 | ||
2029 | DEBUGSPEW_CODE( -- U->debugspew_indent_depth); | 2029 | DEBUGSPEW_CODE(U->debugspew_indent_depth.fetch_sub(1, std::memory_order_relaxed)); |
2030 | 2030 | ||
2031 | if( copyok) | 2031 | if( copyok) |
2032 | { | 2032 | { |
@@ -2051,54 +2051,57 @@ int luaG_inter_move(Universe* U, lua_State* L, lua_State* L2, int n, LookupMode | |||
2051 | return ret; | 2051 | return ret; |
2052 | } | 2052 | } |
2053 | 2053 | ||
2054 | int luaG_inter_copy_package( Universe* U, lua_State* L, lua_State* L2, int package_idx_, LookupMode mode_) | 2054 | int luaG_inter_copy_package(Universe* U, lua_State* L, lua_State* L2, int package_idx_, LookupMode mode_) |
2055 | { | 2055 | { |
2056 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "luaG_inter_copy_package()\n" INDENT_END)); | 2056 | DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "luaG_inter_copy_package()\n" INDENT_END)); |
2057 | DEBUGSPEW_CODE( ++ U->debugspew_indent_depth); | 2057 | DEBUGSPEW_CODE(U->debugspew_indent_depth.fetch_add(1, std::memory_order_relaxed)); |
2058 | // package | 2058 | // package |
2059 | STACK_CHECK_START_REL(L, 0); | 2059 | STACK_CHECK_START_REL(L, 0); |
2060 | STACK_CHECK_START_REL(L2, 0); | 2060 | STACK_CHECK_START_REL(L2, 0); |
2061 | package_idx_ = lua_absindex( L, package_idx_); | 2061 | package_idx_ = lua_absindex(L, package_idx_); |
2062 | if( lua_type( L, package_idx_) != LUA_TTABLE) | 2062 | if (lua_type(L, package_idx_) != LUA_TTABLE) |
2063 | { | 2063 | { |
2064 | lua_pushfstring( L, "expected package as table, got %s", luaL_typename( L, package_idx_)); | 2064 | lua_pushfstring(L, "expected package as table, got %s", luaL_typename(L, package_idx_)); |
2065 | STACK_CHECK( L, 1); | 2065 | STACK_CHECK(L, 1); |
2066 | // raise the error when copying from lane to lane, else just leave it on the stack to be raised later | 2066 | // raise the error when copying from lane to lane, else just leave it on the stack to be raised later |
2067 | return (mode_ == LookupMode::LaneBody) ? lua_error(L) : 1; | 2067 | return (mode_ == LookupMode::LaneBody) ? lua_error(L) : 1; |
2068 | } | 2068 | } |
2069 | lua_getglobal( L2, "package"); | 2069 | lua_getglobal(L2, "package"); |
2070 | if( !lua_isnil( L2, -1)) // package library not loaded: do nothing | 2070 | if (!lua_isnil(L2, -1)) // package library not loaded: do nothing |
2071 | { | 2071 | { |
2072 | int i; | ||
2073 | // package.loaders is renamed package.searchers in Lua 5.2 | 2072 | // package.loaders is renamed package.searchers in Lua 5.2 |
2074 | // but don't copy it anyway, as the function names change depending on the slot index! | 2073 | // but don't copy it anyway, as the function names change depending on the slot index! |
2075 | // users should provide an on_state_create function to setup custom loaders instead | 2074 | // users should provide an on_state_create function to setup custom loaders instead |
2076 | // don't copy package.preload in keeper states (they don't know how to translate functions) | 2075 | // don't copy package.preload in keeper states (they don't know how to translate functions) |
2077 | char const* entries[] = { "path", "cpath", (mode_ == LookupMode::LaneBody) ? "preload" : nullptr /*, (LUA_VERSION_NUM == 501) ? "loaders" : "searchers"*/, nullptr }; | 2076 | char const* entries[] = { "path", "cpath", (mode_ == LookupMode::LaneBody) ? "preload" : nullptr /*, (LUA_VERSION_NUM == 501) ? "loaders" : "searchers"*/, nullptr }; |
2078 | for( i = 0; entries[i]; ++ i) | 2077 | for (char const* const entry : entries) |
2079 | { | 2078 | { |
2080 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "package.%s\n" INDENT_END, entries[i])); | 2079 | if (!entry) |
2081 | lua_getfield( L, package_idx_, entries[i]); | 2080 | { |
2082 | if( lua_isnil( L, -1)) | 2081 | continue; |
2082 | } | ||
2083 | DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "package.%s\n" INDENT_END, entry)); | ||
2084 | lua_getfield(L, package_idx_, entry); | ||
2085 | if (lua_isnil(L, -1)) | ||
2083 | { | 2086 | { |
2084 | lua_pop( L, 1); | 2087 | lua_pop(L, 1); |
2085 | } | 2088 | } |
2086 | else | 2089 | else |
2087 | { | 2090 | { |
2088 | DEBUGSPEW_CODE( ++ U->debugspew_indent_depth); | 2091 | DEBUGSPEW_CODE(U->debugspew_indent_depth.fetch_add(1, std::memory_order_relaxed)); |
2089 | luaG_inter_move( U, L, L2, 1, mode_); // moves the entry to L2 | 2092 | luaG_inter_move(U, L, L2, 1, mode_); // moves the entry to L2 |
2090 | DEBUGSPEW_CODE( -- U->debugspew_indent_depth); | 2093 | DEBUGSPEW_CODE(U->debugspew_indent_depth.fetch_sub(1, std::memory_order_relaxed)); |
2091 | lua_setfield( L2, -2, entries[i]); // set package[entries[i]] | 2094 | lua_setfield(L2, -2, entry); // set package[entry] |
2092 | } | 2095 | } |
2093 | } | 2096 | } |
2094 | } | 2097 | } |
2095 | else | 2098 | else |
2096 | { | 2099 | { |
2097 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "'package' not loaded, nothing to do\n" INDENT_END)); | 2100 | DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "'package' not loaded, nothing to do\n" INDENT_END)); |
2098 | } | 2101 | } |
2099 | lua_pop( L2, 1); | 2102 | lua_pop(L2, 1); |
2100 | STACK_CHECK( L2, 0); | 2103 | STACK_CHECK(L2, 0); |
2101 | STACK_CHECK( L, 0); | 2104 | STACK_CHECK(L, 0); |
2102 | DEBUGSPEW_CODE( -- U->debugspew_indent_depth); | 2105 | DEBUGSPEW_CODE(U->debugspew_indent_depth.fetch_sub(1, std::memory_order_relaxed)); |
2103 | return 0; | 2106 | return 0; |
2104 | } | 2107 | } |
diff --git a/src/universe.h b/src/universe.h index 6a65888..38885cb 100644 --- a/src/universe.h +++ b/src/universe.h | |||
@@ -158,13 +158,13 @@ struct Universe | |||
158 | std::atomic<lua_Integer> next_mt_id{ 1 }; | 158 | std::atomic<lua_Integer> next_mt_id{ 1 }; |
159 | 159 | ||
160 | #if USE_DEBUG_SPEW() | 160 | #if USE_DEBUG_SPEW() |
161 | int debugspew_indent_depth{ 0 }; | 161 | std::atomic<int> debugspew_indent_depth{ 0 }; |
162 | #endif // USE_DEBUG_SPEW() | 162 | #endif // USE_DEBUG_SPEW() |
163 | 163 | ||
164 | Lane* volatile selfdestruct_first{ nullptr }; | 164 | Lane* volatile selfdestruct_first{ nullptr }; |
165 | // After a lane has removed itself from the chain, it still performs some processing. | 165 | // After a lane has removed itself from the chain, it still performs some processing. |
166 | // The terminal desinit sequence should wait for all such processing to terminate before force-killing threads | 166 | // The terminal desinit sequence should wait for all such processing to terminate before force-killing threads |
167 | int volatile selfdestructing_count{ 0 }; | 167 | std::atomic<int> selfdestructing_count{ 0 }; |
168 | }; | 168 | }; |
169 | 169 | ||
170 | // ################################################################################################ | 170 | // ################################################################################################ |