From 53d327679364093e8e1b4c17075633670bea9c83 Mon Sep 17 00:00:00 2001 From: Benoit Germain <benoit.germain@ubisoft.com> Date: Fri, 29 Mar 2024 17:29:23 +0100 Subject: C++ migration: all enums are enum class --- deep_test/deep_test.cpp | 8 +-- docs/index.html | 12 ++--- src/cancel.cpp | 49 ++++++++--------- src/cancel.h | 16 +++--- src/deep.cpp | 40 +++++++------- src/deep.h | 18 +++---- src/keeper.cpp | 16 +++--- src/keeper.h | 2 +- src/lanes.cpp | 86 +++++++++++++++--------------- src/linda.cpp | 16 +++--- src/state.cpp | 6 +-- src/state.h | 16 +++--- src/tools.cpp | 139 ++++++++++++++++++++++++++++++++---------------- src/tools.h | 10 ++-- src/universe.h | 6 ++- 15 files changed, 244 insertions(+), 196 deletions(-) diff --git a/deep_test/deep_test.cpp b/deep_test/deep_test.cpp index d7ecd33..7c8180f 100644 --- a/deep_test/deep_test.cpp +++ b/deep_test/deep_test.cpp @@ -19,26 +19,26 @@ static void* deep_test_id( lua_State* L, DeepOp op_) { switch( op_) { - case eDO_new: + case DeepOp::New: { MyDeepUserdata* deep_test = new MyDeepUserdata; return deep_test; } - case eDO_delete: + case DeepOp::Delete: { MyDeepUserdata* deep_test = static_cast<MyDeepUserdata*>(lua_touserdata( L, 1)); delete deep_test; return nullptr; } - case eDO_metatable: + case DeepOp::Metatable: { luaL_getmetatable( L, "deep"); // mt return nullptr; } - case eDO_module: + case DeepOp::Module: return (void*)"deep_test"; default: diff --git a/docs/index.html b/docs/index.html index f8124c7..24fa4ef 100644 --- a/docs/index.html +++ b/docs/index.html @@ -1669,10 +1669,10 @@ int luaD_new_clonable( lua_State* L) <table border="1" bgcolor="#E0E0FF" cellpadding="10" style="width:50%"><tr><td><pre> void* idfunc( lua_State* L, DeepOp op_);</pre></td></tr></table> <tt>op_</tt> can be one of: <ul> - <li><tt>eDO_new</tt>: requests the creation of a new object, whose pointer is returned. Said object must derive from <tt>DeepPrelude</tt>.</li> - <li><tt>eDO_delete</tt>: receives this same pointer on the stack as a light userdata, and should cleanup the object.</li> - <li><tt>eDO_metatable</tt>: should build a metatable for the object. Don't cache the metatable yourself, Lanes takes care of it (<tt>eDO_metatable</tt> should only be invoked once per state). Just push the metatable on the stack.</li> - <li><tt>eDO_module</tt>: requests the name of the module that exports the idfunc, to be returned. It is necessary so that Lanes can require it in any lane state that receives a userdata. This is to prevent crashes in situations where the module could be unloaded while the idfunc pointer is still held.</li> + <li><tt>DeepOp::New</tt>: requests the creation of a new object, whose pointer is returned. Said object must derive from <tt>DeepPrelude</tt>.</li> + <li><tt>DeepOp::Delete</tt>: receives this same pointer on the stack as a light userdata, and should cleanup the object.</li> + <li><tt>DeepOp::Metatable</tt>: should build a metatable for the object. Don't cache the metatable yourself, Lanes takes care of it (<tt>DeepOp::Metatable</tt> should only be invoked once per state). Just push the metatable on the stack.</li> + <li><tt>DeepOp::Module</tt>: requests the name of the module that exports the idfunc, to be returned. It is necessary so that Lanes can require it in any lane state that receives a userdata. This is to prevent crashes in situations where the module could be unloaded while the idfunc pointer is still held.</li> </ul> Take a look at <tt>linda_id</tt> in <tt>lanes.cpp</tt> or <tt>deep_test_id</tt> in <tt>deep_test.cpp</tt>. </li> @@ -1686,13 +1686,13 @@ int luaD_new_clonable( lua_State* L) </p> <p> - Deep userdata in transit inside keeper states (sent in a linda but not yet consumed) don't call <tt>idfunc(eDO_delete)</tt> and aren't considered by reference counting. The rationale is the following: + Deep userdata in transit inside keeper states (sent in a linda but not yet consumed) don't call <tt>idfunc(DeepOp::Delete)</tt> and aren't considered by reference counting. The rationale is the following: <br /> If some non-keeper state holds a deep userdata for some deep object, then even if the keeper collects its own deep userdata, it shouldn't be cleaned up since the refcount is not 0. <br /> OTOH, if a keeper state holds the last deep userdata for some deep object, then no lane can do actual work with it. Deep userdata's <tt>idfunc()</tt> is never called from a keeper state. <br /> - Therefore, Lanes can just call <tt>idfunc(eDO_delete)</tt> when the last non-keeper-held deep userdata is collected, as long as it doesn't do the same in a keeper state after that, since any remaining deep userdata in keeper states now hold stale pointers. + Therefore, Lanes can just call <tt>idfunc(DeepOp::Delete)</tt> when the last non-keeper-held deep userdata is collected, as long as it doesn't do the same in a keeper state after that, since any remaining deep userdata in keeper states now hold stale pointers. </p> <p> diff --git a/src/cancel.cpp b/src/cancel.cpp index 07c316a..4667f07 100644 --- a/src/cancel.cpp +++ b/src/cancel.cpp @@ -189,7 +189,7 @@ CancelResult thread_cancel(lua_State* L, Lane* lane_, CancelOp op_, double secs_ // signal the linda the wake up the thread so that it can react to the cancel query // let us hope we never land here with a pointer on a linda that has been destroyed... - if (op_ == CO_Soft) + if (op_ == CancelOp::Soft) { return thread_cancel_soft(lane_, secs_, force_); } @@ -203,45 +203,46 @@ CancelResult thread_cancel(lua_State* L, Lane* lane_, CancelOp op_, double secs_ // > 0: the mask // = 0: soft // < 0: hard -static CancelOp which_op( lua_State* L, int idx_) +static CancelOp which_op(lua_State* L, int idx_) { - if( lua_type( L, idx_) == LUA_TSTRING) + if (lua_type(L, idx_) == LUA_TSTRING) { - CancelOp op = CO_Invalid; - char const* str = lua_tostring( L, idx_); - if( strcmp( str, "soft") == 0) + CancelOp op{ CancelOp::Invalid }; + char const* str = lua_tostring(L, idx_); + if (strcmp(str, "hard") == 0) { - op = CO_Soft; + op = CancelOp::Hard; } - else if( strcmp( str, "count") == 0) + else if (strcmp(str, "soft") == 0) { - op = CO_Count; + op = CancelOp::Soft; } - else if( strcmp( str, "line") == 0) + else if (strcmp(str, "call") == 0) { - op = CO_Line; + op = CancelOp::MaskCall; } - else if( strcmp( str, "call") == 0) + else if (strcmp(str, "ret") == 0) { - op = CO_Call; + op = CancelOp::MaskRet; } - else if( strcmp( str, "ret") == 0) + else if (strcmp(str, "line") == 0) { - op = CO_Ret; + op = CancelOp::MaskLine; } - else if( strcmp( str, "hard") == 0) + else if (strcmp(str, "count") == 0) { - op = CO_Hard; + op = CancelOp::MaskCount; } - lua_remove( L, idx_); // argument is processed, remove it - if( op == CO_Invalid) + lua_remove(L, idx_); // argument is processed, remove it + if (op == CancelOp::Invalid) { - std::ignore = luaL_error( L, "invalid hook option %s", str); + std::ignore = luaL_error(L, "invalid hook option %s", str); } return op; } - return CO_Hard; + return CancelOp::Hard; } + // ################################################################################################ // bool[,reason] = lane_h:cancel( [mode, hookcount] [, timeout] [, force [, forcekill_timeout]]) @@ -250,15 +251,15 @@ LUAG_FUNC(thread_cancel) Lane* const lane{ lua_toLane(L, 1) }; CancelOp const op{ which_op(L, 2) }; // this removes the op string from the stack - if (op > 0) // hook is requested + if (static_cast<int>(op) > static_cast<int>(CancelOp::Soft)) // hook is requested { - int hook_count = (int) lua_tointeger(L, 2); + int const hook_count{ static_cast<int>(lua_tointeger(L, 2)) }; lua_remove(L, 2); // argument is processed, remove it if (hook_count < 1) { return luaL_error(L, "hook count cannot be < 1"); } - lua_sethook(lane->L, cancel_hook, op, hook_count); + lua_sethook(lane->L, cancel_hook, static_cast<int>(op), hook_count); } double secs{ 0.0 }; diff --git a/src/cancel.h b/src/cancel.h index 0c1de14..884e193 100644 --- a/src/cancel.h +++ b/src/cancel.h @@ -34,15 +34,15 @@ enum class CancelResult Killed }; -enum CancelOp +enum class CancelOp { - CO_Invalid = -2, - CO_Hard = -1, - CO_Soft = 0, - CO_Count = LUA_MASKCOUNT, - CO_Line = LUA_MASKLINE, - CO_Call = LUA_MASKCALL, - CO_Ret = LUA_MASKRET, + Invalid = -2, + Hard = -1, + Soft = 0, + MaskCall = LUA_MASKCALL, + MaskRet = LUA_MASKRET, + MaskLine = LUA_MASKLINE, + MaskCount = LUA_MASKCOUNT, }; // crc64/we of string "CANCEL_ERROR" generated at http://www.nitrxgen.net/hashgen/ diff --git a/src/deep.cpp b/src/deep.cpp index 290e5ff..ac2905e 100644 --- a/src/deep.cpp +++ b/src/deep.cpp @@ -113,7 +113,7 @@ static void get_deep_lookup( lua_State* L) static inline luaG_IdFunction get_idfunc( lua_State* L, int index, LookupMode mode_) { // when looking inside a keeper, we are 100% sure the object is a deep userdata - if( mode_ == eLM_FromKeeper) + if (mode_ == LookupMode::FromKeeper) { DeepPrelude** const proxy{ lua_tofulluserdata<DeepPrelude*>(L, index) }; // we can (and must) cast and fetch the internally stored idfunc @@ -149,7 +149,7 @@ void free_deep_prelude( lua_State* L, DeepPrelude* prelude_) STACK_CHECK_START_REL(L, 0); // Call 'idfunc( "delete", deep_ptr )' to make deep cleanup lua_pushlightuserdata( L, prelude_); - prelude_->idfunc( L, eDO_delete); + prelude_->idfunc( L, DeepOp::Delete); lua_pop(L, 1); STACK_CHECK(L, 0); } @@ -186,7 +186,7 @@ static int deep_userdata_gc( lua_State* L) // top was set to 0, then userdata was pushed. "delete" might want to pop the userdata (we don't care), but should not push anything! if ( lua_gettop( L) > 1) { - return luaL_error( L, "Bad idfunc(eDO_delete): should not push anything"); + return luaL_error( L, "Bad idfunc(DeepOp::Delete): should not push anything"); } } *proxy = nullptr; // make sure we don't use it any more, just in case @@ -197,7 +197,7 @@ static int deep_userdata_gc( lua_State* L) /* * Push a proxy userdata on the stack. * returns nullptr if ok, else some error string related to bad idfunc behavior or module require problem - * (error cannot happen with mode_ == eLM_ToKeeper) + * (error cannot happen with mode_ == LookupMode::ToKeeper) * * Initializes necessary structures if it's the first time 'idfunc' is being * used in this Lua state (metatable, registring it). Otherwise, increments the @@ -238,9 +238,9 @@ char const* push_deep_proxy(lua_State* L, DeepPrelude* prelude, int nuv_, Lookup int oldtop = lua_gettop( L); // DPC proxy nil lua_pop( L, 1); // DPC proxy // 1 - make one and register it - if( mode_ != eLM_ToKeeper) + if (mode_ != LookupMode::ToKeeper) { - (void) prelude->idfunc( L, eDO_metatable); // DPC proxy metatable + (void) prelude->idfunc( L, DeepOp::Metatable); // DPC proxy metatable if( lua_gettop( L) - oldtop != 0 || !lua_istable( L, -1)) { lua_settop( L, oldtop); // DPC proxy X @@ -278,7 +278,7 @@ char const* push_deep_proxy(lua_State* L, DeepPrelude* prelude, int nuv_, Lookup // this is needed because we must make sure the shared library is still loaded as long as we hold a pointer on the idfunc { int oldtop_module = lua_gettop( L); - modname = (char const*) prelude->idfunc( L, eDO_module); // DPC proxy metatable + modname = (char const*) prelude->idfunc( L, DeepOp::Module); // DPC proxy metatable // make sure the function pushed nothing on the stack! if( lua_gettop( L) - oldtop_module != 0) { @@ -358,9 +358,9 @@ char const* push_deep_proxy(lua_State* L, DeepPrelude* prelude, int nuv_, Lookup * * 'idfunc' must fulfill the following features: * -* lightuserdata = idfunc( eDO_new [, ...] ) -- creates a new deep data instance -* void = idfunc( eDO_delete, lightuserdata ) -- releases a deep data instance -* tbl = idfunc( eDO_metatable ) -- gives metatable for userdata proxies +* lightuserdata = idfunc( DeepOp::New [, ...] ) -- creates a new deep data instance +* void = idfunc( DeepOp::Delete, lightuserdata ) -- releases a deep data instance +* tbl = idfunc( DeepOp::Metatable ) -- gives metatable for userdata proxies * * Reference counting and true userdata proxying are taken care of for the * actual data type. @@ -375,18 +375,18 @@ int luaG_newdeepuserdata( lua_State* L, luaG_IdFunction idfunc, int nuv_) STACK_GROW( L, 1); STACK_CHECK_START_REL(L, 0); int const oldtop{ lua_gettop(L) }; - DeepPrelude* const prelude{ static_cast<DeepPrelude*>(idfunc(L, eDO_new)) }; + DeepPrelude* const prelude{ static_cast<DeepPrelude*>(idfunc(L, DeepOp::New)) }; if (prelude == nullptr) { - return luaL_error( L, "idfunc(eDO_new) failed to create deep userdata (out of memory)"); + return luaL_error( L, "idfunc(DeepOp::New) failed to create deep userdata (out of memory)"); } if( prelude->magic != DEEP_VERSION) { // just in case, don't leak the newly allocated deep userdata object lua_pushlightuserdata( L, prelude); - idfunc( L, eDO_delete); - return luaL_error( L, "Bad idfunc(eDO_new): DEEP_VERSION is incorrect, rebuild your implementation with the latest deep implementation"); + idfunc( L, DeepOp::Delete); + return luaL_error( L, "Bad idfunc(DeepOp::New): DEEP_VERSION is incorrect, rebuild your implementation with the latest deep implementation"); } ASSERT_L(prelude->m_refcount.load(std::memory_order_relaxed) == 0); // 'push_deep_proxy' will lift it to 1 @@ -396,11 +396,11 @@ int luaG_newdeepuserdata( lua_State* L, luaG_IdFunction idfunc, int nuv_) { // just in case, don't leak the newly allocated deep userdata object lua_pushlightuserdata( L, prelude); - idfunc( L, eDO_delete); - return luaL_error( L, "Bad idfunc(eDO_new): should not push anything on the stack"); + idfunc( L, DeepOp::Delete); + return luaL_error( L, "Bad idfunc(DeepOp::New): should not push anything on the stack"); } - char const* const errmsg{ push_deep_proxy(L, prelude, nuv_, eLM_LaneBody) }; // proxy + char const* const errmsg{ push_deep_proxy(L, prelude, nuv_, LookupMode::LaneBody) }; // proxy if (errmsg != nullptr) { return luaL_error( L, errmsg); @@ -420,7 +420,7 @@ DeepPrelude* luaG_todeep(lua_State* L, luaG_IdFunction idfunc, int index) { STACK_CHECK_START_REL(L, 0); // ensure it is actually a deep userdata - if( get_idfunc( L, index, eLM_LaneBody) != idfunc) + if (get_idfunc(L, index, LookupMode::LaneBody) != idfunc) { return nullptr; // no metatable, or wrong kind } @@ -466,7 +466,7 @@ bool copydeep(Universe* U, lua_State* L2, int L2_cache_i, lua_State* L, int i, L int const clone_i = lua_gettop( L2); while( nuv) { - inter_copy_one( U, L2, L2_cache_i, L, lua_absindex( L, -1), VT_NORMAL, mode_, upName_); // u uv + inter_copy_one( U, L2, L2_cache_i, L, lua_absindex( L, -1), VT::NORMAL, mode_, upName_); // u uv lua_pop( L, 1); // ... u [uv]* // this pops the value from the stack lua_setiuservalue( L2, clone_i, nuv); // u @@ -480,7 +480,7 @@ bool copydeep(Universe* U, lua_State* L2, int L2_cache_i, lua_State* L, int i, L if (errmsg != nullptr) { // raise the error in the proper state (not the keeper) - lua_State* const errL { (mode_ == eLM_FromKeeper) ? L2 : L }; + lua_State* const errL{ (mode_ == LookupMode::FromKeeper) ? L2 : L }; std::ignore = luaL_error(errL, errmsg); } return true; diff --git a/src/deep.h b/src/deep.h index 2983427..1799cf0 100644 --- a/src/deep.h +++ b/src/deep.h @@ -21,19 +21,19 @@ extern "C" { // forwards struct Universe; -enum LookupMode +enum class LookupMode { - eLM_LaneBody, // send the lane body directly from the source to the destination lane - eLM_ToKeeper, // send a function from a lane to a keeper state - eLM_FromKeeper // send a function from a keeper state to a lane + LaneBody, // send the lane body directly from the source to the destination lane + ToKeeper, // send a function from a lane to a keeper state + FromKeeper // send a function from a keeper state to a lane }; -enum DeepOp +enum class DeepOp { - eDO_new, - eDO_delete, - eDO_metatable, - eDO_module, + New, + Delete, + Metatable, + Module, }; using luaG_IdFunction = void*(*)( lua_State* L, DeepOp op_); diff --git a/src/keeper.cpp b/src/keeper.cpp index aab7abe..8f762e5 100644 --- a/src/keeper.cpp +++ b/src/keeper.cpp @@ -234,10 +234,10 @@ int keeper_push_linda_storage(Universe* U, lua_State* L, void* ptr_, uintptr_t m { keeper_fifo* fifo = prepare_fifo_access(KL, -1); // storage key fifotbl lua_pushvalue(KL, -2); // storage key fifotbl key - luaG_inter_move(U, KL, L, 1, eLM_FromKeeper); // storage key fifotbl // out key + luaG_inter_move(U, KL, L, 1, LookupMode::FromKeeper); // storage key fifotbl // out key STACK_CHECK(L, 2); lua_newtable(L); // out key keyout - luaG_inter_move(U, KL, L, 1, eLM_FromKeeper); // storage key // out key keyout fifotbl + luaG_inter_move(U, KL, L, 1, LookupMode::FromKeeper); // storage key // out key keyout fifotbl lua_pushinteger(L, fifo->first); // out key keyout fifotbl first STACK_CHECK(L, 5); lua_setfield(L, -3, "first"); // out key keyout fifotbl @@ -703,8 +703,8 @@ void init_keepers(Universe* U, lua_State* L) lua_getglobal(L, "package"); // "..." keepersUD package if (!lua_isnil(L, -1)) { - // when copying with mode eLM_ToKeeper, error message is pushed at the top of the stack, not raised immediately - if (luaG_inter_copy_package(U, L, K, -1, eLM_ToKeeper)) + // when copying with mode LookupMode::ToKeeper, error message is pushed at the top of the stack, not raised immediately + if (luaG_inter_copy_package(U, L, K, -1, LookupMode::ToKeeper)) { // if something went wrong, the error message is at the top of the stack lua_remove(L, -2); // error_msg @@ -717,7 +717,7 @@ void init_keepers(Universe* U, lua_State* L) // attempt to call on_state_create(), if we have one and it is a C function // (only support a C function because we can't transfer executable Lua code in keepers) // will raise an error in L in case of problem - call_on_state_create(U, K, L, eLM_ToKeeper); + call_on_state_create(U, K, L, LookupMode::ToKeeper); // to see VM name in Decoda debugger lua_pushfstring(K, "Keeper #%d", i + 1); // "Keeper #n" @@ -785,7 +785,7 @@ void keeper_toggle_nil_sentinels(lua_State* L, int val_i_, LookupMode const mode int const n{ lua_gettop(L) }; for (int i = val_i_; i <= n; ++i) { - if (mode_ == eLM_ToKeeper) + if (mode_ == LookupMode::ToKeeper) { if (lua_isnil(L, i)) { @@ -827,7 +827,7 @@ int keeper_call(Universe* U, lua_State* K, keeper_api_t func_, lua_State* L, voi lua_pushlightuserdata(K, linda); - if ((args == 0) || luaG_inter_copy(U, L, K, args, eLM_ToKeeper) == 0) // L->K + if ((args == 0) || luaG_inter_copy(U, L, K, args, LookupMode::ToKeeper) == 0) // L->K { lua_call(K, 1 + args, LUA_MULTRET); @@ -836,7 +836,7 @@ int keeper_call(Universe* U, lua_State* K, keeper_api_t func_, lua_State* L, voi // this may interrupt a lane, causing the destruction of the underlying OS thread // after this, another lane making use of this keeper can get an error code from the mutex-locking function // when attempting to grab the mutex again (WINVER <= 0x400 does this, but locks just fine, I don't know about pthread) - if ((retvals > 0) && luaG_inter_move(U, K, L, retvals, eLM_FromKeeper) != 0) // K->L + if ((retvals > 0) && luaG_inter_move(U, K, L, retvals, LookupMode::FromKeeper) != 0) // K->L { retvals = -1; } diff --git a/src/keeper.h b/src/keeper.h index fc0aa6b..e081bea 100644 --- a/src/keeper.h +++ b/src/keeper.h @@ -12,8 +12,8 @@ extern "C" { #include "uniquekey.h" // forwards +enum class LookupMode; struct Universe; -enum LookupMode; struct Keeper { diff --git a/src/lanes.cpp b/src/lanes.cpp index 8a76217..8890b06 100644 --- a/src/lanes.cpp +++ b/src/lanes.cpp @@ -464,7 +464,7 @@ static int universe_gc( lua_State* L) while (lane != SELFDESTRUCT_END) { // attempt a regular unforced hard cancel with a small timeout - bool const cancelled = THREAD_ISNULL(lane->thread) || thread_cancel(L, lane, CO_Hard, 0.0001, false, 0.0) != CancelResult::Timeout; + bool const cancelled{ THREAD_ISNULL(lane->thread) || thread_cancel(L, lane, CancelOp::Hard, 0.0001, false, 0.0) != CancelResult::Timeout }; // if we failed, and we know the thread is waiting on a linda if (cancelled == false && lane->status == WAITING && lane->waiting_on != nullptr) { @@ -1085,7 +1085,7 @@ LUAG_FUNC(lane_new) DEBUGSPEW_CODE( ++ U->debugspew_indent_depth); // populate with selected libraries at the same time - lua_State* const L2{ luaG_newstate(U, L, libs_str) }; // L // L2 + lua_State* const L2{ luaG_newstate(U, L, libs_str) }; // L // L2 // 'lane' is allocated from heap, not Lua, since its life span may surpass the handle's (if free running thread) Lane* const lane{ new (U) Lane{ U, L2 } }; @@ -1122,23 +1122,23 @@ LUAG_FUNC(lane_new) DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "lane_new: launching thread\n" INDENT_END)); THREAD_CREATE(&lane->thread, lane_main, lane, priority); - STACK_GROW( L2, nargs + 3); // + STACK_GROW( L2, nargs + 3); // STACK_CHECK_START_REL(L2, 0); - STACK_GROW(L, 3); // func libs priority globals package required gc_cb [... args ...] + STACK_GROW(L, 3); // func libs priority globals package required gc_cb [... args ...] STACK_CHECK_START_REL(L, 0); // give a default "Lua" name to the thread to see VM name in Decoda debugger - lua_pushfstring( L2, "Lane #%p", L2); // "..." - lua_setglobal( L2, "decoda_name"); // + lua_pushfstring( L2, "Lane #%p", L2); // "..." + lua_setglobal( L2, "decoda_name"); // ASSERT_L( lua_gettop( L2) == 0); DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "lane_new: update 'package'\n" INDENT_END)); // package if (package_idx != 0) { - // when copying with mode eLM_LaneBody, should raise an error in case of problem, not leave it one the stack - (void) luaG_inter_copy_package( U, L, L2, package_idx, eLM_LaneBody); + // when copying with mode LookupMode::LaneBody, should raise an error in case of problem, not leave it one the stack + (void) luaG_inter_copy_package(U, L, L2, package_idx, LookupMode::LaneBody); } // modules to require in the target lane *before* the function is transfered! @@ -1154,8 +1154,8 @@ LUAG_FUNC(lane_new) return luaL_error(L, "expected required module list as a table, got %s", luaL_typename(L, required_idx)); } - lua_pushnil(L); // func libs priority globals package required gc_cb [... args ...] nil - while( lua_next(L, required_idx) != 0) // func libs priority globals package required gc_cb [... args ...] n "modname" + lua_pushnil(L); // func libs priority globals package required gc_cb [... args ...] nil + while( lua_next(L, required_idx) != 0) // func libs priority globals package required gc_cb [... args ...] n "modname" { if (lua_type(L, -1) != LUA_TSTRING || lua_type(L, -2) != LUA_TNUMBER || lua_tonumber(L, -2) != nbRequired) { @@ -1169,33 +1169,33 @@ LUAG_FUNC(lane_new) DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "lane_new: require '%s'\n" INDENT_END, name)); // require the module in the target lane - lua_getglobal( L2, "require"); // require()? + lua_getglobal( L2, "require"); // require()? if (lua_isnil( L2, -1)) { - lua_pop( L2, 1); // + lua_pop( L2, 1); // return luaL_error(L, "cannot pre-require modules without loading 'package' library first"); } else { - lua_pushlstring( L2, name, len); // require() name - if (lua_pcall( L2, 1, 1, 0) != LUA_OK) // ret/errcode + lua_pushlstring( L2, name, len); // require() name + if (lua_pcall( L2, 1, 1, 0) != LUA_OK) // ret/errcode { // propagate error to main state if any - luaG_inter_move(U, L2, L, 1, eLM_LaneBody); // func libs priority globals package required gc_cb [... args ...] n "modname" error + luaG_inter_move(U, L2, L, 1, LookupMode::LaneBody); // func libs priority globals package required gc_cb [... args ...] n "modname" error raise_lua_error(L); } // after requiring the module, register the functions it exported in our name<->function database populate_func_lookup_table( L2, -1, name); - lua_pop( L2, 1); // + lua_pop( L2, 1); // } } - lua_pop(L, 1); // func libs priority globals package required gc_cb [... args ...] n + lua_pop(L, 1); // func libs priority globals package required gc_cb [... args ...] n ++ nbRequired; - } // func libs priority globals package required gc_cb [... args ...] + } // func libs priority globals package required gc_cb [... args ...] DEBUGSPEW_CODE( -- U->debugspew_indent_depth); } STACK_CHECK(L, 0); - STACK_CHECK(L2, 0); // + STACK_CHECK(L2, 0); // // Appending the specified globals to the global environment // *after* stdlibs have been loaded and modules required, in case we transfer references to native functions they exposed... @@ -1209,17 +1209,17 @@ LUAG_FUNC(lane_new) } DEBUGSPEW_CODE( ++ U->debugspew_indent_depth); - lua_pushnil(L); // func libs priority globals package required gc_cb [... args ...] nil + lua_pushnil(L); // func libs priority globals package required gc_cb [... args ...] nil // Lua 5.2 wants us to push the globals table on the stack - lua_pushglobaltable(L2); // _G - while( lua_next(L, globals_idx)) // func libs priority globals package required gc_cb [... args ...] k v + lua_pushglobaltable(L2); // _G + while( lua_next(L, globals_idx)) // func libs priority globals package required gc_cb [... args ...] k v { - luaG_inter_copy(U, L, L2, 2, eLM_LaneBody); // _G k v + luaG_inter_copy(U, L, L2, 2, LookupMode::LaneBody); // _G k v // assign it in L2's globals table - lua_rawset(L2, -3); // _G - lua_pop(L, 1); // func libs priority globals package required gc_cb [... args ...] k - } // func libs priority globals package required gc_cb [... args ...] - lua_pop( L2, 1); // + lua_rawset(L2, -3); // _G + lua_pop(L, 1); // func libs priority globals package required gc_cb [... args ...] k + } // func libs priority globals package required gc_cb [... args ...] + lua_pop( L2, 1); // DEBUGSPEW_CODE( -- U->debugspew_indent_depth); } @@ -1232,8 +1232,8 @@ LUAG_FUNC(lane_new) int res; DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "lane_new: transfer lane body\n" INDENT_END)); DEBUGSPEW_CODE( ++ U->debugspew_indent_depth); - lua_pushvalue(L, 1); // func libs priority globals package required gc_cb [... args ...] func - res = luaG_inter_move(U, L, L2, 1, eLM_LaneBody); // func libs priority globals package required gc_cb [... args ...] // func + lua_pushvalue(L, 1); // func libs priority globals package required gc_cb [... args ...] func + res = luaG_inter_move(U, L, L2, 1, LookupMode::LaneBody); // func libs priority globals package required gc_cb [... args ...] // func DEBUGSPEW_CODE( -- U->debugspew_indent_depth); if (res != 0) { @@ -1243,7 +1243,7 @@ LUAG_FUNC(lane_new) else if (lua_type(L, 1) == LUA_TSTRING) { // compile the string - if (luaL_loadstring(L2, lua_tostring(L, 1)) != 0) // func + if (luaL_loadstring(L2, lua_tostring(L, 1)) != 0) // func { return luaL_error(L, "error when parsing lane function code"); } @@ -1258,7 +1258,7 @@ LUAG_FUNC(lane_new) int res; DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "lane_new: transfer lane arguments\n" INDENT_END)); DEBUGSPEW_CODE( ++ U->debugspew_indent_depth); - res = luaG_inter_move(U, L, L2, nargs, eLM_LaneBody); // func libs priority globals package required gc_cb // func [... args ...] + res = luaG_inter_move(U, L, L2, nargs, LookupMode::LaneBody); // func libs priority globals package required gc_cb // func [... args ...] DEBUGSPEW_CODE( -- U->debugspew_indent_depth); if (res != 0) { @@ -1271,31 +1271,31 @@ LUAG_FUNC(lane_new) STACK_CHECK( L2, 1 + nargs); // a Lane full userdata needs a single uservalue - Lane** const ud{ lua_newuserdatauv<Lane*>(L, 1) }; // func libs priority globals package required gc_cb lane + Lane** const ud{ lua_newuserdatauv<Lane*>(L, 1) }; // func libs priority globals package required gc_cb lane *ud = lane; // don't forget to store the pointer in the userdata! // Set metatable for the userdata // - lua_pushvalue(L, lua_upvalueindex( 1)); // func libs priority globals package required gc_cb lane mt - lua_setmetatable(L, -2); // func libs priority globals package required gc_cb lane + lua_pushvalue(L, lua_upvalueindex( 1)); // func libs priority globals package required gc_cb lane mt + lua_setmetatable(L, -2); // func libs priority globals package required gc_cb lane STACK_CHECK(L, 1); // Create uservalue for the userdata // (this is where lane body return values will be stored when the handle is indexed by a numeric key) - lua_newtable(L); // func libs cancelstep priority globals package required gc_cb lane uv + lua_newtable(L); // func libs cancelstep priority globals package required gc_cb lane uv // Store the gc_cb callback in the uservalue if (gc_cb_idx > 0) { - GCCB_KEY.pushKey(L); // func libs priority globals package required gc_cb lane uv k - lua_pushvalue(L, gc_cb_idx); // func libs priority globals package required gc_cb lane uv k gc_cb - lua_rawset(L, -3); // func libs priority globals package required gc_cb lane uv + GCCB_KEY.pushKey(L); // func libs priority globals package required gc_cb lane uv k + lua_pushvalue(L, gc_cb_idx); // func libs priority globals package required gc_cb lane uv k gc_cb + lua_rawset(L, -3); // func libs priority globals package required gc_cb lane uv } - lua_setiuservalue(L, -2, 1); // func libs priority globals package required gc_cb lane + lua_setiuservalue(L, -2, 1); // func libs priority globals package required gc_cb lane // Store 'lane' in the lane's registry, for 'cancel_test()' (we do cancel tests at pending send/receive). - LANE_POINTER_REGKEY.setValue(L2, [lane](lua_State* L) { lua_pushlightuserdata(L, lane); }); // func [... args ...] + LANE_POINTER_REGKEY.setValue(L2, [lane](lua_State* L) { lua_pushlightuserdata(L, lane); }); // func [... args ...] STACK_CHECK(L, 1); STACK_CHECK(L2, 1 + nargs); @@ -1482,7 +1482,7 @@ LUAG_FUNC(thread_join) case DONE: { int const n{ lua_gettop(L2) }; // whole L2 stack - if ((n > 0) && (luaG_inter_move(U, L2, L, n, eLM_LaneBody) != 0)) + if ((n > 0) && (luaG_inter_move(U, L2, L, n, LookupMode::LaneBody) != 0)) { return luaL_error(L, "tried to copy unsupported types"); } @@ -1496,7 +1496,7 @@ LUAG_FUNC(thread_join) STACK_GROW(L, 3); lua_pushnil(L); // even when ERROR_FULL_STACK, if the error is not LUA_ERRRUN, the handler wasn't called, and we only have 1 error message on the stack ... - if (luaG_inter_move(U, L2, L, n, eLM_LaneBody) != 0) // nil "err" [trace] + if (luaG_inter_move(U, L2, L, n, LookupMode::LaneBody) != 0) // nil "err" [trace] { return luaL_error(L, "tried to copy unsupported types: %s", lua_tostring(L, -n)); } @@ -1967,7 +1967,7 @@ LUAG_FUNC(configure) STACK_CHECK(L, 2); { - char const* errmsg{ push_deep_proxy(L, U->timer_deep, 0, eLM_LaneBody) }; // settings M timer_deep + char const* errmsg{ push_deep_proxy(L, U->timer_deep, 0, LookupMode::LaneBody) }; // settings M timer_deep if (errmsg != nullptr) { return luaL_error(L, errmsg); diff --git a/src/linda.cpp b/src/linda.cpp index 14eba2d..37a74b0 100644 --- a/src/linda.cpp +++ b/src/linda.cpp @@ -256,7 +256,7 @@ LUAG_FUNC(linda_send) } // convert nils to some special non-nil sentinel in sent values - keeper_toggle_nil_sentinels(L, key_i + 1, eLM_ToKeeper); + keeper_toggle_nil_sentinels(L, key_i + 1, LookupMode::ToKeeper); bool ret{ false }; CancelRequest cancel{ CancelRequest::None }; int pushed{ 0 }; @@ -448,7 +448,7 @@ LUAG_FUNC(linda_receive) { ASSERT_L(pushed >= expected_pushed_min && pushed <= expected_pushed_max); // replace sentinels with real nils - keeper_toggle_nil_sentinels(L, lua_gettop(L) - pushed, eLM_FromKeeper); + keeper_toggle_nil_sentinels(L, lua_gettop(L) - pushed, LookupMode::FromKeeper); // To be done from within the 'K' locking area // SIGNAL_ALL(&linda->read_happened); @@ -527,7 +527,7 @@ LUAG_FUNC(linda_set) if (has_value) { // convert nils to some special non-nil sentinel in sent values - keeper_toggle_nil_sentinels(L, 3, eLM_ToKeeper); + keeper_toggle_nil_sentinels(L, 3, LookupMode::ToKeeper); } pushed = keeper_call(linda->U, K->L, KEEPER_API(set), L, linda, 2); if (pushed >= 0) // no error? @@ -603,7 +603,7 @@ LUAG_FUNC(linda_get) pushed = keeper_call(linda->U, K->L, KEEPER_API(get), L, linda, 2); if (pushed > 0) { - keeper_toggle_nil_sentinels(L, lua_gettop(L) - pushed, eLM_FromKeeper); + keeper_toggle_nil_sentinels(L, lua_gettop(L) - pushed, LookupMode::FromKeeper); } } else // linda is cancelled @@ -843,7 +843,7 @@ static void* linda_id( lua_State* L, DeepOp op_) { switch( op_) { - case eDO_new: + case DeepOp::New: { size_t name_len = 0; char const* linda_name = nullptr; @@ -881,7 +881,7 @@ static void* linda_id( lua_State* L, DeepOp op_) return linda; } - case eDO_delete: + case DeepOp::Delete: { Linda* const linda{ lua_tolightuserdata<Linda>(L, 1) }; ASSERT_L(linda); @@ -899,7 +899,7 @@ static void* linda_id( lua_State* L, DeepOp op_) return nullptr; } - case eDO_metatable: + case DeepOp::Metatable: { STACK_CHECK_START_REL(L, 0); lua_newtable(L); @@ -970,7 +970,7 @@ static void* linda_id( lua_State* L, DeepOp op_) return nullptr; } - case eDO_module: + case DeepOp::Module: // linda is a special case because we know lanes must be loaded from the main lua state // to be able to ever get here, so we know it will remain loaded as long a the main state is around // in other words, forever. diff --git a/src/state.cpp b/src/state.cpp index 2678280..55540c8 100644 --- a/src/state.cpp +++ b/src/state.cpp @@ -205,7 +205,7 @@ static void copy_one_time_settings( Universe* U, lua_State* L, lua_State* L2) CONFIG_REGKEY.pushValue(L); // config // copy settings from from source to destination registry - if( luaG_inter_move( U, L, L2, 1, eLM_LaneBody) < 0) // // config + if( luaG_inter_move( U, L, L2, 1, LookupMode::LaneBody) < 0) // // config { (void) luaL_error( L, "failed to copy settings when loading lanes.core"); } @@ -291,7 +291,7 @@ void call_on_state_create(Universe* U, lua_State* L, lua_State* from_, LookupMod } else // Lua function located in the config table, copied when we opened "lanes.core" { - if (mode_ != eLM_LaneBody) + if (mode_ != LookupMode::LaneBody) { // if attempting to call in a keeper state, do nothing because the function doesn't exist there // this doesn't count as an error though @@ -413,7 +413,7 @@ lua_State* luaG_newstate( Universe* U, lua_State* from_, char const* libs_) // call this after the base libraries are loaded and GC is restarted // will raise an error in from_ in case of problem - call_on_state_create( U, L, from_, eLM_LaneBody); + call_on_state_create(U, L, from_, LookupMode::LaneBody); STACK_CHECK(L, 0); // after all this, register everything we find in our name<->function database diff --git a/src/state.h b/src/state.h index 0ffab02..0e35e89 100644 --- a/src/state.h +++ b/src/state.h @@ -1,18 +1,18 @@ #pragma once -#include "threading.h" -#include "deep.h" - #include "macros_and_utils.h" -void serialize_require( DEBUGSPEW_PARAM_COMMA( Universe* U) lua_State *L); +// forwards +struct Universe; + +void serialize_require(DEBUGSPEW_PARAM_COMMA(Universe* U) lua_State* L); // ################################################################################################ -lua_State* create_state( Universe* U, lua_State* from_); -lua_State* luaG_newstate( Universe* U, lua_State* _from, char const* libs); +lua_State* create_state(Universe* U, lua_State* from_); +lua_State* luaG_newstate(Universe* U, lua_State* _from, char const* libs); // ################################################################################################ -void initialize_on_state_create( Universe* U, lua_State* L); -void call_on_state_create( Universe* U, lua_State* L, lua_State* from_, LookupMode mode_); +void initialize_on_state_create(Universe* U, lua_State* L); +void call_on_state_create(Universe* U, lua_State* L, lua_State* from_, LookupMode mode_); diff --git a/src/tools.cpp b/src/tools.cpp index 98224ae..103122e 100644 --- a/src/tools.cpp +++ b/src/tools.cpp @@ -301,7 +301,9 @@ FuncSubType luaG_getfuncsubtype( lua_State *L, int _i) return FST_FastJIT; } -static lua_CFunction luaG_tocfunction( lua_State *L, int _i, FuncSubType *_out) +// ################################################################################################# + +static lua_CFunction luaG_tocfunction(lua_State* L, int _i, FuncSubType* _out) { lua_CFunction p = lua_tocfunction( L, _i); *_out = luaG_getfuncsubtype( L, _i); @@ -311,6 +313,8 @@ static lua_CFunction luaG_tocfunction( lua_State *L, int _i, FuncSubType *_out) // crc64/we of string "LOOKUPCACHE_REGKEY" generated at http://www.nitrxgen.net/hashgen/ static constexpr UniqueKey LOOKUPCACHE_REGKEY{ 0x837a68dfc6fcb716ull }; +// ################################################################################################# + // inspired from tconcat() in ltablib.c static char const* luaG_pushFQN( lua_State* L, int t, int last, size_t* length) { @@ -336,6 +340,8 @@ static char const* luaG_pushFQN( lua_State* L, int t, int last, size_t* length) return lua_tolstring( L, -1, length); } +// ################################################################################################# + /* * receives 2 arguments: a name k and an object o * add two entries ["fully.qualified.name"] = o @@ -418,7 +424,9 @@ static void update_lookup_entry( DEBUGSPEW_PARAM_COMMA( Universe* U) lua_State* DEBUGSPEW_CODE( -- U->debugspew_indent_depth); } -static void populate_func_lookup_table_recur( DEBUGSPEW_PARAM_COMMA( Universe* U) lua_State* L, int _ctx_base, int _i, int _depth) +// ################################################################################################# + +static void populate_func_lookup_table_recur(DEBUGSPEW_PARAM_COMMA(Universe* U) lua_State* L, int _ctx_base, int _i, int _depth) { lua_Integer visit_count; // slot 2 contains a table that, when concatenated, produces the fully qualified name of scanned elements in the table provided at slot _i @@ -541,6 +549,8 @@ static void populate_func_lookup_table_recur( DEBUGSPEW_PARAM_COMMA( Universe* U DEBUGSPEW_CODE( -- U->debugspew_indent_depth); } +// ################################################################################################# + /* * create a "fully.qualified.name" <-> function equivalence database */ @@ -605,6 +615,8 @@ void populate_func_lookup_table( lua_State* L, int _i, char const* name_) DEBUGSPEW_CODE( -- U->debugspew_indent_depth); } +// ################################################################################################# + /*---=== Inter-state copying ===---*/ // crc64/we of string "REG_MTID" generated at http://www.nitrxgen.net/hashgen/ @@ -651,12 +663,15 @@ static lua_Integer get_mt_id( Universe* U, lua_State* L, int i) return id; } +// ################################################################################################# + // function sentinel used to transfer native functions from/to keeper states static int func_lookup_sentinel( lua_State* L) { return luaL_error( L, "function lookup sentinel for %s, should never be called", lua_tostring( L, lua_upvalueindex( 1))); } +// ################################################################################################# // function sentinel used to transfer native table from/to keeper states static int table_lookup_sentinel( lua_State* L) @@ -664,12 +679,16 @@ static int table_lookup_sentinel( lua_State* L) return luaL_error( L, "table lookup sentinel for %s, should never be called", lua_tostring( L, lua_upvalueindex( 1))); } +// ################################################################################################# + // function sentinel used to transfer cloned full userdata from/to keeper states static int userdata_clone_sentinel( lua_State* L) { return luaL_error( L, "userdata clone sentinel for %s, should never be called", lua_tostring( L, lua_upvalueindex( 1))); } +// ################################################################################################# + /* * retrieve the name of a function/table in the lookup database */ @@ -680,7 +699,7 @@ static char const* find_lookup_name(lua_State* L, int i, LookupMode mode_, char ASSERT_L( lua_isfunction( L, i) || lua_istable( L, i)); // ... v ... STACK_CHECK_START_REL(L, 0); STACK_GROW( L, 3); // up to 3 slots are necessary on error - if( mode_ == eLM_FromKeeper) + if (mode_ == LookupMode::FromKeeper) { lua_CFunction f = lua_tocfunction( L, i); // should *always* be func_lookup_sentinel or table_lookup_sentinel! if( f == func_lookup_sentinel || f == table_lookup_sentinel || f == userdata_clone_sentinel) @@ -707,7 +726,7 @@ static char const* find_lookup_name(lua_State* L, int i, LookupMode mode_, char fqn = lua_tolstring( L, -1, len_); DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "function [C] %s \n" INDENT_END, fqn)); // popping doesn't invalidate the pointer since this is an interned string gotten from the lookup database - lua_pop( L, (mode_ == eLM_FromKeeper) ? 1 : 2); // ... v ... + lua_pop( L, (mode_ == LookupMode::FromKeeper) ? 1 : 2); // ... v ... STACK_CHECK( L, 0); if (nullptr == fqn && !lua_istable(L, i)) // raise an error if we try to send an unknown function (but not for tables) { @@ -741,6 +760,7 @@ static char const* find_lookup_name(lua_State* L, int i, LookupMode mode_, char return fqn; } +// ################################################################################################# /* * Push a looked-up table, or nothing if we found nothing @@ -763,14 +783,14 @@ static bool lookup_table(lua_State* L2, lua_State* L, int i, LookupMode mode_, c (void) luaL_error( L, "internal error: unknown lookup mode"); return false; - case eLM_ToKeeper: + case LookupMode::ToKeeper: // push a sentinel closure that holds the lookup name as upvalue lua_pushlstring( L2, fqn, len); // "f.q.n" lua_pushcclosure( L2, table_lookup_sentinel, 1); // f break; - case eLM_LaneBody: - case eLM_FromKeeper: + case LookupMode::LaneBody: + case LookupMode::FromKeeper: LOOKUP_REGKEY.pushValue(L2); // {} STACK_CHECK( L2, 1); ASSERT_L( lua_istable( L2, -1)); @@ -778,7 +798,7 @@ static bool lookup_table(lua_State* L2, lua_State* L, int i, LookupMode mode_, c lua_rawget( L2, -2); // {} 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! - if( lua_isnil( L2, -1) && mode_ == eLM_LaneBody) + if (lua_isnil(L2, -1) && mode_ == LookupMode::LaneBody) { lua_pop( L2, 2); // STACK_CHECK( L2, 0); @@ -793,9 +813,9 @@ static bool lookup_table(lua_State* L2, lua_State* L, int i, LookupMode mode_, c lua_getglobal( L2, "decoda_name"); // {} t decoda_name to = lua_tostring( L2, -1); lua_pop( L2, 1); // {} t - // when mode_ == eLM_FromKeeper, L is a keeper state and L2 is not, therefore L2 is the state where we want to raise the error + // 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 (void) luaL_error( - (mode_ == eLM_FromKeeper) ? L2 : L + (mode_ == LookupMode::FromKeeper) ? L2 : L , "INTERNAL ERROR IN %s: table '%s' not found in %s destination transfer database." , from ? from : "main" , fqn @@ -810,6 +830,7 @@ static bool lookup_table(lua_State* L2, lua_State* L, int i, LookupMode mode_, c return true; } +// ################################################################################################# /* * Check if we've already copied the same table from 'L', and @@ -852,6 +873,7 @@ static bool push_cached_table(lua_State* L2, int L2_cache_i, lua_State* L, int i return !not_found_in_cache; } +// ################################################################################################# /* * Return some name helping to identify an object @@ -998,6 +1020,7 @@ static int discover_object_name_recur( lua_State* L, int shortest_, int depth_) return shortest_; } +// ################################################################################################# /* * "type", "name" = lanes.nameof( o) @@ -1046,6 +1069,7 @@ int luaG_nameof( lua_State* L) return 2; } +// ################################################################################################# /* * Push a looked-up native/LuaJIT function. @@ -1064,14 +1088,14 @@ static void lookup_native_func(lua_State* L2, lua_State* L, int i, LookupMode mo (void) luaL_error( L, "internal error: unknown lookup mode"); return; - case eLM_ToKeeper: + case LookupMode::ToKeeper: // push a sentinel closure that holds the lookup name as upvalue lua_pushlstring( L2, fqn, len); // "f.q.n" lua_pushcclosure( L2, func_lookup_sentinel, 1); // f break; - case eLM_LaneBody: - case eLM_FromKeeper: + case LookupMode::LaneBody: + case LookupMode::FromKeeper: LOOKUP_REGKEY.pushValue(L2); // {} STACK_CHECK( L2, 1); ASSERT_L( lua_istable( L2, -1)); @@ -1088,9 +1112,9 @@ static void lookup_native_func(lua_State* L2, lua_State* L, int i, LookupMode mo lua_getglobal( L2, "decoda_name"); // {} f decoda_name to = lua_tostring( L2, -1); lua_pop( L2, 1); // {} f - // when mode_ == eLM_FromKeeper, L is a keeper state and L2 is not, therefore L2 is the state where we want to raise the error + // 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 (void) luaL_error( - (mode_ == eLM_FromKeeper) ? L2 : L + (mode_ == LookupMode::FromKeeper) ? L2 : L , "%s%s: function '%s' not found in %s destination transfer database." , lua_isnil( L2, -1) ? "" : "INTERNAL ERROR IN " , from ? from : "main" @@ -1103,7 +1127,7 @@ static void lookup_native_func(lua_State* L2, lua_State* L, int i, LookupMode mo break; /* keep it in case I need it someday, who knows... - case eLM_RawFunctions: + case LookupMode::RawFunctions: { int n; char const* upname; @@ -1121,6 +1145,7 @@ static void lookup_native_func(lua_State* L2, lua_State* L, int i, LookupMode mo STACK_CHECK( L2, 1); } +// ################################################################################################# /* * Copy a function over, which has not been found in the cache. @@ -1144,12 +1169,14 @@ static char const* lua_type_names[] = }; static char const* vt_names[] = { - "VT_NORMAL" - , "VT_KEY" - , "VT_METATABLE" + "VT::NORMAL" + , "VT::KEY" + , "VT::METATABLE" }; #endif // USE_DEBUG_SPEW() +// ################################################################################################# + // Lua 5.4.3 style of dumping (see lstrlib.c) // we have to do it that way because we can't unbalance the stack between buffer operations // namely, this means we can't push a function on top of the stack *after* we initialize the buffer! @@ -1165,6 +1192,8 @@ static int buf_writer( lua_State* L, void const* b, size_t size, void* ud) return 0; } +// ################################################################################################# + static void copy_func(Universe* U, lua_State* L2, int L2_cache_i, lua_State* L, int i, LookupMode mode_, char const* upName_) { int n, needToPush; @@ -1277,7 +1306,7 @@ static void copy_func(Universe* U, lua_State* L2, int L2_cache_i, lua_State* L, #endif // LUA_VERSION_NUM { DEBUGSPEW_CODE( fprintf( stderr, "copying value\n")); - if( !inter_copy_one( U, L2, L2_cache_i, L, lua_gettop( L), VT_NORMAL, mode_, upname)) // ... {cache} ... function <upvalues> + if( !inter_copy_one( U, L2, L2_cache_i, L, lua_gettop( L), VT::NORMAL, mode_, upname)) // ... {cache} ... function <upvalues> { luaL_error( L, "Cannot copy upvalue type '%s'", luaL_typename( L, -1)); } @@ -1311,6 +1340,8 @@ static void copy_func(Universe* U, lua_State* L2, int L2_cache_i, lua_State* L, STACK_CHECK( L, 0); } +// ################################################################################################# + /* * Check if we've already copied the same function from 'L', and reuse the old * copy. @@ -1370,6 +1401,8 @@ static void copy_cached_func(Universe* U, lua_State* L2, int L2_cache_i, lua_Sta } } +// ################################################################################################# + static bool push_cached_metatable(Universe* U, lua_State* L2, int L2_cache_i, lua_State* L, int i, LookupMode mode_, char const* upName_) { STACK_CHECK_START_REL(L, 0); @@ -1389,7 +1422,7 @@ static bool push_cached_metatable(Universe* U, lua_State* L2, int L2_cache_i, lu if( lua_isnil( L2, -1)) { // L2 did not know the metatable lua_pop( L2, 1); // _R[REG_MTID] - if( inter_copy_one( U, L2, L2_cache_i, L, lua_gettop( L), VT_METATABLE, mode_, upName_)) // _R[REG_MTID] mt + if (inter_copy_one(U, L2, L2_cache_i, L, lua_gettop( L), VT::METATABLE, mode_, upName_)) // _R[REG_MTID] mt { STACK_CHECK( L2, 2); // mt_id -> metatable @@ -1419,13 +1452,15 @@ static bool push_cached_metatable(Universe* U, lua_State* L2, int L2_cache_i, lu return false; } -static void inter_copy_keyvaluepair(Universe* U, lua_State* L2, int L2_cache_i, lua_State* L, enum e_vt vt, LookupMode mode_, char const* upName_) +// ################################################################################################# + +static void inter_copy_keyvaluepair(Universe* U, lua_State* L2, int L2_cache_i, lua_State* L, VT vt_, LookupMode mode_, char const* upName_) { int val_i = lua_gettop(L); int key_i = val_i - 1; // Only basic key types are copied over; others ignored - if( inter_copy_one( U, L2, 0 /*key*/, L, key_i, VT_KEY, mode_, upName_)) + if (inter_copy_one(U, L2, 0 /*key*/, L, key_i, VT::KEY, mode_, upName_)) { char* valPath = (char*) upName_; if( U->verboseErrors) @@ -1471,18 +1506,20 @@ static void inter_copy_keyvaluepair(Universe* U, lua_State* L2, int L2_cache_i, * Contents of metatables are copied with cache checking; * important to detect loops. */ - if( inter_copy_one( U, L2, L2_cache_i, L, val_i, VT_NORMAL, mode_, valPath)) + if (inter_copy_one(U, L2, L2_cache_i, L, val_i, VT::NORMAL, mode_, valPath)) { ASSERT_L( lua_istable( L2, -3)); lua_rawset( L2, -3); // add to table (pops key & val) } else { - luaL_error( L, "Unable to copy %s entry '%s' because of value is of type '%s'", (vt == VT_NORMAL) ? "table" : "metatable", valPath, luaL_typename( L, val_i)); + luaL_error(L, "Unable to copy %s entry '%s' because of value is of type '%s'", (vt_ == VT::NORMAL) ? "table" : "metatable", valPath, luaL_typename(L, val_i)); } } } +// ################################################################################################# + /* * The clone cache is a weak valued table listing all clones, indexed by their userdatapointer * fnv164 of string "CLONABLES_CACHE_KEY" generated at https://www.pelock.com/products/hash-calculator @@ -1541,9 +1578,9 @@ static bool copyclone(Universe* U, lua_State* L2, int L2_cache_i, lua_State* L, // create the clone userdata with the required number of uservalue slots clone = lua_newuserdatauv( L2, userdata_size, uvi); // ... u // copy the metatable in the target state, and give it to the clone we put there - if( inter_copy_one( U, L2, L2_cache_i, L, mt, VT_NORMAL, mode_, upName_)) // ... u mt|sentinel + if (inter_copy_one(U, L2, L2_cache_i, L, mt, VT::NORMAL, mode_, upName_)) // ... u mt|sentinel { - if( eLM_ToKeeper == mode_) // ... u sentinel + if( LookupMode::ToKeeper == mode_) // ... u sentinel { ASSERT_L( lua_tocfunction( L2, -1) == table_lookup_sentinel); // we want to create a new closure with a 'clone sentinel' function, where the upvalues are the userdata and the metatable fqn @@ -1568,21 +1605,21 @@ static bool copyclone(Universe* U, lua_State* L2, int L2_cache_i, lua_State* L, lua_pushvalue( L2, -2); // ... u source u lua_rawset( L2, L2_cache_i); // ... u // make sure we have the userdata now - if( eLM_ToKeeper == mode_) // ... userdata_clone_sentinel + if( LookupMode::ToKeeper == mode_) // ... userdata_clone_sentinel { lua_getupvalue( L2, -1, 2); // ... userdata_clone_sentinel u } // assign uservalues while( uvi > 0) { - inter_copy_one( U, L2, L2_cache_i, L, lua_absindex( L, -1), VT_NORMAL, mode_, upName_); // ... u uv + inter_copy_one(U, L2, L2_cache_i, L, lua_absindex( L, -1), VT::NORMAL, mode_, upName_); // ... u uv lua_pop( L, 1); // ... mt __lanesclone [uv]* // this pops the value from the stack lua_setiuservalue( L2, -2, uvi); // ... u -- uvi; } // when we are done, all uservalues are popped from the source stack, and we want only the single transferred value in the destination - if( eLM_ToKeeper == mode_) // ... userdata_clone_sentinel u + if( LookupMode::ToKeeper == mode_) // ... userdata_clone_sentinel u { lua_pop( L2, 1); // ... userdata_clone_sentinel } @@ -1602,11 +1639,13 @@ static bool copyclone(Universe* U, lua_State* L2, int L2_cache_i, lua_State* L, return true; } -static bool inter_copy_userdata(Universe* U, lua_State* L2, int L2_cache_i, lua_State* L, int i, enum e_vt vt, LookupMode mode_, char const* upName_) +// ################################################################################################# + +static bool inter_copy_userdata(Universe* U, lua_State* L2, int L2_cache_i, lua_State* L, int i, VT vt_, LookupMode mode_, char const* upName_) { STACK_CHECK_START_REL(L, 0); STACK_CHECK_START_REL(L2, 0); - if( vt == VT_KEY) + if (vt_ == VT::KEY) { return false; } @@ -1650,9 +1689,11 @@ static bool inter_copy_userdata(Universe* U, lua_State* L2, int L2_cache_i, lua_ return true; } -static bool inter_copy_function(Universe* U, lua_State* L2, int L2_cache_i, lua_State* L, int source_i_, enum e_vt vt, LookupMode mode_, char const* upName_) +// ################################################################################################# + +static bool inter_copy_function(Universe* U, lua_State* L2, int L2_cache_i, lua_State* L, int source_i_, VT vt_, LookupMode mode_, char const* upName_) { - if( vt == VT_KEY) + if (vt_ == VT::KEY) { return false; } @@ -1709,7 +1750,7 @@ static bool inter_copy_function(Universe* U, lua_State* L2, int L2_cache_i, lua_ // transfer and assign uservalues while( uvi > 0) { - inter_copy_one( U, L2, L2_cache_i, L, lua_absindex( L, -1), vt, mode_, upName_); // ... mt u uv + inter_copy_one(U, L2, L2_cache_i, L, lua_absindex(L, -1), vt_, mode_, upName_); // ... mt u uv lua_pop( L, 1); // ... u [uv]* // this pops the value from the stack lua_setiuservalue( L2, -2, uvi); // ... mt u @@ -1743,9 +1784,11 @@ static bool inter_copy_function(Universe* U, lua_State* L2, int L2_cache_i, lua_ return true; } -static bool inter_copy_table(Universe* U, lua_State* L2, int L2_cache_i, lua_State* L, int i, enum e_vt vt, LookupMode mode_, char const* upName_) +// ################################################################################################# + +static bool inter_copy_table(Universe* U, lua_State* L2, int L2_cache_i, lua_State* L, int i, VT vt_, LookupMode mode_, char const* upName_) { - if( vt == VT_KEY) + if (vt_ == VT::KEY) { return false; } @@ -1787,7 +1830,7 @@ static bool inter_copy_table(Universe* U, lua_State* L2, int L2_cache_i, lua_Sta while( lua_next( L, i)) { // need a function to prevent overflowing the stack with verboseErrors-induced alloca() - inter_copy_keyvaluepair( U, L2, L2_cache_i, L, vt, mode_, upName_); + inter_copy_keyvaluepair(U, L2, L2_cache_i, L, vt_, mode_, upName_); lua_pop( L, 1); // pop value (next round) } STACK_CHECK( L, 0); @@ -1803,6 +1846,8 @@ static bool inter_copy_table(Universe* U, lua_State* L2, int L2_cache_i, lua_Sta return true; } +// ################################################################################################# + /* * Copies a value from 'L' state (at index 'i') to 'L2' state. Does not remove * the original value. @@ -1813,7 +1858,7 @@ static bool inter_copy_table(Universe* U, lua_State* L2, int L2_cache_i, lua_Sta * * Returns true if value was pushed, false if its type is non-supported. */ -bool inter_copy_one(Universe* U, lua_State* L2, int L2_cache_i, lua_State* L, int i, enum e_vt vt, LookupMode mode_, char const* upName_) +bool inter_copy_one(Universe* U, lua_State* L2, int L2_cache_i, lua_State* L, int i, VT vt_, LookupMode mode_, char const* upName_) { bool ret{ true }; int val_type = lua_type( L, i); @@ -1824,7 +1869,7 @@ bool inter_copy_one(Universe* U, lua_State* L2, int L2_cache_i, lua_State* L, in DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "inter_copy_one()\n" INDENT_END)); DEBUGSPEW_CODE( ++ U->debugspew_indent_depth); - DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "%s %s: " INDENT_END, lua_type_names[val_type], vt_names[vt])); + DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "%s %s: " INDENT_END, lua_type_names[val_type], vt_names[static_cast<int>(vt_)])); // Non-POD can be skipped if its metatable contains { __lanesignore = true } if( ((1 << val_type) & pod_mask) == 0) @@ -1894,11 +1939,11 @@ bool inter_copy_one(Universe* U, lua_State* L2, int L2_cache_i, lua_State* L, in /* The following types are not allowed as table keys */ case LUA_TUSERDATA: - ret = inter_copy_userdata( U, L2, L2_cache_i, L, i, vt, mode_, upName_); + ret = inter_copy_userdata(U, L2, L2_cache_i, L, i, vt_, mode_, upName_); break; case LUA_TNIL: - if( vt == VT_KEY) + if (vt_ == VT::KEY) { ret = false; break; @@ -1907,11 +1952,11 @@ bool inter_copy_one(Universe* U, lua_State* L2, int L2_cache_i, lua_State* L, in break; case LUA_TFUNCTION: - ret = inter_copy_function( U, L2, L2_cache_i, L, i, vt, mode_, upName_); + ret = inter_copy_function(U, L2, L2_cache_i, L, i, vt_, mode_, upName_); break; case LUA_TTABLE: - ret = inter_copy_table( U, L2, L2_cache_i, L, i, vt, mode_, upName_); + ret = inter_copy_table(U, L2, L2_cache_i, L, i, vt_, mode_, upName_); break; /* The following types cannot be copied */ @@ -1973,7 +2018,7 @@ int luaG_inter_copy(Universe* U, lua_State* L, lua_State* L2, int n, LookupMode { sprintf( tmpBuf, "arg_%d", j); } - copyok = inter_copy_one( U, L2, top_L2 + 1, L, i, VT_NORMAL, mode_, pBuf); // ... cache {}n + copyok = inter_copy_one(U, L2, top_L2 + 1, L, i, VT::NORMAL, mode_, pBuf); // ... cache {}n if( !copyok) { break; @@ -2019,7 +2064,7 @@ int luaG_inter_copy_package( Universe* U, lua_State* L, lua_State* L2, int packa lua_pushfstring( L, "expected package as table, got %s", luaL_typename( L, package_idx_)); STACK_CHECK( L, 1); // raise the error when copying from lane to lane, else just leave it on the stack to be raised later - return ( mode_ == eLM_LaneBody) ? lua_error( L) : 1; + return (mode_ == LookupMode::LaneBody) ? lua_error(L) : 1; } lua_getglobal( L2, "package"); if( !lua_isnil( L2, -1)) // package library not loaded: do nothing @@ -2029,7 +2074,7 @@ int luaG_inter_copy_package( Universe* U, lua_State* L, lua_State* L2, int packa // but don't copy it anyway, as the function names change depending on the slot index! // users should provide an on_state_create function to setup custom loaders instead // don't copy package.preload in keeper states (they don't know how to translate functions) - char const* entries[] = { "path", "cpath", (mode_ == eLM_LaneBody) ? "preload" : nullptr /*, (LUA_VERSION_NUM == 501) ? "loaders" : "searchers"*/, nullptr }; + char const* entries[] = { "path", "cpath", (mode_ == LookupMode::LaneBody) ? "preload" : nullptr /*, (LUA_VERSION_NUM == 501) ? "loaders" : "searchers"*/, nullptr }; for( i = 0; entries[i]; ++ i) { DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "package.%s\n" INDENT_END, entries[i])); diff --git a/src/tools.h b/src/tools.h index 5e6ce78..c1a8534 100644 --- a/src/tools.h +++ b/src/tools.h @@ -19,13 +19,13 @@ void luaG_dump( lua_State* L); void push_registry_subtable_mode( lua_State* L, UniqueKey key_, const char* mode_); void push_registry_subtable( lua_State* L, UniqueKey key_); -enum e_vt +enum class VT { - VT_NORMAL, - VT_KEY, - VT_METATABLE + NORMAL, + KEY, + METATABLE }; -bool inter_copy_one(Universe* U, lua_State* L2, int L2_cache_i, lua_State* L, int i, enum e_vt vt, LookupMode mode_, char const* upName_); +bool inter_copy_one(Universe* U, lua_State* L2, int L2_cache_i, lua_State* L, int i, VT vt_, LookupMode mode_, char const* upName_); // ################################################################################################ diff --git a/src/universe.h b/src/universe.h index a2ad5f5..3ee0868 100644 --- a/src/universe.h +++ b/src/universe.h @@ -13,13 +13,13 @@ extern "C" { #include <mutex> +// ################################################################################################ + // forwards struct DeepPrelude; struct Keepers; class Lane; -// ################################################################################################ - /* * Do we want to activate full lane tracking feature? (EXPERIMENTAL) */ @@ -167,6 +167,8 @@ struct Universe int volatile selfdestructing_count{ 0 }; }; +// ################################################################################################ + Universe* universe_get(lua_State* L); Universe* universe_create(lua_State* L); void universe_store(lua_State* L, Universe* U); -- cgit v1.2.3-55-g6feb