diff options
author | Benoit Germain <benoit.germain@ubisoft.com> | 2024-05-22 18:15:13 +0200 |
---|---|---|
committer | Benoit Germain <benoit.germain@ubisoft.com> | 2024-05-22 18:15:13 +0200 |
commit | d468b693d79ddb416c45669e5ca8400cbdc34e85 (patch) | |
tree | e31876c81dae1e3f8359c129f348ed3511342470 /src | |
parent | 9617dd452e529af3a12b14a98cd2edbfd93ea712 (diff) | |
download | lanes-d468b693d79ddb416c45669e5ca8400cbdc34e85.tar.gz lanes-d468b693d79ddb416c45669e5ca8400cbdc34e85.tar.bz2 lanes-d468b693d79ddb416c45669e5ca8400cbdc34e85.zip |
DEBUGSPEW fprintf(stderr) → std::cerr
Diffstat (limited to 'src')
-rw-r--r-- | src/cancel.cpp | 2 | ||||
-rw-r--r-- | src/compat.h | 9 | ||||
-rw-r--r-- | src/debugspew.h | 19 | ||||
-rw-r--r-- | src/deep.cpp | 4 | ||||
-rw-r--r-- | src/intercopycontext.cpp | 70 | ||||
-rw-r--r-- | src/lane.cpp | 14 | ||||
-rw-r--r-- | src/lanes.cpp | 44 | ||||
-rw-r--r-- | src/state.cpp | 56 | ||||
-rw-r--r-- | src/tools.cpp | 33 | ||||
-rw-r--r-- | src/tools.h | 2 | ||||
-rw-r--r-- | src/universe.cpp | 10 |
11 files changed, 138 insertions, 125 deletions
diff --git a/src/cancel.cpp b/src/cancel.cpp index 2fdd1ef..23d9d04 100644 --- a/src/cancel.cpp +++ b/src/cancel.cpp | |||
@@ -77,7 +77,7 @@ LUAG_FUNC(cancel_test) | |||
77 | 77 | ||
78 | [[nodiscard]] static void cancel_hook(lua_State* L_, [[maybe_unused]] lua_Debug* ar_) | 78 | [[nodiscard]] static void cancel_hook(lua_State* L_, [[maybe_unused]] lua_Debug* ar_) |
79 | { | 79 | { |
80 | DEBUGSPEW_CODE(fprintf(stderr, "cancel_hook\n")); | 80 | DEBUGSPEW_CODE(DebugSpew(nullptr) << "cancel_hook" << std::endl); |
81 | if (cancel_test(L_) != CancelRequest::None) { | 81 | if (cancel_test(L_) != CancelRequest::None) { |
82 | lua_sethook(L_, nullptr, 0, 0); | 82 | lua_sethook(L_, nullptr, 0, 0); |
83 | raise_cancel_error(L_); | 83 | raise_cancel_error(L_); |
diff --git a/src/compat.h b/src/compat.h index f097fb6..e080749 100644 --- a/src/compat.h +++ b/src/compat.h | |||
@@ -247,6 +247,8 @@ LuaType luaG_getmodule(lua_State* L_, char const* name_); | |||
247 | 247 | ||
248 | // ################################################################################################# | 248 | // ################################################################################################# |
249 | 249 | ||
250 | #define STRINGVIEW_FMT "%.*s" | ||
251 | |||
250 | // a replacement of lua_tolstring | 252 | // a replacement of lua_tolstring |
251 | [[nodiscard]] inline std::string_view lua_tostringview(lua_State* L_, int idx_) | 253 | [[nodiscard]] inline std::string_view lua_tostringview(lua_State* L_, int idx_) |
252 | { | 254 | { |
@@ -255,6 +257,13 @@ LuaType luaG_getmodule(lua_State* L_, char const* name_); | |||
255 | return std::string_view{ _str, _len }; | 257 | return std::string_view{ _str, _len }; |
256 | } | 258 | } |
257 | 259 | ||
260 | [[nodiscard]] inline std::string_view luaL_checkstringview(lua_State* L_, int idx_) | ||
261 | { | ||
262 | size_t _len{ 0 }; | ||
263 | char const* _str{ luaL_checklstring(L_, idx_, &_len) }; | ||
264 | return std::string_view{ _str, _len }; | ||
265 | } | ||
266 | |||
258 | [[nodiscard]] inline std::string_view lua_pushstringview(lua_State* L_, std::string_view const& str_) | 267 | [[nodiscard]] inline std::string_view lua_pushstringview(lua_State* L_, std::string_view const& str_) |
259 | { | 268 | { |
260 | #if LUA_VERSION_NUM == 501 | 269 | #if LUA_VERSION_NUM == 501 |
diff --git a/src/debugspew.h b/src/debugspew.h index 0c3e14a..216f617 100644 --- a/src/debugspew.h +++ b/src/debugspew.h | |||
@@ -3,6 +3,8 @@ | |||
3 | #include "lanesconf.h" | 3 | #include "lanesconf.h" |
4 | #include "universe.h" | 4 | #include "universe.h" |
5 | 5 | ||
6 | #include <iostream> | ||
7 | |||
6 | // ################################################################################################# | 8 | // ################################################################################################# |
7 | 9 | ||
8 | #if USE_DEBUG_SPEW() | 10 | #if USE_DEBUG_SPEW() |
@@ -10,7 +12,7 @@ | |||
10 | class DebugSpewIndentScope | 12 | class DebugSpewIndentScope |
11 | { | 13 | { |
12 | private: | 14 | private: |
13 | Universe* const U; | 15 | Universe* const U{}; |
14 | 16 | ||
15 | public: | 17 | public: |
16 | static char const* const debugspew_indent; | 18 | static char const* const debugspew_indent; |
@@ -18,21 +20,28 @@ class DebugSpewIndentScope | |||
18 | DebugSpewIndentScope(Universe* U_) | 20 | DebugSpewIndentScope(Universe* U_) |
19 | : U{ U_ } | 21 | : U{ U_ } |
20 | { | 22 | { |
21 | if (U) | 23 | if (U) { |
22 | U->debugspewIndentDepth.fetch_add(1, std::memory_order_relaxed); | 24 | U->debugspewIndentDepth.fetch_add(1, std::memory_order_relaxed); |
25 | } | ||
23 | } | 26 | } |
24 | 27 | ||
25 | ~DebugSpewIndentScope() | 28 | ~DebugSpewIndentScope() |
26 | { | 29 | { |
27 | if (U) | 30 | if (U) { |
28 | U->debugspewIndentDepth.fetch_sub(1, std::memory_order_relaxed); | 31 | U->debugspewIndentDepth.fetch_sub(1, std::memory_order_relaxed); |
32 | } | ||
29 | } | 33 | } |
30 | }; | 34 | }; |
31 | 35 | ||
32 | // ################################################################################################# | 36 | // ################################################################################################# |
33 | 37 | ||
34 | #define INDENT_BEGIN "%.*s " | 38 | inline auto& DebugSpew(Universe const* const U_) |
35 | #define INDENT_END(U_) , (U_ ? U_->debugspewIndentDepth.load(std::memory_order_relaxed) : 0), DebugSpewIndentScope::debugspew_indent | 39 | { |
40 | if (!U_) { | ||
41 | return std::cerr; | ||
42 | } | ||
43 | return std::cerr << std::string_view{ DebugSpewIndentScope::debugspew_indent, static_cast<size_t>(U_->debugspewIndentDepth.load(std::memory_order_relaxed)) } << " "; | ||
44 | } | ||
36 | #define DEBUGSPEW_CODE(_code) _code | 45 | #define DEBUGSPEW_CODE(_code) _code |
37 | #define DEBUGSPEW_OR_NOT(a_, b_) a_ | 46 | #define DEBUGSPEW_OR_NOT(a_, b_) a_ |
38 | #define DEBUGSPEW_PARAM_COMMA(param_) param_, | 47 | #define DEBUGSPEW_PARAM_COMMA(param_) param_, |
diff --git a/src/deep.cpp b/src/deep.cpp index f23f0be..a39e0f8 100644 --- a/src/deep.cpp +++ b/src/deep.cpp | |||
@@ -249,7 +249,7 @@ std::string_view DeepFactory::PushDeepProxy(DestState L_, DeepPrelude* prelude_, | |||
249 | lua_getglobal(L_, "require"); // L_: DPC proxy metatable require() | 249 | lua_getglobal(L_, "require"); // L_: DPC proxy metatable require() |
250 | // check that the module is already loaded (or being loaded, we are happy either way) | 250 | // check that the module is already loaded (or being loaded, we are happy either way) |
251 | if (lua_isfunction(L_, -1)) { | 251 | if (lua_isfunction(L_, -1)) { |
252 | lua_pushlstring(L_, _modname.data(), _modname.size()); // L_: DPC proxy metatable require() "module" | 252 | std::ignore = lua_pushstringview(L_, _modname); // L_: DPC proxy metatable require() "module" |
253 | if (luaG_getfield(L_, LUA_REGISTRYINDEX, LUA_LOADED_TABLE) == LuaType::TABLE) { // L_: DPC proxy metatable require() "module" _R._LOADED | 253 | if (luaG_getfield(L_, LUA_REGISTRYINDEX, LUA_LOADED_TABLE) == LuaType::TABLE) { // L_: DPC proxy metatable require() "module" _R._LOADED |
254 | lua_pushvalue(L_, -2); // L_: DPC proxy metatable require() "module" _R._LOADED "module" | 254 | lua_pushvalue(L_, -2); // L_: DPC proxy metatable require() "module" _R._LOADED "module" |
255 | lua_rawget(L_, -2); // L_: DPC proxy metatable require() "module" _R._LOADED module | 255 | lua_rawget(L_, -2); // L_: DPC proxy metatable require() "module" _R._LOADED module |
@@ -260,7 +260,7 @@ std::string_view DeepFactory::PushDeepProxy(DestState L_, DeepPrelude* prelude_, | |||
260 | LuaError const _require_result{ lua_pcall(L_, 1, 0, 0) }; // L_: DPC proxy metatable error? | 260 | LuaError const _require_result{ lua_pcall(L_, 1, 0, 0) }; // L_: DPC proxy metatable error? |
261 | if (_require_result != LuaError::OK) { | 261 | if (_require_result != LuaError::OK) { |
262 | // failed, return the error message | 262 | // failed, return the error message |
263 | lua_pushfstring(L_, "error while requiring '%s' identified by DeepFactory::moduleName: ", _modname.data()); | 263 | lua_pushfstring(L_, "error while requiring '" STRINGVIEW_FMT "' identified by DeepFactory::moduleName: ", _modname.size(), _modname.data()); |
264 | lua_insert(L_, -2); // L_: DPC proxy metatable prefix error | 264 | lua_insert(L_, -2); // L_: DPC proxy metatable prefix error |
265 | lua_concat(L_, 2); // L_: DPC proxy metatable error | 265 | lua_concat(L_, 2); // L_: DPC proxy metatable error |
266 | return lua_tostringview(L_, -1); | 266 | return lua_tostringview(L_, -1); |
diff --git a/src/intercopycontext.cpp b/src/intercopycontext.cpp index 6ebbbb0..6623b16 100644 --- a/src/intercopycontext.cpp +++ b/src/intercopycontext.cpp | |||
@@ -98,8 +98,7 @@ THE SOFTWARE. | |||
98 | lua_rawget(L1, -2); // L1: ... v ... {} "f.q.n" | 98 | lua_rawget(L1, -2); // L1: ... v ... {} "f.q.n" |
99 | } | 99 | } |
100 | std::string_view _fqn{ lua_tostringview(L1, -1) }; | 100 | std::string_view _fqn{ lua_tostringview(L1, -1) }; |
101 | DEBUGSPEW_CODE(Universe* const _U = universe_get(L1)); | 101 | DEBUGSPEW_CODE(DebugSpew(universe_get(L1)) << "function [C] " << _fqn << std::endl); |
102 | DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "function [C] %s \n" INDENT_END(_U), _fqn.data())); | ||
103 | // popping doesn't invalidate the pointer since this is an interned string gotten from the lookup database | 102 | // popping doesn't invalidate the pointer since this is an interned string gotten from the lookup database |
104 | lua_pop(L1, (mode == LookupMode::FromKeeper) ? 1 : 2); // L1: ... v ... | 103 | lua_pop(L1, (mode == LookupMode::FromKeeper) ? 1 : 2); // L1: ... v ... |
105 | STACK_CHECK(L1, 0); | 104 | STACK_CHECK(L1, 0); |
@@ -220,7 +219,7 @@ void InterCopyContext::copy_func() const | |||
220 | // fills 'fname' 'namewhat' and 'linedefined', pops function | 219 | // fills 'fname' 'namewhat' and 'linedefined', pops function |
221 | lua_getinfo(L1, ">nS", &_ar); // L1: ... b | 220 | lua_getinfo(L1, ">nS", &_ar); // L1: ... b |
222 | _fname = _ar.namewhat; | 221 | _fname = _ar.namewhat; |
223 | DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "FNAME: %s @ %d" INDENT_END(U), _ar.short_src, _ar.linedefined)); // just gives nullptr | 222 | DEBUGSPEW_CODE(DebugSpew(U) << "FNAME: " << _ar.short_src << " @ " << _ar.linedefined << std::endl); |
224 | } | 223 | } |
225 | #endif // LOG_FUNC_INFO | 224 | #endif // LOG_FUNC_INFO |
226 | { | 225 | { |
@@ -267,15 +266,15 @@ void InterCopyContext::copy_func() const | |||
267 | lua_pushglobaltable(L1); // L1: ... _G | 266 | lua_pushglobaltable(L1); // L1: ... _G |
268 | #endif // LUA_VERSION_NUM | 267 | #endif // LUA_VERSION_NUM |
269 | for (_n = 0; (_c.name = lua_getupvalue(L1, L1_i, 1 + _n)) != nullptr; ++_n) { // L1: ... _G up[n] | 268 | for (_n = 0; (_c.name = lua_getupvalue(L1, L1_i, 1 + _n)) != nullptr; ++_n) { // L1: ... _G up[n] |
270 | DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "UPNAME[%d]: %s -> " INDENT_END(U), _n, _c.name)); | 269 | DEBUGSPEW_CODE(DebugSpew(U) << "UPNAME[" << _n << "]: " << _c.name << " -> "); |
271 | #if LUA_VERSION_NUM >= 502 | 270 | #if LUA_VERSION_NUM >= 502 |
272 | if (lua_rawequal(L1, -1, -2)) { // is the upvalue equal to the global table? | 271 | if (lua_rawequal(L1, -1, -2)) { // is the upvalue equal to the global table? |
273 | DEBUGSPEW_CODE(fprintf(stderr, "pushing destination global scope\n")); | 272 | DEBUGSPEW_CODE(DebugSpew(nullptr) << "pushing destination global scope" << std::endl); |
274 | lua_pushglobaltable(L2); // L2: ... {cache} ... function <upvalues> | 273 | lua_pushglobaltable(L2); // L2: ... {cache} ... function <upvalues> |
275 | } else | 274 | } else |
276 | #endif // LUA_VERSION_NUM | 275 | #endif // LUA_VERSION_NUM |
277 | { | 276 | { |
278 | DEBUGSPEW_CODE(fprintf(stderr, "copying value\n")); | 277 | DEBUGSPEW_CODE(DebugSpew(nullptr) << "copying value" << std::endl); |
279 | _c.L1_i = SourceIndex{ lua_gettop(L1) }; | 278 | _c.L1_i = SourceIndex{ lua_gettop(L1) }; |
280 | if (!_c.inter_copy_one()) { // L2: ... {cache} ... function <upvalues> | 279 | if (!_c.inter_copy_one()) { // L2: ... {cache} ... function <upvalues> |
281 | raise_luaL_error(getErrL(), "Cannot copy upvalue type '%s'", luaL_typename(L1, -1)); | 280 | raise_luaL_error(getErrL(), "Cannot copy upvalue type '%s'", luaL_typename(L1, -1)); |
@@ -323,7 +322,7 @@ void InterCopyContext::lookup_native_func() const | |||
323 | 322 | ||
324 | case LookupMode::ToKeeper: | 323 | case LookupMode::ToKeeper: |
325 | // push a sentinel closure that holds the lookup name as upvalue | 324 | // push a sentinel closure that holds the lookup name as upvalue |
326 | lua_pushlstring(L2, _fqn.data(), _fqn.size()); // L1: ... f ... L2: "f.q.n" | 325 | std::ignore = lua_pushstringview(L2, _fqn); // L1: ... f ... L2: "f.q.n" |
327 | lua_pushcclosure(L2, func_lookup_sentinel, 1); // L1: ... f ... L2: f | 326 | lua_pushcclosure(L2, func_lookup_sentinel, 1); // L1: ... f ... L2: f |
328 | break; | 327 | break; |
329 | 328 | ||
@@ -332,7 +331,7 @@ void InterCopyContext::lookup_native_func() const | |||
332 | kLookupRegKey.pushValue(L2); // L1: ... f ... L2: {} | 331 | kLookupRegKey.pushValue(L2); // L1: ... f ... L2: {} |
333 | STACK_CHECK(L2, 1); | 332 | STACK_CHECK(L2, 1); |
334 | LUA_ASSERT(L1, lua_istable(L2, -1)); | 333 | LUA_ASSERT(L1, lua_istable(L2, -1)); |
335 | lua_pushlstring(L2, _fqn.data(), _fqn.size()); // L1: ... f ... L2: {} "f.q.n" | 334 | std::ignore = lua_pushstringview(L2, _fqn); // L1: ... f ... L2: {} "f.q.n" |
336 | lua_rawget(L2, -2); // L1: ... f ... L2: {} f | 335 | lua_rawget(L2, -2); // L1: ... f ... L2: {} f |
337 | // nil means we don't know how to transfer stuff: user should do something | 336 | // nil means we don't know how to transfer stuff: user should do something |
338 | // anything other than function or table should not happen! | 337 | // anything other than function or table should not happen! |
@@ -342,14 +341,14 @@ void InterCopyContext::lookup_native_func() const | |||
342 | lua_pop(L1, 1); // L1: ... f ... | 341 | lua_pop(L1, 1); // L1: ... f ... |
343 | lua_getglobal(L2, "decoda_name"); // L1: ... f ... L2: {} f decoda_name | 342 | lua_getglobal(L2, "decoda_name"); // L1: ... f ... L2: {} f decoda_name |
344 | char const* const _to{ lua_tostring(L2, -1) }; | 343 | char const* const _to{ lua_tostring(L2, -1) }; |
345 | lua_pop(L2, 1); // L2: {} f | 344 | lua_pop(L2, 1); // L2: {} f |
346 | // when mode_ == LookupMode::FromKeeper, L is a keeper state and L2 is not, therefore L2 is the state where we want to raise the error | 345 | // when mode_ == LookupMode::FromKeeper, L is a keeper state and L2 is not, therefore L2 is the state where we want to raise the error |
347 | raise_luaL_error( | 346 | raise_luaL_error( |
348 | getErrL(), | 347 | getErrL(), |
349 | "%s%s: function '%s' not found in %s destination transfer database.", | 348 | "%s%s: function '" STRINGVIEW_FMT "' not found in %s destination transfer database.", |
350 | lua_isnil(L2, -1) ? "" : "INTERNAL ERROR IN ", | 349 | lua_isnil(L2, -1) ? "" : "INTERNAL ERROR IN ", |
351 | _from ? _from : "main", | 350 | _from ? _from : "main", |
352 | _fqn.data(), | 351 | _fqn.size(), _fqn.data(), |
353 | _to ? _to : "main"); | 352 | _to ? _to : "main"); |
354 | return; | 353 | return; |
355 | } | 354 | } |
@@ -398,7 +397,7 @@ void InterCopyContext::copy_cached_func() const | |||
398 | // push a light userdata uniquely representing the function | 397 | // push a light userdata uniquely representing the function |
399 | lua_pushlightuserdata(L2, _aspointer); // L2: ... {cache} ... p | 398 | lua_pushlightuserdata(L2, _aspointer); // L2: ... {cache} ... p |
400 | 399 | ||
401 | // fprintf( stderr, "<< ID: %s >>\n", lua_tostring( L2, -1)); | 400 | //DEBUGSPEW_CODE(DebugSpew(U) << "<< ID: " << lua_tostringview(L2, -1) << " >>" << std::endl); |
402 | 401 | ||
403 | lua_pushvalue(L2, -1); // L2: ... {cache} ... p p | 402 | lua_pushvalue(L2, -1); // L2: ... {cache} ... p p |
404 | lua_rawget(L2, L2_cache_i); // L2: ... {cache} ... p function|nil|true | 403 | lua_rawget(L2, L2_cache_i); // L2: ... {cache} ... p function|nil|true |
@@ -443,7 +442,7 @@ void InterCopyContext::copy_cached_func() const | |||
443 | 442 | ||
444 | case LookupMode::ToKeeper: | 443 | case LookupMode::ToKeeper: |
445 | // push a sentinel closure that holds the lookup name as upvalue | 444 | // push a sentinel closure that holds the lookup name as upvalue |
446 | lua_pushlstring(L2, _fqn.data(), _fqn.size()); // L1: ... t ... L2: "f.q.n" | 445 | std::ignore = lua_pushstringview(L2, _fqn); // L1: ... t ... L2: "f.q.n" |
447 | lua_pushcclosure(L2, table_lookup_sentinel, 1); // L1: ... t ... L2: f | 446 | lua_pushcclosure(L2, table_lookup_sentinel, 1); // L1: ... t ... L2: f |
448 | break; | 447 | break; |
449 | 448 | ||
@@ -452,7 +451,7 @@ void InterCopyContext::copy_cached_func() const | |||
452 | kLookupRegKey.pushValue(L2); // L1: ... t ... L2: {} | 451 | kLookupRegKey.pushValue(L2); // L1: ... t ... L2: {} |
453 | STACK_CHECK(L2, 1); | 452 | STACK_CHECK(L2, 1); |
454 | LUA_ASSERT(L1, lua_istable(L2, -1)); | 453 | LUA_ASSERT(L1, lua_istable(L2, -1)); |
455 | lua_pushlstring(L2, _fqn.data(), _fqn.size()); // L2: {} "f.q.n" | 454 | std::ignore = lua_pushstringview(L2, _fqn); // L2: {} "f.q.n" |
456 | lua_rawget(L2, -2); // L2: {} t | 455 | lua_rawget(L2, -2); // L2: {} t |
457 | // we accept destination lookup failures in the case of transfering the Lanes body function (this will result in the source table being cloned instead) | 456 | // we accept destination lookup failures in the case of transfering the Lanes body function (this will result in the source table being cloned instead) |
458 | // but not when we extract something out of a keeper, as there is nothing to clone! | 457 | // but not when we extract something out of a keeper, as there is nothing to clone! |
@@ -505,7 +504,7 @@ void InterCopyContext::inter_copy_keyvaluepair() const | |||
505 | std::string_view const _key{ lua_tostringview(L1, _key_i) }; | 504 | std::string_view const _key{ lua_tostringview(L1, _key_i) }; |
506 | size_t const _bufLen{ strlen(name) + _key.size() + 2 }; // +2 for separator dot and terminating 0 | 505 | size_t const _bufLen{ strlen(name) + _key.size() + 2 }; // +2 for separator dot and terminating 0 |
507 | _valPath = static_cast<char*>(alloca(_bufLen)); | 506 | _valPath = static_cast<char*>(alloca(_bufLen)); |
508 | sprintf(_valPath, "%s.%*s", name, static_cast<int>(_key.size()), _key.data()); | 507 | sprintf(_valPath, "%s." STRINGVIEW_FMT, name, (int) _key.size(), _key.data()); |
509 | } | 508 | } |
510 | #if defined LUA_LNUM || LUA_VERSION_NUM >= 503 | 509 | #if defined LUA_LNUM || LUA_VERSION_NUM >= 503 |
511 | else if (lua_isinteger(L1, _key_i)) { | 510 | else if (lua_isinteger(L1, _key_i)) { |
@@ -607,7 +606,7 @@ void InterCopyContext::inter_copy_keyvaluepair() const | |||
607 | // push a light userdata uniquely representing the table | 606 | // push a light userdata uniquely representing the table |
608 | lua_pushlightuserdata(L2, const_cast<void*>(_p)); // L1: ... t ... L2: ... p | 607 | lua_pushlightuserdata(L2, const_cast<void*>(_p)); // L1: ... t ... L2: ... p |
609 | 608 | ||
610 | // fprintf(stderr, "<< ID: %s >>\n", lua_tostring(L2, -1)); | 609 | //DEBUGSPEW_CODE(DebugSpew(U) << "<< ID: " << lua_tostringview(L2, -1) << " >>" << std::endl); |
611 | 610 | ||
612 | lua_rawget(L2, L2_cache_i); // L1: ... t ... L2: ... {cached|nil} | 611 | lua_rawget(L2, L2_cache_i); // L1: ... t ... L2: ... {cached|nil} |
613 | bool const _not_found_in_cache{ lua_isnil(L2, -1) }; | 612 | bool const _not_found_in_cache{ lua_isnil(L2, -1) }; |
@@ -783,7 +782,7 @@ void InterCopyContext::inter_copy_keyvaluepair() const | |||
783 | [[nodiscard]] bool InterCopyContext::inter_copy_boolean() const | 782 | [[nodiscard]] bool InterCopyContext::inter_copy_boolean() const |
784 | { | 783 | { |
785 | int const _v{ lua_toboolean(L1, L1_i) }; | 784 | int const _v{ lua_toboolean(L1, L1_i) }; |
786 | DEBUGSPEW_CODE(fprintf(stderr, "%s\n", _v ? "true" : "false")); | 785 | DEBUGSPEW_CODE(DebugSpew(nullptr) << (_v ? "true" : "false") << std::endl); |
787 | lua_pushboolean(L2, _v); | 786 | lua_pushboolean(L2, _v); |
788 | return true; | 787 | return true; |
789 | } | 788 | } |
@@ -798,7 +797,7 @@ void InterCopyContext::inter_copy_keyvaluepair() const | |||
798 | 797 | ||
799 | STACK_CHECK_START_REL(L1, 0); | 798 | STACK_CHECK_START_REL(L1, 0); |
800 | STACK_CHECK_START_REL(L2, 0); | 799 | STACK_CHECK_START_REL(L2, 0); |
801 | DEBUGSPEW_CODE(fprintf(stderr, "FUNCTION %s\n", name)); | 800 | DEBUGSPEW_CODE(DebugSpew(nullptr) << "FUNCTION " << name << std::endl); |
802 | 801 | ||
803 | if (lua_tocfunction(L1, L1_i) == userdata_clone_sentinel) { // we are actually copying a clonable full userdata from a keeper | 802 | if (lua_tocfunction(L1, L1_i) == userdata_clone_sentinel) { // we are actually copying a clonable full userdata from a keeper |
804 | // clone the full userdata again | 803 | // clone the full userdata again |
@@ -873,9 +872,9 @@ void InterCopyContext::inter_copy_keyvaluepair() const | |||
873 | // clone:__lanesclone(dest, source, size) | 872 | // clone:__lanesclone(dest, source, size) |
874 | lua_call(L2, 3, 0); // L2: ... u | 873 | lua_call(L2, 3, 0); // L2: ... u |
875 | } else { // regular function | 874 | } else { // regular function |
876 | DEBUGSPEW_CODE(fprintf(stderr, "FUNCTION %s\n", name)); | 875 | DEBUGSPEW_CODE(DebugSpew(U) << "FUNCTION " << name << std::endl); |
877 | DEBUGSPEW_CODE(DebugSpewIndentScope _scope{ U }); | 876 | DEBUGSPEW_CODE(DebugSpewIndentScope _scope{ U }); |
878 | copy_cached_func(); // L2: ... f | 877 | copy_cached_func(); // L2: ... f |
879 | } | 878 | } |
880 | STACK_CHECK(L2, 1); | 879 | STACK_CHECK(L2, 1); |
881 | STACK_CHECK(L1, 0); | 880 | STACK_CHECK(L1, 0); |
@@ -887,7 +886,8 @@ void InterCopyContext::inter_copy_keyvaluepair() const | |||
887 | [[nodiscard]] bool InterCopyContext::inter_copy_lightuserdata() const | 886 | [[nodiscard]] bool InterCopyContext::inter_copy_lightuserdata() const |
888 | { | 887 | { |
889 | void* const _p{ lua_touserdata(L1, L1_i) }; | 888 | void* const _p{ lua_touserdata(L1, L1_i) }; |
890 | DEBUGSPEW_CODE(fprintf(stderr, "%p\n", _p)); | 889 | // TODO: recognize and print known UniqueKey names here |
890 | DEBUGSPEW_CODE(DebugSpew(nullptr) << _p << std::endl); | ||
891 | // when copying a nil sentinel in a non-keeper, write a nil in the destination | 891 | // when copying a nil sentinel in a non-keeper, write a nil in the destination |
892 | if (mode != LookupMode::ToKeeper && kNilSentinel.equals(L1, L1_i)) { | 892 | if (mode != LookupMode::ToKeeper && kNilSentinel.equals(L1, L1_i)) { |
893 | lua_pushnil(L2); | 893 | lua_pushnil(L2); |
@@ -921,13 +921,13 @@ void InterCopyContext::inter_copy_keyvaluepair() const | |||
921 | #if defined LUA_LNUM || LUA_VERSION_NUM >= 503 | 921 | #if defined LUA_LNUM || LUA_VERSION_NUM >= 503 |
922 | if (lua_isinteger(L1, L1_i)) { | 922 | if (lua_isinteger(L1, L1_i)) { |
923 | lua_Integer const _v{ lua_tointeger(L1, L1_i) }; | 923 | lua_Integer const _v{ lua_tointeger(L1, L1_i) }; |
924 | DEBUGSPEW_CODE(fprintf(stderr, LUA_INTEGER_FMT "\n", _v)); | 924 | DEBUGSPEW_CODE(DebugSpew(nullptr) << _v << std::endl); |
925 | lua_pushinteger(L2, _v); | 925 | lua_pushinteger(L2, _v); |
926 | } else | 926 | } else |
927 | #endif // defined LUA_LNUM || LUA_VERSION_NUM >= 503 | 927 | #endif // defined LUA_LNUM || LUA_VERSION_NUM >= 503 |
928 | { | 928 | { |
929 | lua_Number const _v{ lua_tonumber(L1, L1_i) }; | 929 | lua_Number const _v{ lua_tonumber(L1, L1_i) }; |
930 | DEBUGSPEW_CODE(fprintf(stderr, LUA_NUMBER_FMT "\n", _v)); | 930 | DEBUGSPEW_CODE(DebugSpew(nullptr) << _v << std::endl); |
931 | lua_pushnumber(L2, _v); | 931 | lua_pushnumber(L2, _v); |
932 | } | 932 | } |
933 | return true; | 933 | return true; |
@@ -938,8 +938,8 @@ void InterCopyContext::inter_copy_keyvaluepair() const | |||
938 | [[nodiscard]] bool InterCopyContext::inter_copy_string() const | 938 | [[nodiscard]] bool InterCopyContext::inter_copy_string() const |
939 | { | 939 | { |
940 | std::string_view const _s{ lua_tostringview(L1, L1_i) }; | 940 | std::string_view const _s{ lua_tostringview(L1, L1_i) }; |
941 | DEBUGSPEW_CODE(fprintf(stderr, "'%s'\n", _s.data())); | 941 | DEBUGSPEW_CODE(DebugSpew(nullptr) << "'" << _s << "'" << std::endl); |
942 | lua_pushlstring(L2, _s.data(), _s.size()); | 942 | std::ignore = lua_pushstringview(L2, _s); |
943 | return true; | 943 | return true; |
944 | } | 944 | } |
945 | 945 | ||
@@ -953,7 +953,7 @@ void InterCopyContext::inter_copy_keyvaluepair() const | |||
953 | 953 | ||
954 | STACK_CHECK_START_REL(L1, 0); | 954 | STACK_CHECK_START_REL(L1, 0); |
955 | STACK_CHECK_START_REL(L2, 0); | 955 | STACK_CHECK_START_REL(L2, 0); |
956 | DEBUGSPEW_CODE(fprintf(stderr, "TABLE %s\n", name)); | 956 | DEBUGSPEW_CODE(DebugSpew(nullptr) << "TABLE " << name << std::endl); |
957 | 957 | ||
958 | /* | 958 | /* |
959 | * First, let's try to see if this table is special (aka is it some table that we registered in our lookup databases during module registration?) | 959 | * First, let's try to see if this table is special (aka is it some table that we registered in our lookup databases during module registration?) |
@@ -1021,7 +1021,7 @@ void InterCopyContext::inter_copy_keyvaluepair() const | |||
1021 | STACK_CHECK(L2, 0); | 1021 | STACK_CHECK(L2, 0); |
1022 | 1022 | ||
1023 | // Allow only deep userdata entities to be copied across | 1023 | // Allow only deep userdata entities to be copied across |
1024 | DEBUGSPEW_CODE(fprintf(stderr, "USERDATA\n")); | 1024 | DEBUGSPEW_CODE(DebugSpew(nullptr) << "USERDATA" << std::endl); |
1025 | if (tryCopyDeep()) { | 1025 | if (tryCopyDeep()) { |
1026 | STACK_CHECK(L1, 0); | 1026 | STACK_CHECK(L1, 0); |
1027 | STACK_CHECK(L2, 1); | 1027 | STACK_CHECK(L2, 1); |
@@ -1084,18 +1084,18 @@ static char const* vt_names[] = { | |||
1084 | STACK_CHECK_START_REL(L1, 0); | 1084 | STACK_CHECK_START_REL(L1, 0); |
1085 | STACK_CHECK_START_REL(L2, 0); | 1085 | STACK_CHECK_START_REL(L2, 0); |
1086 | 1086 | ||
1087 | DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "inter_copy_one()\n" INDENT_END(U))); | 1087 | DEBUGSPEW_CODE(DebugSpew(U) << "inter_copy_one()" << std::endl); |
1088 | DEBUGSPEW_CODE(DebugSpewIndentScope _scope{ U }); | 1088 | DEBUGSPEW_CODE(DebugSpewIndentScope _scope{ U }); |
1089 | 1089 | ||
1090 | LuaType _val_type{ lua_type_as_enum(L1, L1_i) }; | 1090 | LuaType _val_type{ lua_type_as_enum(L1, L1_i) }; |
1091 | DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "%s %s: " INDENT_END(U), lua_type_names[static_cast<int>(_val_type)], vt_names[static_cast<int>(vt)])); | 1091 | DEBUGSPEW_CODE(DebugSpew(U) << lua_type_names[static_cast<int>(_val_type)] << " " << vt_names[static_cast<int>(vt)] << ": "); |
1092 | 1092 | ||
1093 | // Non-POD can be skipped if its metatable contains { __lanesignore = true } | 1093 | // Non-POD can be skipped if its metatable contains { __lanesignore = true } |
1094 | if (((1 << static_cast<int>(_val_type)) & kPODmask) == 0) { | 1094 | if (((1 << static_cast<int>(_val_type)) & kPODmask) == 0) { |
1095 | if (lua_getmetatable(L1, L1_i)) { // L1: ... mt | 1095 | if (lua_getmetatable(L1, L1_i)) { // L1: ... mt |
1096 | LuaType const _type{ luaG_getfield(L1, -1, "__lanesignore") }; // L1: ... mt ignore? | 1096 | LuaType const _type{ luaG_getfield(L1, -1, "__lanesignore") }; // L1: ... mt ignore? |
1097 | if (_type == LuaType::BOOLEAN && lua_toboolean(L1, -1)) { | 1097 | if (_type == LuaType::BOOLEAN && lua_toboolean(L1, -1)) { |
1098 | DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "__lanesignore -> LUA_TNIL\n" INDENT_END(U))); | 1098 | DEBUGSPEW_CODE(DebugSpew(U) << "__lanesignore -> LUA_TNIL" << std::endl); |
1099 | _val_type = LuaType::NIL; | 1099 | _val_type = LuaType::NIL; |
1100 | } | 1100 | } |
1101 | lua_pop(L1, 2); // L1: ... | 1101 | lua_pop(L1, 2); // L1: ... |
@@ -1155,7 +1155,7 @@ static char const* vt_names[] = { | |||
1155 | // else raise an error in whichever state is not a keeper | 1155 | // else raise an error in whichever state is not a keeper |
1156 | [[nodiscard]] InterCopyResult InterCopyContext::inter_copy_package() const | 1156 | [[nodiscard]] InterCopyResult InterCopyContext::inter_copy_package() const |
1157 | { | 1157 | { |
1158 | DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "InterCopyContext::inter_copy_package()\n" INDENT_END(U))); | 1158 | DEBUGSPEW_CODE(DebugSpew(U) << "InterCopyContext::inter_copy_package()" << std::endl); |
1159 | 1159 | ||
1160 | class OnExit | 1160 | class OnExit |
1161 | { | 1161 | { |
@@ -1189,7 +1189,7 @@ static char const* vt_names[] = { | |||
1189 | return InterCopyResult::Error; | 1189 | return InterCopyResult::Error; |
1190 | } | 1190 | } |
1191 | if (luaG_getmodule(L2, LUA_LOADLIBNAME) == LuaType::NIL) { // package library not loaded: do nothing | 1191 | if (luaG_getmodule(L2, LUA_LOADLIBNAME) == LuaType::NIL) { // package library not loaded: do nothing |
1192 | DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "'package' not loaded, nothing to do\n" INDENT_END(U))); | 1192 | DEBUGSPEW_CODE(DebugSpew(U) << "'package' not loaded, nothing to do" << std::endl); |
1193 | STACK_CHECK(L1, 0); | 1193 | STACK_CHECK(L1, 0); |
1194 | return InterCopyResult::Success; | 1194 | return InterCopyResult::Success; |
1195 | } | 1195 | } |
@@ -1204,7 +1204,7 @@ static char const* vt_names[] = { | |||
1204 | if (!_entry) { | 1204 | if (!_entry) { |
1205 | continue; | 1205 | continue; |
1206 | } | 1206 | } |
1207 | DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "package.%s\n" INDENT_END(U), _entry)); | 1207 | DEBUGSPEW_CODE(DebugSpew(U) << "package." << _entry << std::endl); |
1208 | if (luaG_getfield(L1, L1_i, _entry) == LuaType::NIL) { | 1208 | if (luaG_getfield(L1, L1_i, _entry) == LuaType::NIL) { |
1209 | lua_pop(L1, 1); | 1209 | lua_pop(L1, 1); |
1210 | } else { | 1210 | } else { |
@@ -1238,13 +1238,13 @@ static char const* vt_names[] = { | |||
1238 | { | 1238 | { |
1239 | LUA_ASSERT(L1, vt == VT::NORMAL); | 1239 | LUA_ASSERT(L1, vt == VT::NORMAL); |
1240 | 1240 | ||
1241 | DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "InterCopyContext::inter_copy()\n" INDENT_END(U))); | 1241 | DEBUGSPEW_CODE(DebugSpew(U) << "InterCopyContext::inter_copy()" << std::endl); |
1242 | DEBUGSPEW_CODE(DebugSpewIndentScope _scope{ U }); | 1242 | DEBUGSPEW_CODE(DebugSpewIndentScope _scope{ U }); |
1243 | 1243 | ||
1244 | int const _top_L1{ lua_gettop(L1) }; | 1244 | int const _top_L1{ lua_gettop(L1) }; |
1245 | if (n_ > _top_L1) { | 1245 | if (n_ > _top_L1) { |
1246 | // requesting to copy more than is available? | 1246 | // requesting to copy more than is available? |
1247 | DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "nothing to copy()\n" INDENT_END(U))); | 1247 | DEBUGSPEW_CODE(DebugSpew(U) << "nothing to copy" << std::endl); |
1248 | return InterCopyResult::NotEnoughValues; | 1248 | return InterCopyResult::NotEnoughValues; |
1249 | } | 1249 | } |
1250 | 1250 | ||
diff --git a/src/lane.cpp b/src/lane.cpp index 5904266..4b6500a 100644 --- a/src/lane.cpp +++ b/src/lane.cpp | |||
@@ -165,7 +165,7 @@ static LUAG_FUNC(thread_join) | |||
165 | break; | 165 | break; |
166 | 166 | ||
167 | default: | 167 | default: |
168 | DEBUGSPEW_CODE(fprintf(stderr, "Status: %d\n", _lane->status)); | 168 | DEBUGSPEW_CODE(DebugSpew(nullptr) << "Unknown Lane status: " << static_cast<int>(_lane->status) << std::endl); |
169 | LUA_ASSERT(L_, false); | 169 | LUA_ASSERT(L_, false); |
170 | _ret = 0; | 170 | _ret = 0; |
171 | } | 171 | } |
@@ -278,7 +278,7 @@ static int thread_index_number(lua_State* L_) | |||
278 | lua_replace(L_, -3); // L_: lane n error() "error" | 278 | lua_replace(L_, -3); // L_: lane n error() "error" |
279 | lua_pushinteger(L_, 3); // L_: lane n error() "error" 3 | 279 | lua_pushinteger(L_, 3); // L_: lane n error() "error" 3 |
280 | lua_call(L_, 2, 0); // error(tostring(errstring), 3) -> doesn't return // L_: lane n | 280 | lua_call(L_, 2, 0); // error(tostring(errstring), 3) -> doesn't return // L_: lane n |
281 | raise_luaL_error(L_, "%s: should not get here!", _lane->debugName.data()); | 281 | raise_luaL_error(L_, STRINGVIEW_FMT ": should not get here!", _lane->debugName.size(), _lane->debugName.data()); |
282 | } else { | 282 | } else { |
283 | lua_pop(L_, 1); // L_: lane n {uv} | 283 | lua_pop(L_, 1); // L_: lane n {uv} |
284 | } | 284 | } |
@@ -316,7 +316,7 @@ static int thread_index_string(lua_State* L_) | |||
316 | lua_rawget(L_, -2); // L_: mt value | 316 | lua_rawget(L_, -2); // L_: mt value |
317 | // only "cancel" and "join" are registered as functions, any other string will raise an error | 317 | // only "cancel" and "join" are registered as functions, any other string will raise an error |
318 | if (!lua_iscfunction(L_, -1)) { | 318 | if (!lua_iscfunction(L_, -1)) { |
319 | raise_luaL_error(L_, "can't index a lane with '%s'", _keystr.data()); | 319 | raise_luaL_error(L_, "can't index a lane with '" STRINGVIEW_FMT "'", _keystr.size(), _keystr.data()); |
320 | } | 320 | } |
321 | return 1; | 321 | return 1; |
322 | } | 322 | } |
@@ -345,7 +345,7 @@ static LUAG_FUNC(thread_index) | |||
345 | lua_pushvalue(L_, kKey); // L_: mt error "Unknown key: " k | 345 | lua_pushvalue(L_, kKey); // L_: mt error "Unknown key: " k |
346 | lua_concat(L_, 2); // L_: mt error "Unknown key: <k>" | 346 | lua_concat(L_, 2); // L_: mt error "Unknown key: <k>" |
347 | lua_call(L_, 1, 0); // error( "Unknown key: " .. key) -> doesn't return // L_: mt | 347 | lua_call(L_, 1, 0); // error( "Unknown key: " .. key) -> doesn't return // L_: mt |
348 | raise_luaL_error(L_, "%s[%s]: should not get here!", _lane->debugName.data(), lua_typename(L_, lua_type(L_, kKey))); | 348 | raise_luaL_error(L_, STRINGVIEW_FMT "[%s]: should not get here!", _lane->debugName.size(), _lane->debugName.data(), lua_typename(L_, lua_type(L_, kKey))); |
349 | } | 349 | } |
350 | } | 350 | } |
351 | 351 | ||
@@ -677,11 +677,11 @@ static void lane_main(Lane* lane_) | |||
677 | // in case of error and if it exists, fetch stack trace from registry and push it | 677 | // in case of error and if it exists, fetch stack trace from registry and push it |
678 | push_stack_trace(_L, lane_->errorTraceLevel, _rc, 1); // L: retvals|error [trace] | 678 | push_stack_trace(_L, lane_->errorTraceLevel, _rc, 1); // L: retvals|error [trace] |
679 | 679 | ||
680 | DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "Lane %p body: %s (%s)\n" INDENT_END(_U), _L, get_errcode_name(_rc), kCancelError.equals(_L, 1) ? "cancelled" : lua_typename(_L, lua_type(_L, 1)))); | 680 | DEBUGSPEW_CODE(DebugSpew(_U) << "Lane " << _L << " body: " << get_errcode_name(_rc) << " (" << (kCancelError.equals(_L, 1) ? "cancelled" : lua_typename(_L, lua_type(_L, 1))) << ")" << std::endl); |
681 | // Call finalizers, if the script has set them up. | 681 | // Call finalizers, if the script has set them up. |
682 | // | 682 | // |
683 | LuaError const _rc2{ run_finalizers(_L, lane_->errorTraceLevel, _rc) }; | 683 | LuaError const _rc2{ run_finalizers(_L, lane_->errorTraceLevel, _rc) }; |
684 | DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "Lane %p finalizer: %s\n" INDENT_END(_U), _L, get_errcode_name(_rc2))); | 684 | DEBUGSPEW_CODE(DebugSpew(_U) << "Lane " << _L << " finalizer: " << get_errcode_name(_rc2) << std::endl); |
685 | if (_rc2 != LuaError::OK) { // Error within a finalizer! | 685 | if (_rc2 != LuaError::OK) { // Error within a finalizer! |
686 | // the finalizer generated an error, and left its own error message [and stack trace] on the stack | 686 | // the finalizer generated an error, and left its own error message [and stack trace] on the stack |
687 | _rc = _rc2; // we're overruling the earlier script error or normal return | 687 | _rc = _rc2; // we're overruling the earlier script error or normal return |
@@ -839,7 +839,7 @@ void Lane::changeDebugName(int nameIdx_) | |||
839 | (errorTraceLevel == ErrorTraceLevel::Minimal) ? "minimal" : | 839 | (errorTraceLevel == ErrorTraceLevel::Minimal) ? "minimal" : |
840 | (errorTraceLevel == ErrorTraceLevel::Basic) ? "basic" : | 840 | (errorTraceLevel == ErrorTraceLevel::Basic) ? "basic" : |
841 | (errorTraceLevel == ErrorTraceLevel::Extended) ? "extended" : | 841 | (errorTraceLevel == ErrorTraceLevel::Extended) ? "extended" : |
842 | nullptr | 842 | "" |
843 | }; | 843 | }; |
844 | return _str; | 844 | return _str; |
845 | } | 845 | } |
diff --git a/src/lanes.cpp b/src/lanes.cpp index c91256e..a5c9c8b 100644 --- a/src/lanes.cpp +++ b/src/lanes.cpp | |||
@@ -166,17 +166,17 @@ LUAG_FUNC(set_thread_affinity) | |||
166 | // upvalue[1]: _G.require | 166 | // upvalue[1]: _G.require |
167 | LUAG_FUNC(require) | 167 | LUAG_FUNC(require) |
168 | { | 168 | { |
169 | char const* _name{ lua_tostring(L_, 1) }; // L_: "name" ... | 169 | std::string_view const _name{ lua_tostringview(L_, 1) }; // L_: "name" ... |
170 | int const _nargs{ lua_gettop(L_) }; | 170 | int const _nargs{ lua_gettop(L_) }; |
171 | DEBUGSPEW_CODE(Universe * _U{ universe_get(L_) }); | 171 | DEBUGSPEW_CODE(Universe * _U{ universe_get(L_) }); |
172 | STACK_CHECK_START_REL(L_, 0); | 172 | STACK_CHECK_START_REL(L_, 0); |
173 | DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "lanes.require %s BEGIN\n" INDENT_END(_U), _name)); | 173 | DEBUGSPEW_CODE(DebugSpew(_U) << "lanes.require '" << _name << "' BEGIN" << std::endl); |
174 | DEBUGSPEW_CODE(DebugSpewIndentScope _scope{ _U }); | 174 | DEBUGSPEW_CODE(DebugSpewIndentScope _scope{ _U }); |
175 | lua_pushvalue(L_, lua_upvalueindex(1)); // L_: "name" ... require | 175 | lua_pushvalue(L_, lua_upvalueindex(1)); // L_: "name" ... require |
176 | lua_insert(L_, 1); // L_: require "name" ... | 176 | lua_insert(L_, 1); // L_: require "name" ... |
177 | lua_call(L_, _nargs, 1); // L_: module | 177 | lua_call(L_, _nargs, 1); // L_: module |
178 | populate_func_lookup_table(L_, -1, _name); | 178 | populate_func_lookup_table(L_, -1, _name); |
179 | DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "lanes.require %s END\n" INDENT_END(_U), _name)); | 179 | DEBUGSPEW_CODE(DebugSpew(_U) << "lanes.require '" << _name << "' END" << std::endl); |
180 | STACK_CHECK(L_, 0); | 180 | STACK_CHECK(L_, 0); |
181 | return 1; | 181 | return 1; |
182 | } | 182 | } |
@@ -188,17 +188,17 @@ LUAG_FUNC(require) | |||
188 | // lanes.register( "modname", module) | 188 | // lanes.register( "modname", module) |
189 | LUAG_FUNC(register) | 189 | LUAG_FUNC(register) |
190 | { | 190 | { |
191 | char const* _name{ luaL_checkstring(L_, 1) }; | 191 | std::string_view const _name{ luaL_checkstringview(L_, 1) }; |
192 | LuaType const _mod_type{ lua_type_as_enum(L_, 2) }; | 192 | LuaType const _mod_type{ lua_type_as_enum(L_, 2) }; |
193 | // ignore extra parameters, just in case | 193 | // ignore extra parameters, just in case |
194 | lua_settop(L_, 2); | 194 | lua_settop(L_, 2); |
195 | luaL_argcheck(L_, (_mod_type == LuaType::TABLE) || (_mod_type == LuaType::FUNCTION), 2, "unexpected module type"); | 195 | luaL_argcheck(L_, (_mod_type == LuaType::TABLE) || (_mod_type == LuaType::FUNCTION), 2, "unexpected module type"); |
196 | DEBUGSPEW_CODE(Universe* _U = universe_get(L_)); | 196 | DEBUGSPEW_CODE(Universe* _U = universe_get(L_)); |
197 | STACK_CHECK_START_REL(L_, 0); // "name" mod_table | 197 | STACK_CHECK_START_REL(L_, 0); // "name" mod_table |
198 | DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "lanes.register %s BEGIN\n" INDENT_END(_U), _name)); | 198 | DEBUGSPEW_CODE(DebugSpew(_U) << "lanes.register '" << _name << "' BEGIN" << std::endl); |
199 | DEBUGSPEW_CODE(DebugSpewIndentScope _scope{ _U }); | 199 | DEBUGSPEW_CODE(DebugSpewIndentScope _scope{ _U }); |
200 | populate_func_lookup_table(L_, -1, _name); | 200 | populate_func_lookup_table(L_, -1, _name); |
201 | DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "lanes.register %s END\n" INDENT_END(_U), _name)); | 201 | DEBUGSPEW_CODE(DebugSpew(_U) << "lanes.register '" << _name << "' END" << std::endl); |
202 | STACK_CHECK(L_, 0); | 202 | STACK_CHECK(L_, 0); |
203 | return 0; | 203 | return 0; |
204 | } | 204 | } |
@@ -236,7 +236,7 @@ LUAG_FUNC(lane_new) | |||
236 | LUA_ASSERT(L_, _nargs >= 0); | 236 | LUA_ASSERT(L_, _nargs >= 0); |
237 | 237 | ||
238 | Universe* const _U{ universe_get(L_) }; | 238 | Universe* const _U{ universe_get(L_) }; |
239 | DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "lane_new: setup\n" INDENT_END(_U))); | 239 | DEBUGSPEW_CODE(DebugSpew(_U) << "lane_new: setup" << std::endl); |
240 | 240 | ||
241 | char const* const _libs_str{ lua_tostring(L_, kLibsIdx) }; | 241 | char const* const _libs_str{ lua_tostring(L_, kLibsIdx) }; |
242 | lua_State* const _L2{ luaG_newstate(_U, SourceState{ L_ }, _libs_str) }; // L_: [fixed] ... L2: | 242 | lua_State* const _L2{ luaG_newstate(_U, SourceState{ L_ }, _libs_str) }; // L_: [fixed] ... L2: |
@@ -288,7 +288,7 @@ LUAG_FUNC(lane_new) | |||
288 | private: | 288 | private: |
289 | void prepareUserData() | 289 | void prepareUserData() |
290 | { | 290 | { |
291 | DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "lane_new: preparing lane userdata\n" INDENT_END(lane->U))); | 291 | DEBUGSPEW_CODE(DebugSpew(lane->U) << "lane_new: preparing lane userdata" << std::endl); |
292 | STACK_CHECK_START_REL(L, 0); | 292 | STACK_CHECK_START_REL(L, 0); |
293 | // a Lane full userdata needs a single uservalue | 293 | // a Lane full userdata needs a single uservalue |
294 | Lane** const _ud{ lua_newuserdatauv<Lane*>(L, 1) }; // L: ... lane | 294 | Lane** const _ud{ lua_newuserdatauv<Lane*>(L, 1) }; // L: ... lane |
@@ -344,7 +344,7 @@ LUAG_FUNC(lane_new) | |||
344 | } | 344 | } |
345 | } onExit{ L_, _lane}; | 345 | } onExit{ L_, _lane}; |
346 | // launch the thread early, it will sync with a std::latch to parallelize OS thread warmup and L2 preparation | 346 | // launch the thread early, it will sync with a std::latch to parallelize OS thread warmup and L2 preparation |
347 | DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "lane_new: launching thread\n" INDENT_END(_U))); | 347 | DEBUGSPEW_CODE(DebugSpew(_U) << "lane_new: launching thread" << std::endl); |
348 | // public Lanes API accepts a generic range -3/+3 | 348 | // public Lanes API accepts a generic range -3/+3 |
349 | // that will be remapped into the platform-specific scheduler priority scheme | 349 | // that will be remapped into the platform-specific scheduler priority scheme |
350 | // On some platforms, -3 is equivalent to -2 and +3 to +2 | 350 | // On some platforms, -3 is equivalent to -2 and +3 to +2 |
@@ -371,7 +371,7 @@ LUAG_FUNC(lane_new) | |||
371 | // package | 371 | // package |
372 | int const _package_idx{ lua_isnoneornil(L_, kPackIdx) ? 0 : kPackIdx }; | 372 | int const _package_idx{ lua_isnoneornil(L_, kPackIdx) ? 0 : kPackIdx }; |
373 | if (_package_idx != 0) { | 373 | if (_package_idx != 0) { |
374 | DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "lane_new: update 'package'\n" INDENT_END(_U))); | 374 | DEBUGSPEW_CODE(DebugSpew(_U) << "lane_new: update 'package'" << std::endl); |
375 | // when copying with mode LookupMode::LaneBody, should raise an error in case of problem, not leave it one the stack | 375 | // when copying with mode LookupMode::LaneBody, should raise an error in case of problem, not leave it one the stack |
376 | InterCopyContext c{ _U, DestState{ _L2 }, SourceState{ L_ }, {}, SourceIndex{ _package_idx }, {}, {}, {} }; | 376 | InterCopyContext c{ _U, DestState{ _L2 }, SourceState{ L_ }, {}, SourceIndex{ _package_idx }, {}, {}, {} }; |
377 | [[maybe_unused]] InterCopyResult const ret{ c.inter_copy_package() }; | 377 | [[maybe_unused]] InterCopyResult const ret{ c.inter_copy_package() }; |
@@ -382,7 +382,7 @@ LUAG_FUNC(lane_new) | |||
382 | int const _required_idx{ lua_isnoneornil(L_, kRequIdx) ? 0 : kRequIdx }; | 382 | int const _required_idx{ lua_isnoneornil(L_, kRequIdx) ? 0 : kRequIdx }; |
383 | if (_required_idx != 0) { | 383 | if (_required_idx != 0) { |
384 | int _nbRequired{ 1 }; | 384 | int _nbRequired{ 1 }; |
385 | DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "lane_new: require 'required' list\n" INDENT_END(_U))); | 385 | DEBUGSPEW_CODE(DebugSpew(_U) << "lane_new: process 'required' list" << std::endl); |
386 | DEBUGSPEW_CODE(DebugSpewIndentScope _scope{ _U }); | 386 | DEBUGSPEW_CODE(DebugSpewIndentScope _scope{ _U }); |
387 | // should not happen, was checked in lanes.lua before calling lane_new() | 387 | // should not happen, was checked in lanes.lua before calling lane_new() |
388 | if (lua_type(L_, _required_idx) != LUA_TTABLE) { | 388 | if (lua_type(L_, _required_idx) != LUA_TTABLE) { |
@@ -396,7 +396,7 @@ LUAG_FUNC(lane_new) | |||
396 | } else { | 396 | } else { |
397 | // require the module in the target state, and populate the lookup table there too | 397 | // require the module in the target state, and populate the lookup table there too |
398 | std::string_view const _name{ lua_tostringview(L_, -1) }; | 398 | std::string_view const _name{ lua_tostringview(L_, -1) }; |
399 | DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "lane_new: require '%s'\n" INDENT_END(_U), _name.data())); | 399 | DEBUGSPEW_CODE(DebugSpew(_U) << "lane_new: require '" << _name << "'" << std::endl); |
400 | 400 | ||
401 | // require the module in the target lane | 401 | // require the module in the target lane |
402 | lua_getglobal(_L2, "require"); // L_: [fixed] args... n "modname" L2: require()? | 402 | lua_getglobal(_L2, "require"); // L_: [fixed] args... n "modname" L2: require()? |
@@ -404,7 +404,7 @@ LUAG_FUNC(lane_new) | |||
404 | lua_pop(_L2, 1); // L_: [fixed] args... n "modname" L2: | 404 | lua_pop(_L2, 1); // L_: [fixed] args... n "modname" L2: |
405 | raise_luaL_error(L_, "cannot pre-require modules without loading 'package' library first"); | 405 | raise_luaL_error(L_, "cannot pre-require modules without loading 'package' library first"); |
406 | } else { | 406 | } else { |
407 | lua_pushlstring(_L2, _name.data(), _name.size()); // L_: [fixed] args... n "modname" L2: require() name | 407 | std::ignore = lua_pushstringview(_L2, _name); // L_: [fixed] args... n "modname" L2: require() name |
408 | LuaError const _rc{ lua_pcall(_L2, 1, 1, 0) }; // L_: [fixed] args... n "modname" L2: ret/errcode | 408 | LuaError const _rc{ lua_pcall(_L2, 1, 1, 0) }; // L_: [fixed] args... n "modname" L2: ret/errcode |
409 | if (_rc != LuaError::OK) { | 409 | if (_rc != LuaError::OK) { |
410 | // propagate error to main state if any | 410 | // propagate error to main state if any |
@@ -414,7 +414,7 @@ LUAG_FUNC(lane_new) | |||
414 | } | 414 | } |
415 | // here the module was successfully required // L_: [fixed] args... n "modname" L2: ret | 415 | // here the module was successfully required // L_: [fixed] args... n "modname" L2: ret |
416 | // after requiring the module, register the functions it exported in our name<->function database | 416 | // after requiring the module, register the functions it exported in our name<->function database |
417 | populate_func_lookup_table(_L2, -1, _name.data()); | 417 | populate_func_lookup_table(_L2, -1, _name); |
418 | lua_pop(_L2, 1); // L_: [fixed] args... n "modname" L2: | 418 | lua_pop(_L2, 1); // L_: [fixed] args... n "modname" L2: |
419 | } | 419 | } |
420 | } | 420 | } |
@@ -430,7 +430,7 @@ LUAG_FUNC(lane_new) | |||
430 | // | 430 | // |
431 | int const _globals_idx{ lua_isnoneornil(L_, kGlobIdx) ? 0 : kGlobIdx }; | 431 | int const _globals_idx{ lua_isnoneornil(L_, kGlobIdx) ? 0 : kGlobIdx }; |
432 | if (_globals_idx != 0) { | 432 | if (_globals_idx != 0) { |
433 | DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "lane_new: transfer globals\n" INDENT_END(_U))); | 433 | DEBUGSPEW_CODE(DebugSpew(_U) << "lane_new: transfer globals" << std::endl); |
434 | if (!lua_istable(L_, _globals_idx)) { | 434 | if (!lua_istable(L_, _globals_idx)) { |
435 | raise_luaL_error(L_, "Expected table, got %s", luaL_typename(L_, _globals_idx)); | 435 | raise_luaL_error(L_, "Expected table, got %s", luaL_typename(L_, _globals_idx)); |
436 | } | 436 | } |
@@ -455,7 +455,7 @@ LUAG_FUNC(lane_new) | |||
455 | [[maybe_unused]] int const errorHandlerCount{ _lane->pushErrorHandler() }; // L_: [fixed] args... L2: eh? | 455 | [[maybe_unused]] int const errorHandlerCount{ _lane->pushErrorHandler() }; // L_: [fixed] args... L2: eh? |
456 | LuaType const _func_type{ lua_type_as_enum(L_, kFuncIdx) }; | 456 | LuaType const _func_type{ lua_type_as_enum(L_, kFuncIdx) }; |
457 | if (_func_type == LuaType::FUNCTION) { | 457 | if (_func_type == LuaType::FUNCTION) { |
458 | DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "lane_new: transfer lane body\n" INDENT_END(_U))); | 458 | DEBUGSPEW_CODE(DebugSpew(_U) << "lane_new: transfer lane body" << std::endl); |
459 | DEBUGSPEW_CODE(DebugSpewIndentScope _scope{ _U }); | 459 | DEBUGSPEW_CODE(DebugSpewIndentScope _scope{ _U }); |
460 | lua_pushvalue(L_, kFuncIdx); // L_: [fixed] args... func L2: eh? | 460 | lua_pushvalue(L_, kFuncIdx); // L_: [fixed] args... func L2: eh? |
461 | InterCopyContext _c{ _U, DestState{ _L2 }, SourceState{ L_ }, {}, {}, {}, {}, {} }; | 461 | InterCopyContext _c{ _U, DestState{ _L2 }, SourceState{ L_ }, {}, {}, {}, {}, {} }; |
@@ -464,7 +464,7 @@ LUAG_FUNC(lane_new) | |||
464 | raise_luaL_error(L_, "tried to copy unsupported types"); | 464 | raise_luaL_error(L_, "tried to copy unsupported types"); |
465 | } | 465 | } |
466 | } else if (_func_type == LuaType::STRING) { | 466 | } else if (_func_type == LuaType::STRING) { |
467 | DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "lane_new: compile lane body\n" INDENT_END(_U))); | 467 | DEBUGSPEW_CODE(DebugSpew(_U) << "lane_new: compile lane body" << std::endl); |
468 | // compile the string | 468 | // compile the string |
469 | if (luaL_loadstring(_L2, lua_tostring(L_, kFuncIdx)) != 0) { // L_: [fixed] args... L2: eh? func | 469 | if (luaL_loadstring(_L2, lua_tostring(L_, kFuncIdx)) != 0) { // L_: [fixed] args... L2: eh? func |
470 | raise_luaL_error(L_, "error when parsing lane function code"); | 470 | raise_luaL_error(L_, "error when parsing lane function code"); |
@@ -478,7 +478,7 @@ LUAG_FUNC(lane_new) | |||
478 | 478 | ||
479 | // revive arguments | 479 | // revive arguments |
480 | if (_nargs > 0) { | 480 | if (_nargs > 0) { |
481 | DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "lane_new: transfer lane arguments\n" INDENT_END(_U))); | 481 | DEBUGSPEW_CODE(DebugSpew(_U) << "lane_new: transfer lane arguments" << std::endl); |
482 | DEBUGSPEW_CODE(DebugSpewIndentScope _scope{ _U }); | 482 | DEBUGSPEW_CODE(DebugSpewIndentScope _scope{ _U }); |
483 | InterCopyContext _c{ _U, DestState{ _L2 }, SourceState{ L_ }, {}, {}, {}, {}, {} }; | 483 | InterCopyContext _c{ _U, DestState{ _L2 }, SourceState{ L_ }, {}, {}, {}, {}, {} }; |
484 | InterCopyResult const res{ _c.inter_move(_nargs) }; // L_: [fixed] L2: eh? func args... | 484 | InterCopyResult const res{ _c.inter_move(_nargs) }; // L_: [fixed] L2: eh? func args... |
@@ -627,13 +627,13 @@ LUAG_FUNC(configure) | |||
627 | 627 | ||
628 | Universe* _U{ universe_get(L_) }; | 628 | Universe* _U{ universe_get(L_) }; |
629 | bool const _from_master_state{ _U == nullptr }; | 629 | bool const _from_master_state{ _U == nullptr }; |
630 | char const* const _name{ luaL_checkstring(L_, lua_upvalueindex(1)) }; | 630 | std::string_view const _name{ luaL_checkstringview(L_, lua_upvalueindex(1)) }; |
631 | LUA_ASSERT(L_, lua_type(L_, 1) == LUA_TTABLE); | 631 | LUA_ASSERT(L_, lua_type(L_, 1) == LUA_TTABLE); |
632 | 632 | ||
633 | STACK_GROW(L_, 4); | 633 | STACK_GROW(L_, 4); |
634 | STACK_CHECK_START_ABS(L_, 1); // L_: settings | 634 | STACK_CHECK_START_ABS(L_, 1); // L_: settings |
635 | 635 | ||
636 | DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "%p: lanes.configure() BEGIN\n" INDENT_END(_U), L_)); | 636 | DEBUGSPEW_CODE(DebugSpew(_U) << L_ << ": lanes.configure() BEGIN" << std::endl); |
637 | DEBUGSPEW_CODE(DebugSpewIndentScope _scope{ _U }); | 637 | DEBUGSPEW_CODE(DebugSpewIndentScope _scope{ _U }); |
638 | 638 | ||
639 | if (_U == nullptr) { | 639 | if (_U == nullptr) { |
@@ -757,7 +757,7 @@ LUAG_FUNC(configure) | |||
757 | // because we will do it after on_state_create() is called, | 757 | // because we will do it after on_state_create() is called, |
758 | // and we don't want to skip _G because of caching in case globals are created then | 758 | // and we don't want to skip _G because of caching in case globals are created then |
759 | lua_pushglobaltable(L_); // L_: settings M _G | 759 | lua_pushglobaltable(L_); // L_: settings M _G |
760 | populate_func_lookup_table(L_, -1, nullptr); | 760 | populate_func_lookup_table(L_, -1, {}); |
761 | lua_pop(L_, 1); // L_: settings M | 761 | lua_pop(L_, 1); // L_: settings M |
762 | } | 762 | } |
763 | lua_pop(L_, 1); // L_: settings | 763 | lua_pop(L_, 1); // L_: settings |
@@ -765,7 +765,7 @@ LUAG_FUNC(configure) | |||
765 | // set _R[kConfigRegKey] = settings | 765 | // set _R[kConfigRegKey] = settings |
766 | kConfigRegKey.setValue(L_, [](lua_State* L_) { lua_pushvalue(L_, -2); }); | 766 | kConfigRegKey.setValue(L_, [](lua_State* L_) { lua_pushvalue(L_, -2); }); |
767 | STACK_CHECK(L_, 1); | 767 | STACK_CHECK(L_, 1); |
768 | DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "%p: lanes.configure() END\n" INDENT_END(_U), L_)); | 768 | DEBUGSPEW_CODE(DebugSpew(_U) << L_ << ": lanes.configure() END" << std::endl); |
769 | // Return the settings table | 769 | // Return the settings table |
770 | return 1; | 770 | return 1; |
771 | } | 771 | } |
diff --git a/src/state.cpp b/src/state.cpp index 90a7c5b..0175449 100644 --- a/src/state.cpp +++ b/src/state.cpp | |||
@@ -55,7 +55,7 @@ THE SOFTWARE. | |||
55 | { | 55 | { |
56 | int const _args{ lua_gettop(L_) }; // L_: args | 56 | int const _args{ lua_gettop(L_) }; // L_: args |
57 | Universe* const _U{ universe_get(L_) }; | 57 | Universe* const _U{ universe_get(L_) }; |
58 | // char const* modname = luaL_checkstring(L_, 1); | 58 | //[[maybe_unused]] std::string_view const _modname{ luaL_checkstringview(L_, 1) }; |
59 | 59 | ||
60 | STACK_GROW(L_, 1); | 60 | STACK_GROW(L_, 1); |
61 | 61 | ||
@@ -88,7 +88,7 @@ void serialize_require(DEBUGSPEW_PARAM_COMMA(Universe* U_) lua_State* L_) | |||
88 | { | 88 | { |
89 | STACK_GROW(L_, 1); | 89 | STACK_GROW(L_, 1); |
90 | STACK_CHECK_START_REL(L_, 0); | 90 | STACK_CHECK_START_REL(L_, 0); |
91 | DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "serializing require()\n" INDENT_END(U_))); | 91 | DEBUGSPEW_CODE(DebugSpew(U_) << "serializing require()" << std::endl); |
92 | 92 | ||
93 | // Check 'require' is there and not already wrapped; if not, do nothing | 93 | // Check 'require' is there and not already wrapped; if not, do nothing |
94 | // | 94 | // |
@@ -155,23 +155,23 @@ namespace global | |||
155 | 155 | ||
156 | // ################################################################################################# | 156 | // ################################################################################################# |
157 | 157 | ||
158 | static void open1lib(DEBUGSPEW_PARAM_COMMA(Universe* U_) lua_State* L_, char const* name_, size_t len_) | 158 | static void open1lib(DEBUGSPEW_PARAM_COMMA(Universe* U_) lua_State* L_, std::string_view const& name_) |
159 | { | 159 | { |
160 | for (luaL_Reg const& _entry : global::sLibs) { | 160 | for (luaL_Reg const& _entry : global::sLibs) { |
161 | if (strncmp(name_, _entry.name, len_) == 0) { | 161 | if (name_ == _entry.name) { |
162 | lua_CFunction const _libfunc{ _entry.func }; | 162 | lua_CFunction const _libfunc{ _entry.func }; |
163 | if (!_libfunc) { | 163 | if (!_libfunc) { |
164 | continue; | 164 | break; |
165 | } | 165 | } |
166 | name_ = _entry.name; // note that the provided name_ doesn't necessarily ends with '\0', hence len_ | 166 | std::string_view const _name{ _entry.name }; |
167 | DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "opening %.*s library\n" INDENT_END(U_), (int) len_, name_)); | 167 | DEBUGSPEW_CODE(DebugSpew(U_) << "opening '" << _name << "' library" << std::endl); |
168 | STACK_CHECK_START_REL(L_, 0); | 168 | STACK_CHECK_START_REL(L_, 0); |
169 | // open the library as if through require(), and create a global as well if necessary (the library table is left on the stack) | 169 | // open the library as if through require(), and create a global as well if necessary (the library table is left on the stack) |
170 | bool const isLanesCore{ _libfunc == require_lanes_core }; // don't want to create a global for "lanes.core" | 170 | bool const isLanesCore{ _libfunc == require_lanes_core }; // don't want to create a global for "lanes.core" |
171 | luaL_requiref(L_, name_, _libfunc, !isLanesCore); // L_: {lib} | 171 | luaL_requiref(L_, _name.data(), _libfunc, !isLanesCore); // L_: {lib} |
172 | // lanes.core doesn't declare a global, so scan it here and now | 172 | // lanes.core doesn't declare a global, so scan it here and now |
173 | if (isLanesCore) { | 173 | if (isLanesCore) { |
174 | populate_func_lookup_table(L_, -1, name_); | 174 | populate_func_lookup_table(L_, -1, _name); |
175 | } | 175 | } |
176 | lua_pop(L_, 1); // L_: | 176 | lua_pop(L_, 1); // L_: |
177 | STACK_CHECK(L_, 0); | 177 | STACK_CHECK(L_, 0); |
@@ -182,14 +182,6 @@ static void open1lib(DEBUGSPEW_PARAM_COMMA(Universe* U_) lua_State* L_, char con | |||
182 | 182 | ||
183 | // ################################################################################################# | 183 | // ################################################################################################# |
184 | 184 | ||
185 | template<size_t N> | ||
186 | static inline void open1lib(DEBUGSPEW_PARAM_COMMA(Universe* U_) lua_State* L_, char const (&name_)[N]) | ||
187 | { | ||
188 | open1lib(DEBUGSPEW_PARAM_COMMA(U_) L_, name_, N - 1); | ||
189 | } | ||
190 | |||
191 | // ################################################################################################# | ||
192 | |||
193 | // just like lua_xmove, args are (from, to) | 185 | // just like lua_xmove, args are (from, to) |
194 | static void copy_one_time_settings(Universe* U_, SourceState L1_, DestState L2_) | 186 | static void copy_one_time_settings(Universe* U_, SourceState L1_, DestState L2_) |
195 | { | 187 | { |
@@ -199,7 +191,7 @@ static void copy_one_time_settings(Universe* U_, SourceState L1_, DestState L2_) | |||
199 | STACK_CHECK_START_REL(L1_, 0); | 191 | STACK_CHECK_START_REL(L1_, 0); |
200 | STACK_CHECK_START_REL(L2_, 0); | 192 | STACK_CHECK_START_REL(L2_, 0); |
201 | 193 | ||
202 | DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "copy_one_time_settings()\n" INDENT_END(U_))); | 194 | DEBUGSPEW_CODE(DebugSpew(U_) << "copy_one_time_settings()" << std::endl); |
203 | 195 | ||
204 | kConfigRegKey.pushValue(L1_); // L1_: config | 196 | kConfigRegKey.pushValue(L1_); // L1_: config |
205 | // copy settings from from source to destination registry | 197 | // copy settings from from source to destination registry |
@@ -275,7 +267,7 @@ void CallOnStateCreate(Universe* U_, lua_State* L_, lua_State* from_, LookupMode | |||
275 | { | 267 | { |
276 | if (U_->onStateCreateFunc != nullptr) { | 268 | if (U_->onStateCreateFunc != nullptr) { |
277 | STACK_CHECK_START_REL(L_, 0); | 269 | STACK_CHECK_START_REL(L_, 0); |
278 | DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "calling on_state_create()\n" INDENT_END(U_))); | 270 | DEBUGSPEW_CODE(DebugSpew(U_) << "calling on_state_create()" << std::endl); |
279 | if (U_->onStateCreateFunc != reinterpret_cast<lua_CFunction>(InitializeOnStateCreate)) { | 271 | if (U_->onStateCreateFunc != reinterpret_cast<lua_CFunction>(InitializeOnStateCreate)) { |
280 | // C function: recreate a closure in the new state, bypassing the lookup scheme | 272 | // C function: recreate a closure in the new state, bypassing the lookup scheme |
281 | lua_pushcfunction(L_, U_->onStateCreateFunc); // on_state_create() | 273 | lua_pushcfunction(L_, U_->onStateCreateFunc); // on_state_create() |
@@ -333,11 +325,11 @@ lua_State* luaG_newstate(Universe* U_, SourceState from_, char const* libs_) | |||
333 | 325 | ||
334 | // neither libs (not even 'base') nor special init func: we are done | 326 | // neither libs (not even 'base') nor special init func: we are done |
335 | if (libs_ == nullptr && U_->onStateCreateFunc == nullptr) { | 327 | if (libs_ == nullptr && U_->onStateCreateFunc == nullptr) { |
336 | DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "luaG_newstate(nullptr)\n" INDENT_END(U_))); | 328 | DEBUGSPEW_CODE(DebugSpew(U_) << "luaG_newstate(nullptr)" << std::endl); |
337 | return _L; | 329 | return _L; |
338 | } | 330 | } |
339 | 331 | ||
340 | DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "luaG_newstate()\n" INDENT_END(U_))); | 332 | DEBUGSPEW_CODE(DebugSpew(U_) << "luaG_newstate()" << std::endl); |
341 | DEBUGSPEW_CODE(DebugSpewIndentScope _scope{ U_ }); | 333 | DEBUGSPEW_CODE(DebugSpewIndentScope _scope{ U_ }); |
342 | 334 | ||
343 | // copy settings (for example because it may contain a Lua on_state_create function) | 335 | // copy settings (for example because it may contain a Lua on_state_create function) |
@@ -351,13 +343,13 @@ lua_State* luaG_newstate(Universe* U_, SourceState from_, char const* libs_) | |||
351 | // special "*" case (mainly to help with LuaJIT compatibility) | 343 | // special "*" case (mainly to help with LuaJIT compatibility) |
352 | // as we are called from luaopen_lanes_core() already, and that would deadlock | 344 | // as we are called from luaopen_lanes_core() already, and that would deadlock |
353 | if (libs_[0] == '*' && libs_[1] == 0) { | 345 | if (libs_[0] == '*' && libs_[1] == 0) { |
354 | DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "opening ALL standard libraries\n" INDENT_END(U_))); | 346 | DEBUGSPEW_CODE(DebugSpew(U_) << "opening ALL standard libraries" << std::endl); |
355 | luaL_openlibs(_L); | 347 | luaL_openlibs(_L); |
356 | // don't forget lanes.core for regular lane states | 348 | // don't forget lanes.core for regular lane states |
357 | open1lib(DEBUGSPEW_PARAM_COMMA(U_) _L, kLanesCoreLibName); | 349 | open1lib(DEBUGSPEW_PARAM_COMMA(U_) _L, kLanesCoreLibName); |
358 | libs_ = nullptr; // done with libs | 350 | libs_ = nullptr; // done with libs |
359 | } else { | 351 | } else { |
360 | DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "opening base library\n" INDENT_END(U_))); | 352 | DEBUGSPEW_CODE(DebugSpew(U_) << "opening 'base' library" << std::endl); |
361 | #if LUA_VERSION_NUM >= 502 | 353 | #if LUA_VERSION_NUM >= 502 |
362 | // open base library the same way as in luaL_openlibs() | 354 | // open base library the same way as in luaL_openlibs() |
363 | luaL_requiref(_L, LUA_GNAME, luaopen_base, 1); | 355 | luaL_requiref(_L, LUA_GNAME, luaopen_base, 1); |
@@ -373,17 +365,17 @@ lua_State* luaG_newstate(Universe* U_, SourceState from_, char const* libs_) | |||
373 | 365 | ||
374 | // scan all libraries, open them one by one | 366 | // scan all libraries, open them one by one |
375 | if (libs_) { | 367 | if (libs_) { |
376 | unsigned int len{ 0 }; | 368 | unsigned int _len{ 0 }; |
377 | for (char const* p{ libs_ }; *p; p += len) { | 369 | for (char const* _p{ libs_ }; *_p; _p += _len) { |
378 | // skip delimiters ('.' can be part of name for "lanes.core") | 370 | // skip delimiters ('.' can be part of name for "lanes.core") |
379 | while (*p && !isalnum(*p) && *p != '.') | 371 | while (*_p && !isalnum(*_p) && *_p != '.') |
380 | ++p; | 372 | ++_p; |
381 | // skip name | 373 | // skip name |
382 | len = 0; | 374 | _len = 0; |
383 | while (isalnum(p[len]) || p[len] == '.') | 375 | while (isalnum(_p[_len]) || _p[_len] == '.') |
384 | ++len; | 376 | ++_len; |
385 | // open library | 377 | // open library |
386 | open1lib(DEBUGSPEW_PARAM_COMMA(U_) _L, p, len); | 378 | open1lib(DEBUGSPEW_PARAM_COMMA(U_) _L, { _p, _len }); |
387 | } | 379 | } |
388 | } | 380 | } |
389 | lua_gc(_L, LUA_GCRESTART, 0); | 381 | lua_gc(_L, LUA_GCRESTART, 0); |
@@ -398,7 +390,7 @@ lua_State* luaG_newstate(Universe* U_, SourceState from_, char const* libs_) | |||
398 | // after all this, register everything we find in our name<->function database | 390 | // after all this, register everything we find in our name<->function database |
399 | lua_pushglobaltable(_L); // Lua 5.2 no longer has LUA_GLOBALSINDEX: we must push globals table on the stack | 391 | lua_pushglobaltable(_L); // Lua 5.2 no longer has LUA_GLOBALSINDEX: we must push globals table on the stack |
400 | STACK_CHECK(_L, 1); | 392 | STACK_CHECK(_L, 1); |
401 | populate_func_lookup_table(_L, -1, nullptr); | 393 | populate_func_lookup_table(_L, -1, {}); |
402 | 394 | ||
403 | #if 1 && USE_DEBUG_SPEW() | 395 | #if 1 && USE_DEBUG_SPEW() |
404 | // dump the lookup database contents | 396 | // dump the lookup database contents |
diff --git a/src/tools.cpp b/src/tools.cpp index ba0785b..5f12995 100644 --- a/src/tools.cpp +++ b/src/tools.cpp | |||
@@ -129,7 +129,7 @@ static void update_lookup_entry(DEBUGSPEW_PARAM_COMMA(Universe* U_) lua_State* L | |||
129 | // slot 2 contains a table that, when concatenated, produces the fully qualified name of scanned elements in the table provided at slot _i | 129 | // slot 2 contains a table that, when concatenated, produces the fully qualified name of scanned elements in the table provided at slot _i |
130 | int const _fqn{ ctxBase_ + 1 }; | 130 | int const _fqn{ ctxBase_ + 1 }; |
131 | 131 | ||
132 | DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "update_lookup_entry()\n" INDENT_END(U_))); | 132 | DEBUGSPEW_CODE(DebugSpew(U_) << "update_lookup_entry()" << std::endl); |
133 | DEBUGSPEW_CODE(DebugSpewIndentScope _scope{ U_ }); | 133 | DEBUGSPEW_CODE(DebugSpewIndentScope _scope{ U_ }); |
134 | 134 | ||
135 | STACK_CHECK_START_REL(L_, 0); | 135 | STACK_CHECK_START_REL(L_, 0); |
@@ -154,7 +154,7 @@ static void update_lookup_entry(DEBUGSPEW_PARAM_COMMA(Universe* U_) lua_State* L | |||
154 | // Therefore, when we encounter an object for which a name was previously registered, we need to select the names | 154 | // Therefore, when we encounter an object for which a name was previously registered, we need to select the names |
155 | // based on some sorting order so that we end up with the same name in all databases whatever order the table walk yielded | 155 | // based on some sorting order so that we end up with the same name in all databases whatever order the table walk yielded |
156 | if (!_prevName.empty() && (_prevName.size() < _newName.size() || lua_lessthan(L_, -2, -1))) { | 156 | if (!_prevName.empty() && (_prevName.size() < _newName.size() || lua_lessthan(L_, -2, -1))) { |
157 | DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "%s '%s' remained named '%s'\n" INDENT_END(U_), lua_typename(L_, lua_type(L_, -3)), _newName.data(), _prevName.data())); | 157 | DEBUGSPEW_CODE(DebugSpew(U_) << lua_typename(L_, lua_type(L_, -3)) << " '" << _newName << "' remains named '" << _prevName << "'" << std::endl); |
158 | // the previous name is 'smaller' than the one we just generated: keep it! | 158 | // the previous name is 'smaller' than the one we just generated: keep it! |
159 | lua_pop(L_, 3); // L_: ... {bfc} k | 159 | lua_pop(L_, 3); // L_: ... {bfc} k |
160 | } else { | 160 | } else { |
@@ -168,7 +168,7 @@ static void update_lookup_entry(DEBUGSPEW_PARAM_COMMA(Universe* U_) lua_State* L | |||
168 | } else { | 168 | } else { |
169 | lua_remove(L_, -2); // L_: ... {bfc} k o "f.q.n" | 169 | lua_remove(L_, -2); // L_: ... {bfc} k o "f.q.n" |
170 | } | 170 | } |
171 | DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "%s '%s'\n" INDENT_END(U_), lua_typename(L_, lua_type(L_, -2)), _newName.data())); | 171 | DEBUGSPEW_CODE(DebugSpew(U_) << lua_typename(L_, lua_type(L_, -2)) << " '" << _newName << "'" << std::endl); |
172 | // prepare the stack for database feed | 172 | // prepare the stack for database feed |
173 | lua_pushvalue(L_, -1); // L_: ... {bfc} k o "f.q.n" "f.q.n" | 173 | lua_pushvalue(L_, -1); // L_: ... {bfc} k o "f.q.n" "f.q.n" |
174 | lua_pushvalue(L_, -3); // L_: ... {bfc} k o "f.q.n" "f.q.n" o | 174 | lua_pushvalue(L_, -3); // L_: ... {bfc} k o "f.q.n" "f.q.n" o |
@@ -195,7 +195,7 @@ static void populate_func_lookup_table_recur(DEBUGSPEW_PARAM_COMMA(Universe* U_) | |||
195 | int const _fqn{ dbIdx_ + 1 }; | 195 | int const _fqn{ dbIdx_ + 1 }; |
196 | // slot dbIdx_ + 2 contains a cache that stores all already visited tables to avoid infinite recursion loops | 196 | // slot dbIdx_ + 2 contains a cache that stores all already visited tables to avoid infinite recursion loops |
197 | int const _cache{ dbIdx_ + 2 }; | 197 | int const _cache{ dbIdx_ + 2 }; |
198 | DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "populate_func_lookup_table_recur()\n" INDENT_END(U_))); | 198 | DEBUGSPEW_CODE(DebugSpew(U_) << "populate_func_lookup_table_recur()" << std::endl); |
199 | DEBUGSPEW_CODE(DebugSpewIndentScope _scope{ U_ }); | 199 | DEBUGSPEW_CODE(DebugSpewIndentScope _scope{ U_ }); |
200 | 200 | ||
201 | STACK_GROW(L_, 6); | 201 | STACK_GROW(L_, 6); |
@@ -215,7 +215,7 @@ static void populate_func_lookup_table_recur(DEBUGSPEW_PARAM_COMMA(Universe* U_) | |||
215 | lua_pop(L_, 1); // L_: ... {i_} | 215 | lua_pop(L_, 1); // L_: ... {i_} |
216 | STACK_CHECK(L_, 0); | 216 | STACK_CHECK(L_, 0); |
217 | if (_visit_count > 0) { | 217 | if (_visit_count > 0) { |
218 | DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "already visited\n" INDENT_END(U_))); | 218 | DEBUGSPEW_CODE(DebugSpew(U_) << "already visited" << std::endl); |
219 | return; | 219 | return; |
220 | } | 220 | } |
221 | 221 | ||
@@ -262,8 +262,8 @@ static void populate_func_lookup_table_recur(DEBUGSPEW_PARAM_COMMA(Universe* U_) | |||
262 | ++depth_; | 262 | ++depth_; |
263 | lua_pushnil(L_); // L_: ... {i_} {bfc} nil | 263 | lua_pushnil(L_); // L_: ... {i_} {bfc} nil |
264 | while (lua_next(L_, breadthFirstCache) != 0) { // L_: ... {i_} {bfc} k {} | 264 | while (lua_next(L_, breadthFirstCache) != 0) { // L_: ... {i_} {bfc} k {} |
265 | DEBUGSPEW_CODE(char const* _key = (lua_type(L_, -2) == LUA_TSTRING) ? lua_tostring(L_, -2) : "not a string"); | 265 | DEBUGSPEW_CODE(std::string_view const _key{ (lua_type(L_, -2) == LUA_TSTRING) ? lua_tostringview(L_, -2) : std::string_view{ "<not a string>" } }); |
266 | DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "table '%s'\n" INDENT_END(U_), _key)); | 266 | DEBUGSPEW_CODE(DebugSpew(U_) << "table '"<< _key <<"'" << std::endl); |
267 | DEBUGSPEW_CODE(DebugSpewIndentScope _scope2{ U_ }); | 267 | DEBUGSPEW_CODE(DebugSpewIndentScope _scope2{ U_ }); |
268 | // un-visit this table in case we do need to process it | 268 | // un-visit this table in case we do need to process it |
269 | lua_pushvalue(L_, -1); // L_: ... {i_} {bfc} k {} {} | 269 | lua_pushvalue(L_, -1); // L_: ... {i_} {bfc} k {} {} |
@@ -298,11 +298,12 @@ static void populate_func_lookup_table_recur(DEBUGSPEW_PARAM_COMMA(Universe* U_) | |||
298 | // ################################################################################################# | 298 | // ################################################################################################# |
299 | 299 | ||
300 | // create a "fully.qualified.name" <-> function equivalence database | 300 | // create a "fully.qualified.name" <-> function equivalence database |
301 | void populate_func_lookup_table(lua_State* L_, int i_, char const* name_) | 301 | void populate_func_lookup_table(lua_State* const L_, int const i_, std::string_view const& name_) |
302 | { | 302 | { |
303 | int const _in_base = lua_absindex(L_, i_); | 303 | int const _in_base = lua_absindex(L_, i_); |
304 | DEBUGSPEW_CODE(Universe* _U = universe_get(L_)); | 304 | DEBUGSPEW_CODE(Universe* _U = universe_get(L_)); |
305 | DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "%p: populate_func_lookup_table('%s')\n" INDENT_END(_U), L_, name_ ? name_ : "nullptr")); | 305 | std::string_view _name{ name_.empty() ? std::string_view{} : name_ }; |
306 | DEBUGSPEW_CODE(DebugSpew(_U) << L_ << ": populate_func_lookup_table('" << _name << "')" << std::endl); | ||
306 | DEBUGSPEW_CODE(DebugSpewIndentScope _scope{ _U }); | 307 | DEBUGSPEW_CODE(DebugSpewIndentScope _scope{ _U }); |
307 | STACK_GROW(L_, 3); | 308 | STACK_GROW(L_, 3); |
308 | STACK_CHECK_START_REL(L_, 0); | 309 | STACK_CHECK_START_REL(L_, 0); |
@@ -311,20 +312,22 @@ void populate_func_lookup_table(lua_State* L_, int i_, char const* name_) | |||
311 | STACK_CHECK(L_, 1); | 312 | STACK_CHECK(L_, 1); |
312 | LUA_ASSERT(L_, lua_istable(L_, -1)); | 313 | LUA_ASSERT(L_, lua_istable(L_, -1)); |
313 | if (lua_type(L_, _in_base) == LUA_TFUNCTION) { // for example when a module is a simple function | 314 | if (lua_type(L_, _in_base) == LUA_TFUNCTION) { // for example when a module is a simple function |
314 | name_ = name_ ? name_ : "nullptr"; | 315 | if (_name.empty()) { |
316 | _name = "nullptr"; | ||
317 | } | ||
315 | lua_pushvalue(L_, _in_base); // L_: {} f | 318 | lua_pushvalue(L_, _in_base); // L_: {} f |
316 | lua_pushstring(L_, name_); // L_: {} f _name | 319 | std::ignore = lua_pushstringview(L_, _name); // L_: {} f name_ |
317 | lua_rawset(L_, -3); // L_: {} | 320 | lua_rawset(L_, -3); // L_: {} |
318 | lua_pushstring(L_, name_); // L_: {} _name | 321 | std::ignore = lua_pushstringview(L_, _name); // L_: {} name_ |
319 | lua_pushvalue(L_, _in_base); // L_: {} _name f | 322 | lua_pushvalue(L_, _in_base); // L_: {} name_ f |
320 | lua_rawset(L_, -3); // L_: {} | 323 | lua_rawset(L_, -3); // L_: {} |
321 | lua_pop(L_, 1); // L_: | 324 | lua_pop(L_, 1); // L_: |
322 | } else if (lua_type(L_, _in_base) == LUA_TTABLE) { | 325 | } else if (lua_type(L_, _in_base) == LUA_TTABLE) { |
323 | lua_newtable(L_); // L_: {} {fqn} | 326 | lua_newtable(L_); // L_: {} {fqn} |
324 | int _startDepth{ 0 }; | 327 | int _startDepth{ 0 }; |
325 | if (name_) { | 328 | if (!_name.empty()) { |
326 | STACK_CHECK(L_, 2); | 329 | STACK_CHECK(L_, 2); |
327 | lua_pushstring(L_, name_); // L_: {} {fqn} "name" | 330 | std::ignore = lua_pushstringview(L_, _name); // L_: {} {fqn} "name" |
328 | // generate a name, and if we already had one name, keep whichever is the shorter | 331 | // generate a name, and if we already had one name, keep whichever is the shorter |
329 | lua_pushvalue(L_, _in_base); // L_: {} {fqn} "name" t | 332 | lua_pushvalue(L_, _in_base); // L_: {} {fqn} "name" t |
330 | update_lookup_entry(DEBUGSPEW_PARAM_COMMA(_U) L_, _dbIdx, _startDepth); // L_: {} {fqn} "name" | 333 | update_lookup_entry(DEBUGSPEW_PARAM_COMMA(_U) L_, _dbIdx, _startDepth); // L_: {} {fqn} "name" |
diff --git a/src/tools.h b/src/tools.h index be76fd9..4857eeb 100644 --- a/src/tools.h +++ b/src/tools.h | |||
@@ -24,7 +24,7 @@ enum class FuncSubType | |||
24 | 24 | ||
25 | [[nodiscard]] int luaG_nameof(lua_State* L_); | 25 | [[nodiscard]] int luaG_nameof(lua_State* L_); |
26 | 26 | ||
27 | void populate_func_lookup_table(lua_State* L_, int i_, char const* name_); | 27 | void populate_func_lookup_table(lua_State* const L_, int const i_, std::string_view const& name_); |
28 | 28 | ||
29 | // ################################################################################################# | 29 | // ################################################################################################# |
30 | 30 | ||
diff --git a/src/universe.cpp b/src/universe.cpp index 548475e..0bab844 100644 --- a/src/universe.cpp +++ b/src/universe.cpp | |||
@@ -322,20 +322,20 @@ void Universe::terminateFreeRunningLanes(lua_State* L_, lua_Duration shutdownTim | |||
322 | // give threads time to act on their cancel | 322 | // give threads time to act on their cancel |
323 | std::this_thread::yield(); | 323 | std::this_thread::yield(); |
324 | // count the number of cancelled thread that didn't have the time to act yet | 324 | // count the number of cancelled thread that didn't have the time to act yet |
325 | int n{ 0 }; | 325 | int _n{ 0 }; |
326 | { | 326 | { |
327 | std::lock_guard<std::mutex> _guard{ selfdestructMutex }; | 327 | std::lock_guard<std::mutex> _guard{ selfdestructMutex }; |
328 | Lane* _lane{ selfdestructFirst }; | 328 | Lane* _lane{ selfdestructFirst }; |
329 | while (_lane != SELFDESTRUCT_END) { | 329 | while (_lane != SELFDESTRUCT_END) { |
330 | if (_lane->cancelRequest != CancelRequest::None) | 330 | if (_lane->cancelRequest != CancelRequest::None) |
331 | ++n; | 331 | ++_n; |
332 | _lane = _lane->selfdestruct_next; | 332 | _lane = _lane->selfdestruct_next; |
333 | } | 333 | } |
334 | } | 334 | } |
335 | // if timeout elapsed, or we know all threads have acted, stop waiting | 335 | // if timeout elapsed, or we know all threads have acted, stop waiting |
336 | std::chrono::time_point<std::chrono::steady_clock> _now = std::chrono::steady_clock::now(); | 336 | std::chrono::time_point<std::chrono::steady_clock> _now = std::chrono::steady_clock::now(); |
337 | if (n == 0 || (_now >= _until)) { | 337 | if (_n == 0 || (_now >= _until)) { |
338 | DEBUGSPEW_CODE(fprintf(stderr, "%d uncancelled lane(s) remain after waiting %fs at process end.\n", n, shutdownTimeout_.count())); | 338 | DEBUGSPEW_CODE(DebugSpew(this) << _n << " uncancelled lane(s) remain after waiting " << shutdownTimeout_.count() << "s at process end." << std::endl); |
339 | break; | 339 | break; |
340 | } | 340 | } |
341 | } | 341 | } |
@@ -354,7 +354,7 @@ void Universe::terminateFreeRunningLanes(lua_State* L_, lua_Duration shutdownTim | |||
354 | Lane* _lane{ selfdestructFirst }; | 354 | Lane* _lane{ selfdestructFirst }; |
355 | if (_lane != SELFDESTRUCT_END) { | 355 | if (_lane != SELFDESTRUCT_END) { |
356 | // this causes a leak because we don't call U's destructor (which could be bad if the still running lanes are accessing it) | 356 | // this causes a leak because we don't call U's destructor (which could be bad if the still running lanes are accessing it) |
357 | raise_luaL_error(L_, "Zombie thread %s refuses to die!", _lane->debugName.data()); | 357 | raise_luaL_error(L_, "Zombie thread " STRINGVIEW_FMT " refuses to die!", _lane->debugName.size(), _lane->debugName.data()); |
358 | } | 358 | } |
359 | } | 359 | } |
360 | } | 360 | } |