From d468b693d79ddb416c45669e5ca8400cbdc34e85 Mon Sep 17 00:00:00 2001 From: Benoit Germain Date: Wed, 22 May 2024 18:15:13 +0200 Subject: DEBUGSPEW fprintf(stderr) → std::cerr MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/cancel.cpp | 2 +- src/compat.h | 9 +++++++ src/debugspew.h | 19 +++++++++---- src/deep.cpp | 4 +-- src/intercopycontext.cpp | 70 ++++++++++++++++++++++++------------------------ src/lane.cpp | 14 +++++----- src/lanes.cpp | 44 +++++++++++++++--------------- src/state.cpp | 56 +++++++++++++++++--------------------- src/tools.cpp | 33 ++++++++++++----------- src/tools.h | 2 +- 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) [[nodiscard]] static void cancel_hook(lua_State* L_, [[maybe_unused]] lua_Debug* ar_) { - DEBUGSPEW_CODE(fprintf(stderr, "cancel_hook\n")); + DEBUGSPEW_CODE(DebugSpew(nullptr) << "cancel_hook" << std::endl); if (cancel_test(L_) != CancelRequest::None) { lua_sethook(L_, nullptr, 0, 0); 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_); // ################################################################################################# +#define STRINGVIEW_FMT "%.*s" + // a replacement of lua_tolstring [[nodiscard]] inline std::string_view lua_tostringview(lua_State* L_, int idx_) { @@ -255,6 +257,13 @@ LuaType luaG_getmodule(lua_State* L_, char const* name_); return std::string_view{ _str, _len }; } +[[nodiscard]] inline std::string_view luaL_checkstringview(lua_State* L_, int idx_) +{ + size_t _len{ 0 }; + char const* _str{ luaL_checklstring(L_, idx_, &_len) }; + return std::string_view{ _str, _len }; +} + [[nodiscard]] inline std::string_view lua_pushstringview(lua_State* L_, std::string_view const& str_) { #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 @@ #include "lanesconf.h" #include "universe.h" +#include + // ################################################################################################# #if USE_DEBUG_SPEW() @@ -10,7 +12,7 @@ class DebugSpewIndentScope { private: - Universe* const U; + Universe* const U{}; public: static char const* const debugspew_indent; @@ -18,21 +20,28 @@ class DebugSpewIndentScope DebugSpewIndentScope(Universe* U_) : U{ U_ } { - if (U) + if (U) { U->debugspewIndentDepth.fetch_add(1, std::memory_order_relaxed); + } } ~DebugSpewIndentScope() { - if (U) + if (U) { U->debugspewIndentDepth.fetch_sub(1, std::memory_order_relaxed); + } } }; // ################################################################################################# -#define INDENT_BEGIN "%.*s " -#define INDENT_END(U_) , (U_ ? U_->debugspewIndentDepth.load(std::memory_order_relaxed) : 0), DebugSpewIndentScope::debugspew_indent +inline auto& DebugSpew(Universe const* const U_) +{ + if (!U_) { + return std::cerr; + } + return std::cerr << std::string_view{ DebugSpewIndentScope::debugspew_indent, static_cast(U_->debugspewIndentDepth.load(std::memory_order_relaxed)) } << " "; +} #define DEBUGSPEW_CODE(_code) _code #define DEBUGSPEW_OR_NOT(a_, b_) a_ #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_, lua_getglobal(L_, "require"); // L_: DPC proxy metatable require() // check that the module is already loaded (or being loaded, we are happy either way) if (lua_isfunction(L_, -1)) { - lua_pushlstring(L_, _modname.data(), _modname.size()); // L_: DPC proxy metatable require() "module" + std::ignore = lua_pushstringview(L_, _modname); // L_: DPC proxy metatable require() "module" if (luaG_getfield(L_, LUA_REGISTRYINDEX, LUA_LOADED_TABLE) == LuaType::TABLE) { // L_: DPC proxy metatable require() "module" _R._LOADED lua_pushvalue(L_, -2); // L_: DPC proxy metatable require() "module" _R._LOADED "module" 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_, LuaError const _require_result{ lua_pcall(L_, 1, 0, 0) }; // L_: DPC proxy metatable error? if (_require_result != LuaError::OK) { // failed, return the error message - lua_pushfstring(L_, "error while requiring '%s' identified by DeepFactory::moduleName: ", _modname.data()); + lua_pushfstring(L_, "error while requiring '" STRINGVIEW_FMT "' identified by DeepFactory::moduleName: ", _modname.size(), _modname.data()); lua_insert(L_, -2); // L_: DPC proxy metatable prefix error lua_concat(L_, 2); // L_: DPC proxy metatable error 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. lua_rawget(L1, -2); // L1: ... v ... {} "f.q.n" } std::string_view _fqn{ lua_tostringview(L1, -1) }; - DEBUGSPEW_CODE(Universe* const _U = universe_get(L1)); - DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "function [C] %s \n" INDENT_END(_U), _fqn.data())); + DEBUGSPEW_CODE(DebugSpew(universe_get(L1)) << "function [C] " << _fqn << std::endl); // popping doesn't invalidate the pointer since this is an interned string gotten from the lookup database lua_pop(L1, (mode == LookupMode::FromKeeper) ? 1 : 2); // L1: ... v ... STACK_CHECK(L1, 0); @@ -220,7 +219,7 @@ void InterCopyContext::copy_func() const // fills 'fname' 'namewhat' and 'linedefined', pops function lua_getinfo(L1, ">nS", &_ar); // L1: ... b _fname = _ar.namewhat; - DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "FNAME: %s @ %d" INDENT_END(U), _ar.short_src, _ar.linedefined)); // just gives nullptr + DEBUGSPEW_CODE(DebugSpew(U) << "FNAME: " << _ar.short_src << " @ " << _ar.linedefined << std::endl); } #endif // LOG_FUNC_INFO { @@ -267,15 +266,15 @@ void InterCopyContext::copy_func() const lua_pushglobaltable(L1); // L1: ... _G #endif // LUA_VERSION_NUM for (_n = 0; (_c.name = lua_getupvalue(L1, L1_i, 1 + _n)) != nullptr; ++_n) { // L1: ... _G up[n] - DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "UPNAME[%d]: %s -> " INDENT_END(U), _n, _c.name)); + DEBUGSPEW_CODE(DebugSpew(U) << "UPNAME[" << _n << "]: " << _c.name << " -> "); #if LUA_VERSION_NUM >= 502 if (lua_rawequal(L1, -1, -2)) { // is the upvalue equal to the global table? - DEBUGSPEW_CODE(fprintf(stderr, "pushing destination global scope\n")); + DEBUGSPEW_CODE(DebugSpew(nullptr) << "pushing destination global scope" << std::endl); lua_pushglobaltable(L2); // L2: ... {cache} ... function } else #endif // LUA_VERSION_NUM { - DEBUGSPEW_CODE(fprintf(stderr, "copying value\n")); + DEBUGSPEW_CODE(DebugSpew(nullptr) << "copying value" << std::endl); _c.L1_i = SourceIndex{ lua_gettop(L1) }; if (!_c.inter_copy_one()) { // L2: ... {cache} ... function raise_luaL_error(getErrL(), "Cannot copy upvalue type '%s'", luaL_typename(L1, -1)); @@ -323,7 +322,7 @@ void InterCopyContext::lookup_native_func() const case LookupMode::ToKeeper: // push a sentinel closure that holds the lookup name as upvalue - lua_pushlstring(L2, _fqn.data(), _fqn.size()); // L1: ... f ... L2: "f.q.n" + std::ignore = lua_pushstringview(L2, _fqn); // L1: ... f ... L2: "f.q.n" lua_pushcclosure(L2, func_lookup_sentinel, 1); // L1: ... f ... L2: f break; @@ -332,7 +331,7 @@ void InterCopyContext::lookup_native_func() const kLookupRegKey.pushValue(L2); // L1: ... f ... L2: {} STACK_CHECK(L2, 1); LUA_ASSERT(L1, lua_istable(L2, -1)); - lua_pushlstring(L2, _fqn.data(), _fqn.size()); // L1: ... f ... L2: {} "f.q.n" + std::ignore = lua_pushstringview(L2, _fqn); // L1: ... f ... L2: {} "f.q.n" lua_rawget(L2, -2); // L1: ... f ... L2: {} f // nil means we don't know how to transfer stuff: user should do something // anything other than function or table should not happen! @@ -342,14 +341,14 @@ void InterCopyContext::lookup_native_func() const lua_pop(L1, 1); // L1: ... f ... lua_getglobal(L2, "decoda_name"); // L1: ... f ... L2: {} f decoda_name char const* const _to{ lua_tostring(L2, -1) }; - lua_pop(L2, 1); // L2: {} f + lua_pop(L2, 1); // L2: {} f // 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 raise_luaL_error( getErrL(), - "%s%s: function '%s' not found in %s destination transfer database.", + "%s%s: function '" STRINGVIEW_FMT "' not found in %s destination transfer database.", lua_isnil(L2, -1) ? "" : "INTERNAL ERROR IN ", _from ? _from : "main", - _fqn.data(), + _fqn.size(), _fqn.data(), _to ? _to : "main"); return; } @@ -398,7 +397,7 @@ void InterCopyContext::copy_cached_func() const // push a light userdata uniquely representing the function lua_pushlightuserdata(L2, _aspointer); // L2: ... {cache} ... p - // fprintf( stderr, "<< ID: %s >>\n", lua_tostring( L2, -1)); + //DEBUGSPEW_CODE(DebugSpew(U) << "<< ID: " << lua_tostringview(L2, -1) << " >>" << std::endl); lua_pushvalue(L2, -1); // L2: ... {cache} ... p p lua_rawget(L2, L2_cache_i); // L2: ... {cache} ... p function|nil|true @@ -443,7 +442,7 @@ void InterCopyContext::copy_cached_func() const case LookupMode::ToKeeper: // push a sentinel closure that holds the lookup name as upvalue - lua_pushlstring(L2, _fqn.data(), _fqn.size()); // L1: ... t ... L2: "f.q.n" + std::ignore = lua_pushstringview(L2, _fqn); // L1: ... t ... L2: "f.q.n" lua_pushcclosure(L2, table_lookup_sentinel, 1); // L1: ... t ... L2: f break; @@ -452,7 +451,7 @@ void InterCopyContext::copy_cached_func() const kLookupRegKey.pushValue(L2); // L1: ... t ... L2: {} STACK_CHECK(L2, 1); LUA_ASSERT(L1, lua_istable(L2, -1)); - lua_pushlstring(L2, _fqn.data(), _fqn.size()); // L2: {} "f.q.n" + std::ignore = lua_pushstringview(L2, _fqn); // L2: {} "f.q.n" lua_rawget(L2, -2); // L2: {} t // we accept destination lookup failures in the case of transfering the Lanes body function (this will result in the source table being cloned instead) // 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 std::string_view const _key{ lua_tostringview(L1, _key_i) }; size_t const _bufLen{ strlen(name) + _key.size() + 2 }; // +2 for separator dot and terminating 0 _valPath = static_cast(alloca(_bufLen)); - sprintf(_valPath, "%s.%*s", name, static_cast(_key.size()), _key.data()); + sprintf(_valPath, "%s." STRINGVIEW_FMT, name, (int) _key.size(), _key.data()); } #if defined LUA_LNUM || LUA_VERSION_NUM >= 503 else if (lua_isinteger(L1, _key_i)) { @@ -607,7 +606,7 @@ void InterCopyContext::inter_copy_keyvaluepair() const // push a light userdata uniquely representing the table lua_pushlightuserdata(L2, const_cast(_p)); // L1: ... t ... L2: ... p - // fprintf(stderr, "<< ID: %s >>\n", lua_tostring(L2, -1)); + //DEBUGSPEW_CODE(DebugSpew(U) << "<< ID: " << lua_tostringview(L2, -1) << " >>" << std::endl); lua_rawget(L2, L2_cache_i); // L1: ... t ... L2: ... {cached|nil} bool const _not_found_in_cache{ lua_isnil(L2, -1) }; @@ -783,7 +782,7 @@ void InterCopyContext::inter_copy_keyvaluepair() const [[nodiscard]] bool InterCopyContext::inter_copy_boolean() const { int const _v{ lua_toboolean(L1, L1_i) }; - DEBUGSPEW_CODE(fprintf(stderr, "%s\n", _v ? "true" : "false")); + DEBUGSPEW_CODE(DebugSpew(nullptr) << (_v ? "true" : "false") << std::endl); lua_pushboolean(L2, _v); return true; } @@ -798,7 +797,7 @@ void InterCopyContext::inter_copy_keyvaluepair() const STACK_CHECK_START_REL(L1, 0); STACK_CHECK_START_REL(L2, 0); - DEBUGSPEW_CODE(fprintf(stderr, "FUNCTION %s\n", name)); + DEBUGSPEW_CODE(DebugSpew(nullptr) << "FUNCTION " << name << std::endl); if (lua_tocfunction(L1, L1_i) == userdata_clone_sentinel) { // we are actually copying a clonable full userdata from a keeper // clone the full userdata again @@ -873,9 +872,9 @@ void InterCopyContext::inter_copy_keyvaluepair() const // clone:__lanesclone(dest, source, size) lua_call(L2, 3, 0); // L2: ... u } else { // regular function - DEBUGSPEW_CODE(fprintf(stderr, "FUNCTION %s\n", name)); + DEBUGSPEW_CODE(DebugSpew(U) << "FUNCTION " << name << std::endl); DEBUGSPEW_CODE(DebugSpewIndentScope _scope{ U }); - copy_cached_func(); // L2: ... f + copy_cached_func(); // L2: ... f } STACK_CHECK(L2, 1); STACK_CHECK(L1, 0); @@ -887,7 +886,8 @@ void InterCopyContext::inter_copy_keyvaluepair() const [[nodiscard]] bool InterCopyContext::inter_copy_lightuserdata() const { void* const _p{ lua_touserdata(L1, L1_i) }; - DEBUGSPEW_CODE(fprintf(stderr, "%p\n", _p)); + // TODO: recognize and print known UniqueKey names here + DEBUGSPEW_CODE(DebugSpew(nullptr) << _p << std::endl); // when copying a nil sentinel in a non-keeper, write a nil in the destination if (mode != LookupMode::ToKeeper && kNilSentinel.equals(L1, L1_i)) { lua_pushnil(L2); @@ -921,13 +921,13 @@ void InterCopyContext::inter_copy_keyvaluepair() const #if defined LUA_LNUM || LUA_VERSION_NUM >= 503 if (lua_isinteger(L1, L1_i)) { lua_Integer const _v{ lua_tointeger(L1, L1_i) }; - DEBUGSPEW_CODE(fprintf(stderr, LUA_INTEGER_FMT "\n", _v)); + DEBUGSPEW_CODE(DebugSpew(nullptr) << _v << std::endl); lua_pushinteger(L2, _v); } else #endif // defined LUA_LNUM || LUA_VERSION_NUM >= 503 { lua_Number const _v{ lua_tonumber(L1, L1_i) }; - DEBUGSPEW_CODE(fprintf(stderr, LUA_NUMBER_FMT "\n", _v)); + DEBUGSPEW_CODE(DebugSpew(nullptr) << _v << std::endl); lua_pushnumber(L2, _v); } return true; @@ -938,8 +938,8 @@ void InterCopyContext::inter_copy_keyvaluepair() const [[nodiscard]] bool InterCopyContext::inter_copy_string() const { std::string_view const _s{ lua_tostringview(L1, L1_i) }; - DEBUGSPEW_CODE(fprintf(stderr, "'%s'\n", _s.data())); - lua_pushlstring(L2, _s.data(), _s.size()); + DEBUGSPEW_CODE(DebugSpew(nullptr) << "'" << _s << "'" << std::endl); + std::ignore = lua_pushstringview(L2, _s); return true; } @@ -953,7 +953,7 @@ void InterCopyContext::inter_copy_keyvaluepair() const STACK_CHECK_START_REL(L1, 0); STACK_CHECK_START_REL(L2, 0); - DEBUGSPEW_CODE(fprintf(stderr, "TABLE %s\n", name)); + DEBUGSPEW_CODE(DebugSpew(nullptr) << "TABLE " << name << std::endl); /* * 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 STACK_CHECK(L2, 0); // Allow only deep userdata entities to be copied across - DEBUGSPEW_CODE(fprintf(stderr, "USERDATA\n")); + DEBUGSPEW_CODE(DebugSpew(nullptr) << "USERDATA" << std::endl); if (tryCopyDeep()) { STACK_CHECK(L1, 0); STACK_CHECK(L2, 1); @@ -1084,18 +1084,18 @@ static char const* vt_names[] = { STACK_CHECK_START_REL(L1, 0); STACK_CHECK_START_REL(L2, 0); - DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "inter_copy_one()\n" INDENT_END(U))); + DEBUGSPEW_CODE(DebugSpew(U) << "inter_copy_one()" << std::endl); DEBUGSPEW_CODE(DebugSpewIndentScope _scope{ U }); LuaType _val_type{ lua_type_as_enum(L1, L1_i) }; - DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "%s %s: " INDENT_END(U), lua_type_names[static_cast(_val_type)], vt_names[static_cast(vt)])); + DEBUGSPEW_CODE(DebugSpew(U) << lua_type_names[static_cast(_val_type)] << " " << vt_names[static_cast(vt)] << ": "); // Non-POD can be skipped if its metatable contains { __lanesignore = true } if (((1 << static_cast(_val_type)) & kPODmask) == 0) { if (lua_getmetatable(L1, L1_i)) { // L1: ... mt LuaType const _type{ luaG_getfield(L1, -1, "__lanesignore") }; // L1: ... mt ignore? if (_type == LuaType::BOOLEAN && lua_toboolean(L1, -1)) { - DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "__lanesignore -> LUA_TNIL\n" INDENT_END(U))); + DEBUGSPEW_CODE(DebugSpew(U) << "__lanesignore -> LUA_TNIL" << std::endl); _val_type = LuaType::NIL; } lua_pop(L1, 2); // L1: ... @@ -1155,7 +1155,7 @@ static char const* vt_names[] = { // else raise an error in whichever state is not a keeper [[nodiscard]] InterCopyResult InterCopyContext::inter_copy_package() const { - DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "InterCopyContext::inter_copy_package()\n" INDENT_END(U))); + DEBUGSPEW_CODE(DebugSpew(U) << "InterCopyContext::inter_copy_package()" << std::endl); class OnExit { @@ -1189,7 +1189,7 @@ static char const* vt_names[] = { return InterCopyResult::Error; } if (luaG_getmodule(L2, LUA_LOADLIBNAME) == LuaType::NIL) { // package library not loaded: do nothing - DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "'package' not loaded, nothing to do\n" INDENT_END(U))); + DEBUGSPEW_CODE(DebugSpew(U) << "'package' not loaded, nothing to do" << std::endl); STACK_CHECK(L1, 0); return InterCopyResult::Success; } @@ -1204,7 +1204,7 @@ static char const* vt_names[] = { if (!_entry) { continue; } - DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "package.%s\n" INDENT_END(U), _entry)); + DEBUGSPEW_CODE(DebugSpew(U) << "package." << _entry << std::endl); if (luaG_getfield(L1, L1_i, _entry) == LuaType::NIL) { lua_pop(L1, 1); } else { @@ -1238,13 +1238,13 @@ static char const* vt_names[] = { { LUA_ASSERT(L1, vt == VT::NORMAL); - DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "InterCopyContext::inter_copy()\n" INDENT_END(U))); + DEBUGSPEW_CODE(DebugSpew(U) << "InterCopyContext::inter_copy()" << std::endl); DEBUGSPEW_CODE(DebugSpewIndentScope _scope{ U }); int const _top_L1{ lua_gettop(L1) }; if (n_ > _top_L1) { // requesting to copy more than is available? - DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "nothing to copy()\n" INDENT_END(U))); + DEBUGSPEW_CODE(DebugSpew(U) << "nothing to copy" << std::endl); return InterCopyResult::NotEnoughValues; } 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) break; default: - DEBUGSPEW_CODE(fprintf(stderr, "Status: %d\n", _lane->status)); + DEBUGSPEW_CODE(DebugSpew(nullptr) << "Unknown Lane status: " << static_cast(_lane->status) << std::endl); LUA_ASSERT(L_, false); _ret = 0; } @@ -278,7 +278,7 @@ static int thread_index_number(lua_State* L_) lua_replace(L_, -3); // L_: lane n error() "error" lua_pushinteger(L_, 3); // L_: lane n error() "error" 3 lua_call(L_, 2, 0); // error(tostring(errstring), 3) -> doesn't return // L_: lane n - raise_luaL_error(L_, "%s: should not get here!", _lane->debugName.data()); + raise_luaL_error(L_, STRINGVIEW_FMT ": should not get here!", _lane->debugName.size(), _lane->debugName.data()); } else { lua_pop(L_, 1); // L_: lane n {uv} } @@ -316,7 +316,7 @@ static int thread_index_string(lua_State* L_) lua_rawget(L_, -2); // L_: mt value // only "cancel" and "join" are registered as functions, any other string will raise an error if (!lua_iscfunction(L_, -1)) { - raise_luaL_error(L_, "can't index a lane with '%s'", _keystr.data()); + raise_luaL_error(L_, "can't index a lane with '" STRINGVIEW_FMT "'", _keystr.size(), _keystr.data()); } return 1; } @@ -345,7 +345,7 @@ static LUAG_FUNC(thread_index) lua_pushvalue(L_, kKey); // L_: mt error "Unknown key: " k lua_concat(L_, 2); // L_: mt error "Unknown key: " lua_call(L_, 1, 0); // error( "Unknown key: " .. key) -> doesn't return // L_: mt - raise_luaL_error(L_, "%s[%s]: should not get here!", _lane->debugName.data(), lua_typename(L_, lua_type(L_, kKey))); + raise_luaL_error(L_, STRINGVIEW_FMT "[%s]: should not get here!", _lane->debugName.size(), _lane->debugName.data(), lua_typename(L_, lua_type(L_, kKey))); } } @@ -677,11 +677,11 @@ static void lane_main(Lane* lane_) // in case of error and if it exists, fetch stack trace from registry and push it push_stack_trace(_L, lane_->errorTraceLevel, _rc, 1); // L: retvals|error [trace] - 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)))); + 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); // Call finalizers, if the script has set them up. // LuaError const _rc2{ run_finalizers(_L, lane_->errorTraceLevel, _rc) }; - DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "Lane %p finalizer: %s\n" INDENT_END(_U), _L, get_errcode_name(_rc2))); + DEBUGSPEW_CODE(DebugSpew(_U) << "Lane " << _L << " finalizer: " << get_errcode_name(_rc2) << std::endl); if (_rc2 != LuaError::OK) { // Error within a finalizer! // the finalizer generated an error, and left its own error message [and stack trace] on the stack _rc = _rc2; // we're overruling the earlier script error or normal return @@ -839,7 +839,7 @@ void Lane::changeDebugName(int nameIdx_) (errorTraceLevel == ErrorTraceLevel::Minimal) ? "minimal" : (errorTraceLevel == ErrorTraceLevel::Basic) ? "basic" : (errorTraceLevel == ErrorTraceLevel::Extended) ? "extended" : - nullptr + "" }; return _str; } 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) // upvalue[1]: _G.require LUAG_FUNC(require) { - char const* _name{ lua_tostring(L_, 1) }; // L_: "name" ... + std::string_view const _name{ lua_tostringview(L_, 1) }; // L_: "name" ... int const _nargs{ lua_gettop(L_) }; DEBUGSPEW_CODE(Universe * _U{ universe_get(L_) }); STACK_CHECK_START_REL(L_, 0); - DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "lanes.require %s BEGIN\n" INDENT_END(_U), _name)); + DEBUGSPEW_CODE(DebugSpew(_U) << "lanes.require '" << _name << "' BEGIN" << std::endl); DEBUGSPEW_CODE(DebugSpewIndentScope _scope{ _U }); lua_pushvalue(L_, lua_upvalueindex(1)); // L_: "name" ... require lua_insert(L_, 1); // L_: require "name" ... lua_call(L_, _nargs, 1); // L_: module populate_func_lookup_table(L_, -1, _name); - DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "lanes.require %s END\n" INDENT_END(_U), _name)); + DEBUGSPEW_CODE(DebugSpew(_U) << "lanes.require '" << _name << "' END" << std::endl); STACK_CHECK(L_, 0); return 1; } @@ -188,17 +188,17 @@ LUAG_FUNC(require) // lanes.register( "modname", module) LUAG_FUNC(register) { - char const* _name{ luaL_checkstring(L_, 1) }; + std::string_view const _name{ luaL_checkstringview(L_, 1) }; LuaType const _mod_type{ lua_type_as_enum(L_, 2) }; // ignore extra parameters, just in case lua_settop(L_, 2); luaL_argcheck(L_, (_mod_type == LuaType::TABLE) || (_mod_type == LuaType::FUNCTION), 2, "unexpected module type"); DEBUGSPEW_CODE(Universe* _U = universe_get(L_)); STACK_CHECK_START_REL(L_, 0); // "name" mod_table - DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "lanes.register %s BEGIN\n" INDENT_END(_U), _name)); + DEBUGSPEW_CODE(DebugSpew(_U) << "lanes.register '" << _name << "' BEGIN" << std::endl); DEBUGSPEW_CODE(DebugSpewIndentScope _scope{ _U }); populate_func_lookup_table(L_, -1, _name); - DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "lanes.register %s END\n" INDENT_END(_U), _name)); + DEBUGSPEW_CODE(DebugSpew(_U) << "lanes.register '" << _name << "' END" << std::endl); STACK_CHECK(L_, 0); return 0; } @@ -236,7 +236,7 @@ LUAG_FUNC(lane_new) LUA_ASSERT(L_, _nargs >= 0); Universe* const _U{ universe_get(L_) }; - DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "lane_new: setup\n" INDENT_END(_U))); + DEBUGSPEW_CODE(DebugSpew(_U) << "lane_new: setup" << std::endl); char const* const _libs_str{ lua_tostring(L_, kLibsIdx) }; lua_State* const _L2{ luaG_newstate(_U, SourceState{ L_ }, _libs_str) }; // L_: [fixed] ... L2: @@ -288,7 +288,7 @@ LUAG_FUNC(lane_new) private: void prepareUserData() { - DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "lane_new: preparing lane userdata\n" INDENT_END(lane->U))); + DEBUGSPEW_CODE(DebugSpew(lane->U) << "lane_new: preparing lane userdata" << std::endl); STACK_CHECK_START_REL(L, 0); // a Lane full userdata needs a single uservalue Lane** const _ud{ lua_newuserdatauv(L, 1) }; // L: ... lane @@ -344,7 +344,7 @@ LUAG_FUNC(lane_new) } } onExit{ L_, _lane}; // launch the thread early, it will sync with a std::latch to parallelize OS thread warmup and L2 preparation - DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "lane_new: launching thread\n" INDENT_END(_U))); + DEBUGSPEW_CODE(DebugSpew(_U) << "lane_new: launching thread" << std::endl); // public Lanes API accepts a generic range -3/+3 // that will be remapped into the platform-specific scheduler priority scheme // On some platforms, -3 is equivalent to -2 and +3 to +2 @@ -371,7 +371,7 @@ LUAG_FUNC(lane_new) // package int const _package_idx{ lua_isnoneornil(L_, kPackIdx) ? 0 : kPackIdx }; if (_package_idx != 0) { - DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "lane_new: update 'package'\n" INDENT_END(_U))); + DEBUGSPEW_CODE(DebugSpew(_U) << "lane_new: update 'package'" << std::endl); // when copying with mode LookupMode::LaneBody, should raise an error in case of problem, not leave it one the stack InterCopyContext c{ _U, DestState{ _L2 }, SourceState{ L_ }, {}, SourceIndex{ _package_idx }, {}, {}, {} }; [[maybe_unused]] InterCopyResult const ret{ c.inter_copy_package() }; @@ -382,7 +382,7 @@ LUAG_FUNC(lane_new) int const _required_idx{ lua_isnoneornil(L_, kRequIdx) ? 0 : kRequIdx }; if (_required_idx != 0) { int _nbRequired{ 1 }; - DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "lane_new: require 'required' list\n" INDENT_END(_U))); + DEBUGSPEW_CODE(DebugSpew(_U) << "lane_new: process 'required' list" << std::endl); DEBUGSPEW_CODE(DebugSpewIndentScope _scope{ _U }); // should not happen, was checked in lanes.lua before calling lane_new() if (lua_type(L_, _required_idx) != LUA_TTABLE) { @@ -396,7 +396,7 @@ LUAG_FUNC(lane_new) } else { // require the module in the target state, and populate the lookup table there too std::string_view const _name{ lua_tostringview(L_, -1) }; - DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "lane_new: require '%s'\n" INDENT_END(_U), _name.data())); + DEBUGSPEW_CODE(DebugSpew(_U) << "lane_new: require '" << _name << "'" << std::endl); // require the module in the target lane lua_getglobal(_L2, "require"); // L_: [fixed] args... n "modname" L2: require()? @@ -404,7 +404,7 @@ LUAG_FUNC(lane_new) lua_pop(_L2, 1); // L_: [fixed] args... n "modname" L2: raise_luaL_error(L_, "cannot pre-require modules without loading 'package' library first"); } else { - lua_pushlstring(_L2, _name.data(), _name.size()); // L_: [fixed] args... n "modname" L2: require() name + std::ignore = lua_pushstringview(_L2, _name); // L_: [fixed] args... n "modname" L2: require() name LuaError const _rc{ lua_pcall(_L2, 1, 1, 0) }; // L_: [fixed] args... n "modname" L2: ret/errcode if (_rc != LuaError::OK) { // propagate error to main state if any @@ -414,7 +414,7 @@ LUAG_FUNC(lane_new) } // here the module was successfully required // L_: [fixed] args... n "modname" L2: ret // after requiring the module, register the functions it exported in our name<->function database - populate_func_lookup_table(_L2, -1, _name.data()); + populate_func_lookup_table(_L2, -1, _name); lua_pop(_L2, 1); // L_: [fixed] args... n "modname" L2: } } @@ -430,7 +430,7 @@ LUAG_FUNC(lane_new) // int const _globals_idx{ lua_isnoneornil(L_, kGlobIdx) ? 0 : kGlobIdx }; if (_globals_idx != 0) { - DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "lane_new: transfer globals\n" INDENT_END(_U))); + DEBUGSPEW_CODE(DebugSpew(_U) << "lane_new: transfer globals" << std::endl); if (!lua_istable(L_, _globals_idx)) { raise_luaL_error(L_, "Expected table, got %s", luaL_typename(L_, _globals_idx)); } @@ -455,7 +455,7 @@ LUAG_FUNC(lane_new) [[maybe_unused]] int const errorHandlerCount{ _lane->pushErrorHandler() }; // L_: [fixed] args... L2: eh? LuaType const _func_type{ lua_type_as_enum(L_, kFuncIdx) }; if (_func_type == LuaType::FUNCTION) { - DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "lane_new: transfer lane body\n" INDENT_END(_U))); + DEBUGSPEW_CODE(DebugSpew(_U) << "lane_new: transfer lane body" << std::endl); DEBUGSPEW_CODE(DebugSpewIndentScope _scope{ _U }); lua_pushvalue(L_, kFuncIdx); // L_: [fixed] args... func L2: eh? InterCopyContext _c{ _U, DestState{ _L2 }, SourceState{ L_ }, {}, {}, {}, {}, {} }; @@ -464,7 +464,7 @@ LUAG_FUNC(lane_new) raise_luaL_error(L_, "tried to copy unsupported types"); } } else if (_func_type == LuaType::STRING) { - DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "lane_new: compile lane body\n" INDENT_END(_U))); + DEBUGSPEW_CODE(DebugSpew(_U) << "lane_new: compile lane body" << std::endl); // compile the string if (luaL_loadstring(_L2, lua_tostring(L_, kFuncIdx)) != 0) { // L_: [fixed] args... L2: eh? func raise_luaL_error(L_, "error when parsing lane function code"); @@ -478,7 +478,7 @@ LUAG_FUNC(lane_new) // revive arguments if (_nargs > 0) { - DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "lane_new: transfer lane arguments\n" INDENT_END(_U))); + DEBUGSPEW_CODE(DebugSpew(_U) << "lane_new: transfer lane arguments" << std::endl); DEBUGSPEW_CODE(DebugSpewIndentScope _scope{ _U }); InterCopyContext _c{ _U, DestState{ _L2 }, SourceState{ L_ }, {}, {}, {}, {}, {} }; InterCopyResult const res{ _c.inter_move(_nargs) }; // L_: [fixed] L2: eh? func args... @@ -627,13 +627,13 @@ LUAG_FUNC(configure) Universe* _U{ universe_get(L_) }; bool const _from_master_state{ _U == nullptr }; - char const* const _name{ luaL_checkstring(L_, lua_upvalueindex(1)) }; + std::string_view const _name{ luaL_checkstringview(L_, lua_upvalueindex(1)) }; LUA_ASSERT(L_, lua_type(L_, 1) == LUA_TTABLE); STACK_GROW(L_, 4); STACK_CHECK_START_ABS(L_, 1); // L_: settings - DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "%p: lanes.configure() BEGIN\n" INDENT_END(_U), L_)); + DEBUGSPEW_CODE(DebugSpew(_U) << L_ << ": lanes.configure() BEGIN" << std::endl); DEBUGSPEW_CODE(DebugSpewIndentScope _scope{ _U }); if (_U == nullptr) { @@ -757,7 +757,7 @@ LUAG_FUNC(configure) // because we will do it after on_state_create() is called, // and we don't want to skip _G because of caching in case globals are created then lua_pushglobaltable(L_); // L_: settings M _G - populate_func_lookup_table(L_, -1, nullptr); + populate_func_lookup_table(L_, -1, {}); lua_pop(L_, 1); // L_: settings M } lua_pop(L_, 1); // L_: settings @@ -765,7 +765,7 @@ LUAG_FUNC(configure) // set _R[kConfigRegKey] = settings kConfigRegKey.setValue(L_, [](lua_State* L_) { lua_pushvalue(L_, -2); }); STACK_CHECK(L_, 1); - DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "%p: lanes.configure() END\n" INDENT_END(_U), L_)); + DEBUGSPEW_CODE(DebugSpew(_U) << L_ << ": lanes.configure() END" << std::endl); // Return the settings table return 1; } 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. { int const _args{ lua_gettop(L_) }; // L_: args Universe* const _U{ universe_get(L_) }; - // char const* modname = luaL_checkstring(L_, 1); + //[[maybe_unused]] std::string_view const _modname{ luaL_checkstringview(L_, 1) }; STACK_GROW(L_, 1); @@ -88,7 +88,7 @@ void serialize_require(DEBUGSPEW_PARAM_COMMA(Universe* U_) lua_State* L_) { STACK_GROW(L_, 1); STACK_CHECK_START_REL(L_, 0); - DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "serializing require()\n" INDENT_END(U_))); + DEBUGSPEW_CODE(DebugSpew(U_) << "serializing require()" << std::endl); // Check 'require' is there and not already wrapped; if not, do nothing // @@ -155,23 +155,23 @@ namespace global // ################################################################################################# -static void open1lib(DEBUGSPEW_PARAM_COMMA(Universe* U_) lua_State* L_, char const* name_, size_t len_) +static void open1lib(DEBUGSPEW_PARAM_COMMA(Universe* U_) lua_State* L_, std::string_view const& name_) { for (luaL_Reg const& _entry : global::sLibs) { - if (strncmp(name_, _entry.name, len_) == 0) { + if (name_ == _entry.name) { lua_CFunction const _libfunc{ _entry.func }; if (!_libfunc) { - continue; + break; } - name_ = _entry.name; // note that the provided name_ doesn't necessarily ends with '\0', hence len_ - DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "opening %.*s library\n" INDENT_END(U_), (int) len_, name_)); + std::string_view const _name{ _entry.name }; + DEBUGSPEW_CODE(DebugSpew(U_) << "opening '" << _name << "' library" << std::endl); STACK_CHECK_START_REL(L_, 0); // open the library as if through require(), and create a global as well if necessary (the library table is left on the stack) bool const isLanesCore{ _libfunc == require_lanes_core }; // don't want to create a global for "lanes.core" - luaL_requiref(L_, name_, _libfunc, !isLanesCore); // L_: {lib} + luaL_requiref(L_, _name.data(), _libfunc, !isLanesCore); // L_: {lib} // lanes.core doesn't declare a global, so scan it here and now if (isLanesCore) { - populate_func_lookup_table(L_, -1, name_); + populate_func_lookup_table(L_, -1, _name); } lua_pop(L_, 1); // L_: STACK_CHECK(L_, 0); @@ -182,14 +182,6 @@ static void open1lib(DEBUGSPEW_PARAM_COMMA(Universe* U_) lua_State* L_, char con // ################################################################################################# -template -static inline void open1lib(DEBUGSPEW_PARAM_COMMA(Universe* U_) lua_State* L_, char const (&name_)[N]) -{ - open1lib(DEBUGSPEW_PARAM_COMMA(U_) L_, name_, N - 1); -} - -// ################################################################################################# - // just like lua_xmove, args are (from, to) static void copy_one_time_settings(Universe* U_, SourceState L1_, DestState L2_) { @@ -199,7 +191,7 @@ static void copy_one_time_settings(Universe* U_, SourceState L1_, DestState L2_) STACK_CHECK_START_REL(L1_, 0); STACK_CHECK_START_REL(L2_, 0); - DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "copy_one_time_settings()\n" INDENT_END(U_))); + DEBUGSPEW_CODE(DebugSpew(U_) << "copy_one_time_settings()" << std::endl); kConfigRegKey.pushValue(L1_); // L1_: config // copy settings from from source to destination registry @@ -275,7 +267,7 @@ void CallOnStateCreate(Universe* U_, lua_State* L_, lua_State* from_, LookupMode { if (U_->onStateCreateFunc != nullptr) { STACK_CHECK_START_REL(L_, 0); - DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "calling on_state_create()\n" INDENT_END(U_))); + DEBUGSPEW_CODE(DebugSpew(U_) << "calling on_state_create()" << std::endl); if (U_->onStateCreateFunc != reinterpret_cast(InitializeOnStateCreate)) { // C function: recreate a closure in the new state, bypassing the lookup scheme lua_pushcfunction(L_, U_->onStateCreateFunc); // on_state_create() @@ -333,11 +325,11 @@ lua_State* luaG_newstate(Universe* U_, SourceState from_, char const* libs_) // neither libs (not even 'base') nor special init func: we are done if (libs_ == nullptr && U_->onStateCreateFunc == nullptr) { - DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "luaG_newstate(nullptr)\n" INDENT_END(U_))); + DEBUGSPEW_CODE(DebugSpew(U_) << "luaG_newstate(nullptr)" << std::endl); return _L; } - DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "luaG_newstate()\n" INDENT_END(U_))); + DEBUGSPEW_CODE(DebugSpew(U_) << "luaG_newstate()" << std::endl); DEBUGSPEW_CODE(DebugSpewIndentScope _scope{ U_ }); // 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_) // special "*" case (mainly to help with LuaJIT compatibility) // as we are called from luaopen_lanes_core() already, and that would deadlock if (libs_[0] == '*' && libs_[1] == 0) { - DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "opening ALL standard libraries\n" INDENT_END(U_))); + DEBUGSPEW_CODE(DebugSpew(U_) << "opening ALL standard libraries" << std::endl); luaL_openlibs(_L); // don't forget lanes.core for regular lane states open1lib(DEBUGSPEW_PARAM_COMMA(U_) _L, kLanesCoreLibName); libs_ = nullptr; // done with libs } else { - DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "opening base library\n" INDENT_END(U_))); + DEBUGSPEW_CODE(DebugSpew(U_) << "opening 'base' library" << std::endl); #if LUA_VERSION_NUM >= 502 // open base library the same way as in luaL_openlibs() luaL_requiref(_L, LUA_GNAME, luaopen_base, 1); @@ -373,17 +365,17 @@ lua_State* luaG_newstate(Universe* U_, SourceState from_, char const* libs_) // scan all libraries, open them one by one if (libs_) { - unsigned int len{ 0 }; - for (char const* p{ libs_ }; *p; p += len) { + unsigned int _len{ 0 }; + for (char const* _p{ libs_ }; *_p; _p += _len) { // skip delimiters ('.' can be part of name for "lanes.core") - while (*p && !isalnum(*p) && *p != '.') - ++p; + while (*_p && !isalnum(*_p) && *_p != '.') + ++_p; // skip name - len = 0; - while (isalnum(p[len]) || p[len] == '.') - ++len; + _len = 0; + while (isalnum(_p[_len]) || _p[_len] == '.') + ++_len; // open library - open1lib(DEBUGSPEW_PARAM_COMMA(U_) _L, p, len); + open1lib(DEBUGSPEW_PARAM_COMMA(U_) _L, { _p, _len }); } } lua_gc(_L, LUA_GCRESTART, 0); @@ -398,7 +390,7 @@ lua_State* luaG_newstate(Universe* U_, SourceState from_, char const* libs_) // after all this, register everything we find in our name<->function database lua_pushglobaltable(_L); // Lua 5.2 no longer has LUA_GLOBALSINDEX: we must push globals table on the stack STACK_CHECK(_L, 1); - populate_func_lookup_table(_L, -1, nullptr); + populate_func_lookup_table(_L, -1, {}); #if 1 && USE_DEBUG_SPEW() // 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 // slot 2 contains a table that, when concatenated, produces the fully qualified name of scanned elements in the table provided at slot _i int const _fqn{ ctxBase_ + 1 }; - DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "update_lookup_entry()\n" INDENT_END(U_))); + DEBUGSPEW_CODE(DebugSpew(U_) << "update_lookup_entry()" << std::endl); DEBUGSPEW_CODE(DebugSpewIndentScope _scope{ U_ }); STACK_CHECK_START_REL(L_, 0); @@ -154,7 +154,7 @@ static void update_lookup_entry(DEBUGSPEW_PARAM_COMMA(Universe* U_) lua_State* L // Therefore, when we encounter an object for which a name was previously registered, we need to select the names // based on some sorting order so that we end up with the same name in all databases whatever order the table walk yielded if (!_prevName.empty() && (_prevName.size() < _newName.size() || lua_lessthan(L_, -2, -1))) { - 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())); + DEBUGSPEW_CODE(DebugSpew(U_) << lua_typename(L_, lua_type(L_, -3)) << " '" << _newName << "' remains named '" << _prevName << "'" << std::endl); // the previous name is 'smaller' than the one we just generated: keep it! lua_pop(L_, 3); // L_: ... {bfc} k } else { @@ -168,7 +168,7 @@ static void update_lookup_entry(DEBUGSPEW_PARAM_COMMA(Universe* U_) lua_State* L } else { lua_remove(L_, -2); // L_: ... {bfc} k o "f.q.n" } - DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "%s '%s'\n" INDENT_END(U_), lua_typename(L_, lua_type(L_, -2)), _newName.data())); + DEBUGSPEW_CODE(DebugSpew(U_) << lua_typename(L_, lua_type(L_, -2)) << " '" << _newName << "'" << std::endl); // prepare the stack for database feed lua_pushvalue(L_, -1); // L_: ... {bfc} k o "f.q.n" "f.q.n" 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_) int const _fqn{ dbIdx_ + 1 }; // slot dbIdx_ + 2 contains a cache that stores all already visited tables to avoid infinite recursion loops int const _cache{ dbIdx_ + 2 }; - DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "populate_func_lookup_table_recur()\n" INDENT_END(U_))); + DEBUGSPEW_CODE(DebugSpew(U_) << "populate_func_lookup_table_recur()" << std::endl); DEBUGSPEW_CODE(DebugSpewIndentScope _scope{ U_ }); STACK_GROW(L_, 6); @@ -215,7 +215,7 @@ static void populate_func_lookup_table_recur(DEBUGSPEW_PARAM_COMMA(Universe* U_) lua_pop(L_, 1); // L_: ... {i_} STACK_CHECK(L_, 0); if (_visit_count > 0) { - DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "already visited\n" INDENT_END(U_))); + DEBUGSPEW_CODE(DebugSpew(U_) << "already visited" << std::endl); return; } @@ -262,8 +262,8 @@ static void populate_func_lookup_table_recur(DEBUGSPEW_PARAM_COMMA(Universe* U_) ++depth_; lua_pushnil(L_); // L_: ... {i_} {bfc} nil while (lua_next(L_, breadthFirstCache) != 0) { // L_: ... {i_} {bfc} k {} - DEBUGSPEW_CODE(char const* _key = (lua_type(L_, -2) == LUA_TSTRING) ? lua_tostring(L_, -2) : "not a string"); - DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "table '%s'\n" INDENT_END(U_), _key)); + DEBUGSPEW_CODE(std::string_view const _key{ (lua_type(L_, -2) == LUA_TSTRING) ? lua_tostringview(L_, -2) : std::string_view{ "" } }); + DEBUGSPEW_CODE(DebugSpew(U_) << "table '"<< _key <<"'" << std::endl); DEBUGSPEW_CODE(DebugSpewIndentScope _scope2{ U_ }); // un-visit this table in case we do need to process it lua_pushvalue(L_, -1); // L_: ... {i_} {bfc} k {} {} @@ -298,11 +298,12 @@ static void populate_func_lookup_table_recur(DEBUGSPEW_PARAM_COMMA(Universe* U_) // ################################################################################################# // create a "fully.qualified.name" <-> function equivalence database -void populate_func_lookup_table(lua_State* L_, int i_, char const* name_) +void populate_func_lookup_table(lua_State* const L_, int const i_, std::string_view const& name_) { int const _in_base = lua_absindex(L_, i_); DEBUGSPEW_CODE(Universe* _U = universe_get(L_)); - DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "%p: populate_func_lookup_table('%s')\n" INDENT_END(_U), L_, name_ ? name_ : "nullptr")); + std::string_view _name{ name_.empty() ? std::string_view{} : name_ }; + DEBUGSPEW_CODE(DebugSpew(_U) << L_ << ": populate_func_lookup_table('" << _name << "')" << std::endl); DEBUGSPEW_CODE(DebugSpewIndentScope _scope{ _U }); STACK_GROW(L_, 3); STACK_CHECK_START_REL(L_, 0); @@ -311,20 +312,22 @@ void populate_func_lookup_table(lua_State* L_, int i_, char const* name_) STACK_CHECK(L_, 1); LUA_ASSERT(L_, lua_istable(L_, -1)); if (lua_type(L_, _in_base) == LUA_TFUNCTION) { // for example when a module is a simple function - name_ = name_ ? name_ : "nullptr"; + if (_name.empty()) { + _name = "nullptr"; + } lua_pushvalue(L_, _in_base); // L_: {} f - lua_pushstring(L_, name_); // L_: {} f _name + std::ignore = lua_pushstringview(L_, _name); // L_: {} f name_ lua_rawset(L_, -3); // L_: {} - lua_pushstring(L_, name_); // L_: {} _name - lua_pushvalue(L_, _in_base); // L_: {} _name f + std::ignore = lua_pushstringview(L_, _name); // L_: {} name_ + lua_pushvalue(L_, _in_base); // L_: {} name_ f lua_rawset(L_, -3); // L_: {} lua_pop(L_, 1); // L_: } else if (lua_type(L_, _in_base) == LUA_TTABLE) { lua_newtable(L_); // L_: {} {fqn} int _startDepth{ 0 }; - if (name_) { + if (!_name.empty()) { STACK_CHECK(L_, 2); - lua_pushstring(L_, name_); // L_: {} {fqn} "name" + std::ignore = lua_pushstringview(L_, _name); // L_: {} {fqn} "name" // generate a name, and if we already had one name, keep whichever is the shorter lua_pushvalue(L_, _in_base); // L_: {} {fqn} "name" t 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 [[nodiscard]] int luaG_nameof(lua_State* L_); -void populate_func_lookup_table(lua_State* L_, int i_, char const* name_); +void populate_func_lookup_table(lua_State* const L_, int const i_, std::string_view const& name_); // ################################################################################################# 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 // give threads time to act on their cancel std::this_thread::yield(); // count the number of cancelled thread that didn't have the time to act yet - int n{ 0 }; + int _n{ 0 }; { std::lock_guard _guard{ selfdestructMutex }; Lane* _lane{ selfdestructFirst }; while (_lane != SELFDESTRUCT_END) { if (_lane->cancelRequest != CancelRequest::None) - ++n; + ++_n; _lane = _lane->selfdestruct_next; } } // if timeout elapsed, or we know all threads have acted, stop waiting std::chrono::time_point _now = std::chrono::steady_clock::now(); - if (n == 0 || (_now >= _until)) { - DEBUGSPEW_CODE(fprintf(stderr, "%d uncancelled lane(s) remain after waiting %fs at process end.\n", n, shutdownTimeout_.count())); + if (_n == 0 || (_now >= _until)) { + DEBUGSPEW_CODE(DebugSpew(this) << _n << " uncancelled lane(s) remain after waiting " << shutdownTimeout_.count() << "s at process end." << std::endl); break; } } @@ -354,7 +354,7 @@ void Universe::terminateFreeRunningLanes(lua_State* L_, lua_Duration shutdownTim Lane* _lane{ selfdestructFirst }; if (_lane != SELFDESTRUCT_END) { // this causes a leak because we don't call U's destructor (which could be bad if the still running lanes are accessing it) - raise_luaL_error(L_, "Zombie thread %s refuses to die!", _lane->debugName.data()); + raise_luaL_error(L_, "Zombie thread " STRINGVIEW_FMT " refuses to die!", _lane->debugName.size(), _lane->debugName.data()); } } } -- cgit v1.2.3-55-g6feb