diff options
| author | Benoit Germain <benoit.germain@ubisoft.com> | 2024-05-29 17:31:45 +0200 |
|---|---|---|
| committer | Benoit Germain <benoit.germain@ubisoft.com> | 2024-05-29 17:31:45 +0200 |
| commit | a156aaeb07fada043b308409dcffcae1726eec0b (patch) | |
| tree | f15a5d60cda30607260d896598ea33f8619af53a | |
| parent | d47758d58d532a9716ad4fd85cc806704df13735 (diff) | |
| download | lanes-a156aaeb07fada043b308409dcffcae1726eec0b.tar.gz lanes-a156aaeb07fada043b308409dcffcae1726eec0b.tar.bz2 lanes-a156aaeb07fada043b308409dcffcae1726eec0b.zip | |
Fix clang-tidy issues (most notably Microsoft-specific explicit constructor calls)
| -rw-r--r-- | src/deep.h | 18 | ||||
| -rw-r--r-- | src/intercopycontext.cpp | 5 | ||||
| -rw-r--r-- | src/lane.cpp | 2 | ||||
| -rw-r--r-- | src/lanes.cpp | 18 | ||||
| -rw-r--r-- | src/lanes.lua | 4 | ||||
| -rw-r--r-- | src/linda.cpp | 2 | ||||
| -rw-r--r-- | src/lindafactory.cpp | 2 | ||||
| -rw-r--r-- | src/macros_and_utils.h | 2 | ||||
| -rw-r--r-- | src/state.cpp | 4 | ||||
| -rw-r--r-- | src/tools.cpp | 10 | ||||
| -rw-r--r-- | src/universe.cpp | 40 | ||||
| -rw-r--r-- | src/universe.h | 25 | ||||
| -rw-r--r-- | tests/keeper.lua | 2 |
13 files changed, 71 insertions, 63 deletions
| @@ -64,21 +64,21 @@ class DeepFactory | |||
| 64 | 64 | ||
| 65 | private: | 65 | private: |
| 66 | // NVI: private overrides | 66 | // NVI: private overrides |
| 67 | virtual void createMetatable(lua_State* const L_) const = 0; | 67 | virtual void createMetatable(lua_State* L_) const = 0; |
| 68 | virtual void deleteDeepObjectInternal(lua_State* const L_, DeepPrelude* const o_) const = 0; | 68 | virtual void deleteDeepObjectInternal(lua_State* L_, DeepPrelude* o_) const = 0; |
| 69 | [[nodiscard]] virtual DeepPrelude* newDeepObjectInternal(lua_State* const L_) const = 0; | 69 | [[nodiscard]] virtual DeepPrelude* newDeepObjectInternal(lua_State* L_) const = 0; |
| 70 | [[nodiscard]] virtual std::string_view moduleName() const = 0; | 70 | [[nodiscard]] virtual std::string_view moduleName() const = 0; |
| 71 | 71 | ||
| 72 | private: | 72 | private: |
| 73 | void storeDeepLookup(lua_State* const L_) const; | 73 | void storeDeepLookup(lua_State* L_) const; |
| 74 | 74 | ||
| 75 | public: | 75 | public: |
| 76 | // NVI: public interface | 76 | // NVI: public interface |
| 77 | static void DeleteDeepObject(lua_State* const L_, DeepPrelude* const o_); | 77 | static void DeleteDeepObject(lua_State* L_, DeepPrelude* o_); |
| 78 | [[nodiscard]] static DeepFactory* LookupFactory(lua_State* const L_, int const index_, LookupMode const mode_); | 78 | [[nodiscard]] static DeepFactory* LookupFactory(lua_State* L_, int index_, LookupMode mode_); |
| 79 | static void PushDeepProxy(DestState const L_, DeepPrelude* const o_, int const nuv_, LookupMode const mode_, lua_State* const errL_); | 79 | static void PushDeepProxy(DestState L_, DeepPrelude* o_, int nuv_, LookupMode mode_, lua_State* errL_); |
| 80 | [[nodiscard]] int pushDeepUserdata(DestState const L_, int const nuv_) const; | 80 | [[nodiscard]] int pushDeepUserdata(DestState L_, int nuv_) const; |
| 81 | [[nodiscard]] DeepPrelude* toDeep(lua_State* const L_, int const index_) const; | 81 | [[nodiscard]] DeepPrelude* toDeep(lua_State* L_, int index_) const; |
| 82 | }; | 82 | }; |
| 83 | 83 | ||
| 84 | // ################################################################################################# | 84 | // ################################################################################################# |
diff --git a/src/intercopycontext.cpp b/src/intercopycontext.cpp index eddb309..3557c7b 100644 --- a/src/intercopycontext.cpp +++ b/src/intercopycontext.cpp | |||
| @@ -101,7 +101,7 @@ THE SOFTWARE. | |||
| 101 | lua_rawget(L1, -2); // L1: ... v ... {} "f.q.n" | 101 | lua_rawget(L1, -2); // L1: ... v ... {} "f.q.n" |
| 102 | } | 102 | } |
| 103 | std::string_view _fqn{ lua_tostringview(L1, -1) }; | 103 | std::string_view _fqn{ lua_tostringview(L1, -1) }; |
| 104 | DEBUGSPEW_CODE(DebugSpew(universe_get(L1)) << "function [C] " << _fqn << std::endl); | 104 | DEBUGSPEW_CODE(DebugSpew(Universe::Get(L1)) << "function [C] " << _fqn << std::endl); |
| 105 | // popping doesn't invalidate the pointer since this is an interned string gotten from the lookup database | 105 | // popping doesn't invalidate the pointer since this is an interned string gotten from the lookup database |
| 106 | lua_pop(L1, (mode == LookupMode::FromKeeper) ? 1 : 2); // L1: ... v ... | 106 | lua_pop(L1, (mode == LookupMode::FromKeeper) ? 1 : 2); // L1: ... v ... |
| 107 | STACK_CHECK(L1, 0); | 107 | STACK_CHECK(L1, 0); |
| @@ -1142,6 +1142,7 @@ namespace { | |||
| 1142 | break; | 1142 | break; |
| 1143 | 1143 | ||
| 1144 | // The following types cannot be copied | 1144 | // The following types cannot be copied |
| 1145 | case LuaType::NONE: | ||
| 1145 | case LuaType::CDATA: | 1146 | case LuaType::CDATA: |
| 1146 | [[fallthrough]]; | 1147 | [[fallthrough]]; |
| 1147 | case LuaType::THREAD: | 1148 | case LuaType::THREAD: |
| @@ -1175,7 +1176,7 @@ namespace { | |||
| 1175 | OnExit(lua_State* L2_) | 1176 | OnExit(lua_State* L2_) |
| 1176 | : L2{ L2_ } | 1177 | : L2{ L2_ } |
| 1177 | , top_L2{ lua_gettop(L2) } | 1178 | , top_L2{ lua_gettop(L2) } |
| 1178 | DEBUGSPEW_COMMA_PARAM(scope{ universe_get(L2_) }) | 1179 | DEBUGSPEW_COMMA_PARAM(scope{ Universe::Get(L2_) }) |
| 1179 | { | 1180 | { |
| 1180 | } | 1181 | } |
| 1181 | 1182 | ||
diff --git a/src/lane.cpp b/src/lane.cpp index eef9e6e..22147f1 100644 --- a/src/lane.cpp +++ b/src/lane.cpp | |||
| @@ -669,7 +669,7 @@ static void lane_main(Lane* lane_) | |||
| 669 | // At this point, the lane function and arguments are on the stack, possibly preceded by the error handler | 669 | // At this point, the lane function and arguments are on the stack, possibly preceded by the error handler |
| 670 | int const _errorHandlerCount{ lane_->errorTraceLevel == Lane::Minimal ? 0 : 1}; | 670 | int const _errorHandlerCount{ lane_->errorTraceLevel == Lane::Minimal ? 0 : 1}; |
| 671 | int const _nargs{ lua_gettop(_L) - 1 - _errorHandlerCount }; | 671 | int const _nargs{ lua_gettop(_L) - 1 - _errorHandlerCount }; |
| 672 | DEBUGSPEW_CODE(Universe* _U = universe_get(_L)); | 672 | DEBUGSPEW_CODE(Universe* _U = Universe::Get(_L)); |
| 673 | lane_->status = Lane::Running; // Pending -> Running | 673 | lane_->status = Lane::Running; // Pending -> Running |
| 674 | 674 | ||
| 675 | PrepareLaneHelpers(lane_); | 675 | PrepareLaneHelpers(lane_); |
diff --git a/src/lanes.cpp b/src/lanes.cpp index 9fc7fc9..b74e9ec 100644 --- a/src/lanes.cpp +++ b/src/lanes.cpp | |||
| @@ -143,7 +143,7 @@ LUAG_FUNC(set_thread_priority) | |||
| 143 | if (_prio < kThreadPrioMin || _prio > kThreadPrioMax) { | 143 | if (_prio < kThreadPrioMin || _prio > kThreadPrioMax) { |
| 144 | raise_luaL_error(L_, "priority out of range: %d..+%d (%d)", kThreadPrioMin, kThreadPrioMax, _prio); | 144 | raise_luaL_error(L_, "priority out of range: %d..+%d (%d)", kThreadPrioMin, kThreadPrioMax, _prio); |
| 145 | } | 145 | } |
| 146 | THREAD_SET_PRIORITY(static_cast<int>(_prio), universe_get(L_)->sudo); | 146 | THREAD_SET_PRIORITY(static_cast<int>(_prio), Universe::Get(L_)->sudo); |
| 147 | return 0; | 147 | return 0; |
| 148 | } | 148 | } |
| 149 | 149 | ||
| @@ -169,7 +169,7 @@ LUAG_FUNC(require) | |||
| 169 | { | 169 | { |
| 170 | std::string_view const _name{ lua_tostringview(L_, 1) }; // L_: "name" ... | 170 | std::string_view const _name{ lua_tostringview(L_, 1) }; // L_: "name" ... |
| 171 | int const _nargs{ lua_gettop(L_) }; | 171 | int const _nargs{ lua_gettop(L_) }; |
| 172 | DEBUGSPEW_CODE(Universe * _U{ universe_get(L_) }); | 172 | DEBUGSPEW_CODE(Universe * _U{ Universe::Get(L_) }); |
| 173 | STACK_CHECK_START_REL(L_, 0); | 173 | STACK_CHECK_START_REL(L_, 0); |
| 174 | DEBUGSPEW_CODE(DebugSpew(_U) << "lanes.require '" << _name << "' BEGIN" << std::endl); | 174 | DEBUGSPEW_CODE(DebugSpew(_U) << "lanes.require '" << _name << "' BEGIN" << std::endl); |
| 175 | DEBUGSPEW_CODE(DebugSpewIndentScope _scope{ _U }); | 175 | DEBUGSPEW_CODE(DebugSpewIndentScope _scope{ _U }); |
| @@ -194,7 +194,7 @@ LUAG_FUNC(register) | |||
| 194 | // ignore extra parameters, just in case | 194 | // ignore extra parameters, just in case |
| 195 | lua_settop(L_, 2); | 195 | lua_settop(L_, 2); |
| 196 | luaL_argcheck(L_, (_mod_type == LuaType::TABLE) || (_mod_type == LuaType::FUNCTION), 2, "unexpected module type"); | 196 | luaL_argcheck(L_, (_mod_type == LuaType::TABLE) || (_mod_type == LuaType::FUNCTION), 2, "unexpected module type"); |
| 197 | DEBUGSPEW_CODE(Universe* _U = universe_get(L_)); | 197 | DEBUGSPEW_CODE(Universe* _U = Universe::Get(L_)); |
| 198 | STACK_CHECK_START_REL(L_, 0); // "name" mod_table | 198 | STACK_CHECK_START_REL(L_, 0); // "name" mod_table |
| 199 | DEBUGSPEW_CODE(DebugSpew(_U) << "lanes.register '" << _name << "' BEGIN" << std::endl); | 199 | DEBUGSPEW_CODE(DebugSpew(_U) << "lanes.register '" << _name << "' BEGIN" << std::endl); |
| 200 | DEBUGSPEW_CODE(DebugSpewIndentScope _scope{ _U }); | 200 | DEBUGSPEW_CODE(DebugSpewIndentScope _scope{ _U }); |
| @@ -236,7 +236,7 @@ LUAG_FUNC(lane_new) | |||
| 236 | int const _nargs{ lua_gettop(L_) - kFixedArgsIdx }; | 236 | int const _nargs{ lua_gettop(L_) - kFixedArgsIdx }; |
| 237 | LUA_ASSERT(L_, _nargs >= 0); | 237 | LUA_ASSERT(L_, _nargs >= 0); |
| 238 | 238 | ||
| 239 | Universe* const _U{ universe_get(L_) }; | 239 | Universe* const _U{ Universe::Get(L_) }; |
| 240 | DEBUGSPEW_CODE(DebugSpew(_U) << "lane_new: setup" << std::endl); | 240 | DEBUGSPEW_CODE(DebugSpew(_U) << "lane_new: setup" << std::endl); |
| 241 | 241 | ||
| 242 | std::optional<std::string_view> _libs_str{ lua_isnil(L_, kLibsIdx) ? std::nullopt : std::make_optional(lua_tostringview(L_, kLibsIdx)) }; | 242 | std::optional<std::string_view> _libs_str{ lua_isnil(L_, kLibsIdx) ? std::nullopt : std::make_optional(lua_tostringview(L_, kLibsIdx)) }; |
| @@ -510,7 +510,7 @@ LUAG_FUNC(lane_new) | |||
| 510 | // Return a list of all known lanes | 510 | // Return a list of all known lanes |
| 511 | LUAG_FUNC(threads) | 511 | LUAG_FUNC(threads) |
| 512 | { | 512 | { |
| 513 | LaneTracker const& _tracker = universe_get(L_)->tracker; | 513 | LaneTracker const& _tracker = Universe::Get(L_)->tracker; |
| 514 | return _tracker.pushThreadsTable(L_); | 514 | return _tracker.pushThreadsTable(L_); |
| 515 | } | 515 | } |
| 516 | 516 | ||
| @@ -616,7 +616,7 @@ LUAG_FUNC(configure) | |||
| 616 | // start with one-time initializations. | 616 | // start with one-time initializations. |
| 617 | { | 617 | { |
| 618 | // C++ guarantees that the static variable initialization is threadsafe. | 618 | // C++ guarantees that the static variable initialization is threadsafe. |
| 619 | static auto _ = std::invoke( | 619 | [[maybe_unused]] static auto _ = std::invoke( |
| 620 | []() { | 620 | []() { |
| 621 | #if (defined PLATFORM_OSX) && (defined _UTILBINDTHREADTOCPU) | 621 | #if (defined PLATFORM_OSX) && (defined _UTILBINDTHREADTOCPU) |
| 622 | chudInitialize(); | 622 | chudInitialize(); |
| @@ -625,7 +625,7 @@ LUAG_FUNC(configure) | |||
| 625 | }); | 625 | }); |
| 626 | } | 626 | } |
| 627 | 627 | ||
| 628 | Universe* _U{ universe_get(L_) }; | 628 | Universe* _U{ Universe::Get(L_) }; |
| 629 | bool const _from_master_state{ _U == nullptr }; | 629 | bool const _from_master_state{ _U == nullptr }; |
| 630 | std::string_view const _name{ luaL_checkstringview(L_, lua_upvalueindex(1)) }; | 630 | std::string_view const _name{ luaL_checkstringview(L_, lua_upvalueindex(1)) }; |
| 631 | LUA_ASSERT(L_, lua_type(L_, 1) == LUA_TTABLE); | 631 | LUA_ASSERT(L_, lua_type(L_, 1) == LUA_TTABLE); |
| @@ -637,12 +637,12 @@ LUAG_FUNC(configure) | |||
| 637 | DEBUGSPEW_CODE(DebugSpewIndentScope _scope{ _U }); | 637 | DEBUGSPEW_CODE(DebugSpewIndentScope _scope{ _U }); |
| 638 | 638 | ||
| 639 | if (_U == nullptr) { | 639 | if (_U == nullptr) { |
| 640 | _U = universe_create(L_); // L_: settings universe | 640 | _U = Universe::Create(L_); // L_: settings universe |
| 641 | DEBUGSPEW_CODE(DebugSpewIndentScope _scope2{ _U }); | 641 | DEBUGSPEW_CODE(DebugSpewIndentScope _scope2{ _U }); |
| 642 | lua_createtable(L_, 0, 1); // L_: settings universe {mt} | 642 | lua_createtable(L_, 0, 1); // L_: settings universe {mt} |
| 643 | std::ignore = luaG_getfield(L_, 1, "shutdown_timeout"); // L_: settings universe {mt} shutdown_timeout | 643 | std::ignore = luaG_getfield(L_, 1, "shutdown_timeout"); // L_: settings universe {mt} shutdown_timeout |
| 644 | std::ignore = luaG_getfield(L_, 1, "shutdown_mode"); // L_: settings universe {mt} shutdown_timeout shutdown_mode | 644 | std::ignore = luaG_getfield(L_, 1, "shutdown_mode"); // L_: settings universe {mt} shutdown_timeout shutdown_mode |
| 645 | lua_pushcclosure(L_, universe_gc, 2); // L_: settings universe {mt} universe_gc | 645 | lua_pushcclosure(L_, LG_universe_gc, 2); // L_: settings universe {mt} LG_universe_gc |
| 646 | lua_setfield(L_, -2, "__gc"); // L_: settings universe {mt} | 646 | lua_setfield(L_, -2, "__gc"); // L_: settings universe {mt} |
| 647 | lua_setmetatable(L_, -2); // L_: settings universe | 647 | lua_setmetatable(L_, -2); // L_: settings universe |
| 648 | lua_pop(L_, 1); // L_: settings | 648 | lua_pop(L_, 1); // L_: settings |
diff --git a/src/lanes.lua b/src/lanes.lua index 982de98..e7763b1 100644 --- a/src/lanes.lua +++ b/src/lanes.lua | |||
| @@ -115,8 +115,8 @@ end | |||
| 115 | local param_checkers = | 115 | local param_checkers = |
| 116 | { | 116 | { |
| 117 | nb_keepers = function(val_) | 117 | nb_keepers = function(val_) |
| 118 | -- nb_keepers should be a number > 0 | 118 | -- nb_keepers should be a number in [1,100] (so that nobody tries to run OOM by specifying a huge amount) |
| 119 | return type(val_) == "number" and val_ > 0 | 119 | return type(val_) == "number" and val_ > 0 and val_ <= 100 |
| 120 | end, | 120 | end, |
| 121 | keepers_gc_threshold = function(val_) | 121 | keepers_gc_threshold = function(val_) |
| 122 | -- keepers_gc_threshold should be a number | 122 | -- keepers_gc_threshold should be a number |
diff --git a/src/linda.cpp b/src/linda.cpp index 8d09903..76cd347 100644 --- a/src/linda.cpp +++ b/src/linda.cpp | |||
| @@ -100,7 +100,7 @@ template <bool OPT> | |||
| 100 | Linda* const _linda{ static_cast<Linda*>(LindaFactory::Instance.toDeep(L_, idx_)) }; | 100 | Linda* const _linda{ static_cast<Linda*>(LindaFactory::Instance.toDeep(L_, idx_)) }; |
| 101 | if constexpr (!OPT) { | 101 | if constexpr (!OPT) { |
| 102 | luaL_argcheck(L_, _linda != nullptr, idx_, "expecting a linda object"); // doesn't return if linda is nullptr | 102 | luaL_argcheck(L_, _linda != nullptr, idx_, "expecting a linda object"); // doesn't return if linda is nullptr |
| 103 | LUA_ASSERT(L_, _linda->U == universe_get(L_)); | 103 | LUA_ASSERT(L_, _linda->U == Universe::Get(L_)); |
| 104 | } | 104 | } |
| 105 | return _linda; | 105 | return _linda; |
| 106 | } | 106 | } |
diff --git a/src/lindafactory.cpp b/src/lindafactory.cpp index 890cc96..6d26852 100644 --- a/src/lindafactory.cpp +++ b/src/lindafactory.cpp | |||
| @@ -126,7 +126,7 @@ DeepPrelude* LindaFactory::newDeepObjectInternal(lua_State* L_) const | |||
| 126 | 126 | ||
| 127 | // The deep data is allocated separately of Lua stack; we might no longer be around when last reference to it is being released. | 127 | // The deep data is allocated separately of Lua stack; we might no longer be around when last reference to it is being released. |
| 128 | // One can use any memory allocation scheme. Just don't use L's allocF because we don't know which state will get the honor of GCing the linda | 128 | // One can use any memory allocation scheme. Just don't use L's allocF because we don't know which state will get the honor of GCing the linda |
| 129 | Universe* const _U{ universe_get(L_) }; | 129 | Universe* const _U{ Universe::Get(L_) }; |
| 130 | Linda* const _linda{ new (_U) Linda{ _U, _linda_group, _linda_name } }; | 130 | Linda* const _linda{ new (_U) Linda{ _U, _linda_group, _linda_name } }; |
| 131 | return _linda; | 131 | return _linda; |
| 132 | } | 132 | } |
diff --git a/src/macros_and_utils.h b/src/macros_and_utils.h index 1427ef1..7bb0d2a 100644 --- a/src/macros_and_utils.h +++ b/src/macros_and_utils.h | |||
| @@ -178,7 +178,7 @@ inline void STACK_GROW(lua_State* L_, int n_) | |||
| 178 | 178 | ||
| 179 | // ################################################################################################# | 179 | // ################################################################################################# |
| 180 | 180 | ||
| 181 | #define LUAG_FUNC(func_name) [[nodiscard]] int LG_##func_name(lua_State* L_) | 181 | #define LUAG_FUNC(func_name) [[nodiscard]] int LG_##func_name(lua_State* const L_) |
| 182 | 182 | ||
| 183 | // ################################################################################################# | 183 | // ################################################################################################# |
| 184 | 184 | ||
diff --git a/src/state.cpp b/src/state.cpp index 5589c30..7585132 100644 --- a/src/state.cpp +++ b/src/state.cpp | |||
| @@ -105,7 +105,7 @@ namespace { | |||
| 105 | break; | 105 | break; |
| 106 | } | 106 | } |
| 107 | std::string_view const _name{ _entry.name }; | 107 | std::string_view const _name{ _entry.name }; |
| 108 | DEBUGSPEW_CODE(DebugSpew(universe_get(L_)) << "opening '" << _name << "' library" << std::endl); | 108 | DEBUGSPEW_CODE(DebugSpew(Universe::Get(L_)) << "opening '" << _name << "' library" << std::endl); |
| 109 | STACK_CHECK_START_REL(L_, 0); | 109 | STACK_CHECK_START_REL(L_, 0); |
| 110 | // open the library as if through require(), and create a global as well if necessary (the library table is left on the stack) | 110 | // open the library as if through require(), and create a global as well if necessary (the library table is left on the stack) |
| 111 | bool const isLanesCore{ _libfunc == require_lanes_core }; // don't want to create a global for "lanes.core" | 111 | bool const isLanesCore{ _libfunc == require_lanes_core }; // don't want to create a global for "lanes.core" |
| @@ -273,7 +273,7 @@ namespace state { | |||
| 273 | 273 | ||
| 274 | // copy the universe as a light userdata (only the master state holds the full userdata) | 274 | // copy the universe as a light userdata (only the master state holds the full userdata) |
| 275 | // that way, if Lanes is required in this new state, we'll know we are part of this universe | 275 | // that way, if Lanes is required in this new state, we'll know we are part of this universe |
| 276 | universe_store(_L, U_); | 276 | Universe::Store(_L, U_); |
| 277 | STACK_CHECK(_L, 0); | 277 | STACK_CHECK(_L, 0); |
| 278 | 278 | ||
| 279 | // we'll need this every time we transfer some C function from/to this state | 279 | // we'll need this every time we transfer some C function from/to this state |
diff --git a/src/tools.cpp b/src/tools.cpp index e9114e0..94e941d 100644 --- a/src/tools.cpp +++ b/src/tools.cpp | |||
| @@ -133,7 +133,7 @@ static void update_lookup_entry(lua_State* L_, int ctxBase_, int depth_) | |||
| 133 | // slot 2 contains a table that, when concatenated, produces the fully qualified name of scanned elements in the table provided at slot _i | 133 | // slot 2 contains a table that, when concatenated, produces the fully qualified name of scanned elements in the table provided at slot _i |
| 134 | int const _fqn{ ctxBase_ + 1 }; | 134 | int const _fqn{ ctxBase_ + 1 }; |
| 135 | 135 | ||
| 136 | DEBUGSPEW_CODE(Universe* const _U{ universe_get(L_) }); | 136 | DEBUGSPEW_CODE(Universe* const _U{ Universe::Get(L_) }); |
| 137 | DEBUGSPEW_CODE(DebugSpew(_U) << "update_lookup_entry()" << std::endl); | 137 | DEBUGSPEW_CODE(DebugSpew(_U) << "update_lookup_entry()" << std::endl); |
| 138 | DEBUGSPEW_CODE(DebugSpewIndentScope _scope{ _U }); | 138 | DEBUGSPEW_CODE(DebugSpewIndentScope _scope{ _U }); |
| 139 | 139 | ||
| @@ -200,7 +200,7 @@ static void populate_func_lookup_table_recur(lua_State* L_, int dbIdx_, int i_, | |||
| 200 | int const _fqn{ dbIdx_ + 1 }; | 200 | int const _fqn{ dbIdx_ + 1 }; |
| 201 | // slot dbIdx_ + 2 contains a cache that stores all already visited tables to avoid infinite recursion loops | 201 | // slot dbIdx_ + 2 contains a cache that stores all already visited tables to avoid infinite recursion loops |
| 202 | int const _cache{ dbIdx_ + 2 }; | 202 | int const _cache{ dbIdx_ + 2 }; |
| 203 | DEBUGSPEW_CODE(Universe* const _U{ universe_get(L_) }); | 203 | DEBUGSPEW_CODE(Universe* const _U{ Universe::Get(L_) }); |
| 204 | DEBUGSPEW_CODE(DebugSpew(_U) << "populate_func_lookup_table_recur()" << std::endl); | 204 | DEBUGSPEW_CODE(DebugSpew(_U) << "populate_func_lookup_table_recur()" << std::endl); |
| 205 | DEBUGSPEW_CODE(DebugSpewIndentScope _scope{ _U }); | 205 | DEBUGSPEW_CODE(DebugSpewIndentScope _scope{ _U }); |
| 206 | 206 | ||
| @@ -309,7 +309,7 @@ namespace tools { | |||
| 309 | void PopulateFuncLookupTable(lua_State* const L_, int const i_, std::string_view const& name_) | 309 | void PopulateFuncLookupTable(lua_State* const L_, int const i_, std::string_view const& name_) |
| 310 | { | 310 | { |
| 311 | int const _in_base{ lua_absindex(L_, i_) }; | 311 | int const _in_base{ lua_absindex(L_, i_) }; |
| 312 | DEBUGSPEW_CODE(Universe* _U = universe_get(L_)); | 312 | DEBUGSPEW_CODE(Universe* _U = Universe::Get(L_)); |
| 313 | std::string_view _name{ name_.empty() ? std::string_view{} : name_ }; | 313 | std::string_view _name{ name_.empty() ? std::string_view{} : name_ }; |
| 314 | DEBUGSPEW_CODE(DebugSpew(_U) << L_ << ": PopulateFuncLookupTable('" << _name << "')" << std::endl); | 314 | DEBUGSPEW_CODE(DebugSpew(_U) << L_ << ": PopulateFuncLookupTable('" << _name << "')" << std::endl); |
| 315 | DEBUGSPEW_CODE(DebugSpewIndentScope _scope{ _U }); | 315 | DEBUGSPEW_CODE(DebugSpewIndentScope _scope{ _U }); |
| @@ -380,7 +380,7 @@ namespace tools { | |||
| 380 | LuaError const _rc{ std::invoke( | 380 | LuaError const _rc{ std::invoke( |
| 381 | [L = L_, args = _args]() | 381 | [L = L_, args = _args]() |
| 382 | { | 382 | { |
| 383 | std::lock_guard _guard{ universe_get(L)->requireMutex }; | 383 | std::lock_guard _guard{ Universe::Get(L)->requireMutex }; |
| 384 | // starting with Lua 5.4, require may return a second optional value, so we need LUA_MULTRET | 384 | // starting with Lua 5.4, require may return a second optional value, so we need LUA_MULTRET |
| 385 | return lua_pcall(L, args, LUA_MULTRET, 0 /*errfunc*/); // L_: err|result(s) | 385 | return lua_pcall(L, args, LUA_MULTRET, 0 /*errfunc*/); // L_: err|result(s) |
| 386 | }) | 386 | }) |
| @@ -398,7 +398,7 @@ namespace tools { | |||
| 398 | 398 | ||
| 399 | STACK_GROW(L_, 1); | 399 | STACK_GROW(L_, 1); |
| 400 | STACK_CHECK_START_REL(L_, 0); | 400 | STACK_CHECK_START_REL(L_, 0); |
| 401 | DEBUGSPEW_CODE(DebugSpew(universe_get(L_)) << "serializing require()" << std::endl); | 401 | DEBUGSPEW_CODE(DebugSpew(Universe::Get(L_)) << "serializing require()" << std::endl); |
| 402 | 402 | ||
| 403 | // Check 'require' is there and not already wrapped; if not, do nothing | 403 | // Check 'require' is there and not already wrapped; if not, do nothing |
| 404 | lua_getglobal(L_, "require"); // L_: _G.require()|nil | 404 | lua_getglobal(L_, "require"); // L_: _G.require()|nil |
diff --git a/src/universe.cpp b/src/universe.cpp index 77f799b..55c3e69 100644 --- a/src/universe.cpp +++ b/src/universe.cpp | |||
| @@ -40,6 +40,11 @@ THE SOFTWARE. | |||
| 40 | 40 | ||
| 41 | // ################################################################################################# | 41 | // ################################################################################################# |
| 42 | 42 | ||
| 43 | // xxh64 of string "kUniverseFullRegKey" generated at https://www.pelock.com/products/hash-calculator | ||
| 44 | static constexpr RegistryUniqueKey kUniverseFullRegKey{ 0x1C2D76870DD9DD9Full }; | ||
| 45 | |||
| 46 | // ################################################################################################# | ||
| 47 | |||
| 43 | Universe::Universe() | 48 | Universe::Universe() |
| 44 | { | 49 | { |
| 45 | //--- | 50 | //--- |
| @@ -69,12 +74,12 @@ Universe::Universe() | |||
| 69 | // ################################################################################################# | 74 | // ################################################################################################# |
| 70 | 75 | ||
| 71 | // only called from the master state | 76 | // only called from the master state |
| 72 | [[nodiscard]] Universe* universe_create(lua_State* L_) | 77 | [[nodiscard]] Universe* Universe::Create(lua_State* const L_) |
| 73 | { | 78 | { |
| 74 | LUA_ASSERT(L_, universe_get(L_) == nullptr); | 79 | LUA_ASSERT(L_, Universe::Get(L_) == nullptr); |
| 75 | Universe* const _U{ lua_newuserdatauv<Universe>(L_, 0) }; // universe | 80 | STACK_CHECK_START_REL(L_, 0); |
| 76 | _U->Universe::Universe(); | 81 | Universe* const _U{ new (L_) Universe{} }; // L_: universe |
| 77 | STACK_CHECK_START_REL(L_, 1); | 82 | STACK_CHECK(L_, 1); |
| 78 | kUniverseFullRegKey.setValue(L_, [](lua_State* L_) { lua_pushvalue(L_, -2); }); | 83 | kUniverseFullRegKey.setValue(L_, [](lua_State* L_) { lua_pushvalue(L_, -2); }); |
| 79 | kUniverseLightRegKey.setValue(L_, [U = _U](lua_State* L_) { lua_pushlightuserdata(L_, U); }); | 84 | kUniverseLightRegKey.setValue(L_, [U = _U](lua_State* L_) { lua_pushlightuserdata(L_, U); }); |
| 80 | STACK_CHECK(L_, 1); | 85 | STACK_CHECK(L_, 1); |
| @@ -86,7 +91,7 @@ Universe::Universe() | |||
| 86 | // ################################################################################################# | 91 | // ################################################################################################# |
| 87 | 92 | ||
| 88 | // same as PUC-Lua l_alloc | 93 | // same as PUC-Lua l_alloc |
| 89 | extern "C" [[nodiscard]] static void* libc_lua_Alloc([[maybe_unused]] void* ud_, [[maybe_unused]] void* ptr_, [[maybe_unused]] size_t osize_, size_t nsize_) | 94 | [[nodiscard]] static void* libc_lua_Alloc([[maybe_unused]] void* ud_, [[maybe_unused]] void* ptr_, [[maybe_unused]] size_t osize_, size_t nsize_) |
| 90 | { | 95 | { |
| 91 | if (nsize_ == 0) { | 96 | if (nsize_ == 0) { |
| 92 | free(ptr_); | 97 | free(ptr_); |
| @@ -98,11 +103,11 @@ extern "C" [[nodiscard]] static void* libc_lua_Alloc([[maybe_unused]] void* ud_, | |||
| 98 | 103 | ||
| 99 | // ################################################################################################# | 104 | // ################################################################################################# |
| 100 | 105 | ||
| 101 | [[nodiscard]] static int luaG_provide_protected_allocator(lua_State* L_) | 106 | [[nodiscard]] static int luaG_provide_protected_allocator(lua_State* const L_) |
| 102 | { | 107 | { |
| 103 | Universe* const _U{ universe_get(L_) }; | 108 | Universe* const _U{ Universe::Get(L_) }; |
| 104 | // push a new full userdata on the stack, giving access to the universe's protected allocator | 109 | // push a new full userdata on the stack, giving access to the universe's protected allocator |
| 105 | [[maybe_unused]] AllocatorDefinition* const def{ new (L_) AllocatorDefinition{ _U->protectedAllocator.makeDefinition() } }; | 110 | [[maybe_unused]] AllocatorDefinition* const _def{ new (L_) AllocatorDefinition{ _U->protectedAllocator.makeDefinition() } }; |
| 106 | return 1; | 111 | return 1; |
| 107 | } | 112 | } |
| 108 | 113 | ||
| @@ -149,7 +154,7 @@ void Universe::closeKeepers() | |||
| 149 | 154 | ||
| 150 | // called once at the creation of the universe (therefore L_ is the master Lua state everything originates from) | 155 | // called once at the creation of the universe (therefore L_ is the master Lua state everything originates from) |
| 151 | // Do I need to disable this when compiling for LuaJIT to prevent issues? | 156 | // Do I need to disable this when compiling for LuaJIT to prevent issues? |
| 152 | void Universe::initializeAllocatorFunction(lua_State* L_) | 157 | void Universe::initializeAllocatorFunction(lua_State* const L_) |
| 153 | { | 158 | { |
| 154 | STACK_CHECK_START_REL(L_, 1); // L_: settings | 159 | STACK_CHECK_START_REL(L_, 1); // L_: settings |
| 155 | if (luaG_getfield(L_, -1, "allocator") != LuaType::NIL) { // L_: settings allocator|nil|"protected" | 160 | if (luaG_getfield(L_, -1, "allocator") != LuaType::NIL) { // L_: settings allocator|nil|"protected" |
| @@ -198,7 +203,7 @@ void Universe::initializeAllocatorFunction(lua_State* L_) | |||
| 198 | // ################################################################################################# | 203 | // ################################################################################################# |
| 199 | 204 | ||
| 200 | // should be called ONLY from the state that created the universe | 205 | // should be called ONLY from the state that created the universe |
| 201 | int Universe::InitializeFinalizer(lua_State* L_) | 206 | int Universe::InitializeFinalizer(lua_State* const L_) |
| 202 | { | 207 | { |
| 203 | luaL_argcheck(L_, lua_gettop(L_) <= 1, 1, "too many arguments"); // L_: f? | 208 | luaL_argcheck(L_, lua_gettop(L_) <= 1, 1, "too many arguments"); // L_: f? |
| 204 | lua_settop(L_, 1); // L_: f|nil | 209 | lua_settop(L_, 1); // L_: f|nil |
| @@ -230,7 +235,7 @@ int Universe::InitializeFinalizer(lua_State* L_) | |||
| 230 | * function never fails. | 235 | * function never fails. |
| 231 | * settings table is expected at position 1 on the stack | 236 | * settings table is expected at position 1 on the stack |
| 232 | */ | 237 | */ |
| 233 | void Universe::initializeKeepers(lua_State* L_) | 238 | void Universe::initializeKeepers(lua_State* const L_) |
| 234 | { | 239 | { |
| 235 | LUA_ASSERT(L_, lua_gettop(L_) == 1 && lua_istable(L_, 1)); | 240 | LUA_ASSERT(L_, lua_gettop(L_) == 1 && lua_istable(L_, 1)); |
| 236 | STACK_CHECK_START_REL(L_, 0); // L_: settings | 241 | STACK_CHECK_START_REL(L_, 0); // L_: settings |
| @@ -258,8 +263,9 @@ void Universe::initializeKeepers(lua_State* L_) | |||
| 258 | keepers->gc_threshold = keepers_gc_threshold; | 263 | keepers->gc_threshold = keepers_gc_threshold; |
| 259 | keepers->nb_keepers = _nb_keepers; | 264 | keepers->nb_keepers = _nb_keepers; |
| 260 | 265 | ||
| 261 | for (int const _i : std::ranges::iota_view{ 0, _nb_keepers }) { | 266 | // we have to manually call the Keeper constructor on the additional array slots |
| 262 | keepers->keeper_array[_i].Keeper::Keeper(); | 267 | for (int const _i : std::ranges::iota_view{ 1, _nb_keepers }) { |
| 268 | new (&keepers->keeper_array[_i]) Keeper{}; // placement new | ||
| 263 | } | 269 | } |
| 264 | } | 270 | } |
| 265 | 271 | ||
| @@ -279,7 +285,7 @@ void Universe::initializeKeepers(lua_State* L_) | |||
| 279 | STACK_CHECK_START_ABS(_K, 0); | 285 | STACK_CHECK_START_ABS(_K, 0); |
| 280 | 286 | ||
| 281 | // copy the universe pointer in the keeper itself | 287 | // copy the universe pointer in the keeper itself |
| 282 | universe_store(_K, this); | 288 | Universe::Store(_K, this); |
| 283 | STACK_CHECK(_K, 0); | 289 | STACK_CHECK(_K, 0); |
| 284 | 290 | ||
| 285 | // make sure 'package' is initialized in keeper states, so that we have require() | 291 | // make sure 'package' is initialized in keeper states, so that we have require() |
| @@ -325,7 +331,7 @@ void Universe::initializeKeepers(lua_State* L_) | |||
| 325 | 331 | ||
| 326 | // ################################################################################################# | 332 | // ################################################################################################# |
| 327 | 333 | ||
| 328 | void Universe::terminateFreeRunningLanes(lua_State* L_, lua_Duration shutdownTimeout_, CancelOp op_) | 334 | void Universe::terminateFreeRunningLanes(lua_State* const L_, lua_Duration const shutdownTimeout_, CancelOp const op_) |
| 329 | { | 335 | { |
| 330 | if (selfdestructFirst != SELFDESTRUCT_END) { | 336 | if (selfdestructFirst != SELFDESTRUCT_END) { |
| 331 | // Signal _all_ still running threads to exit (including the timer thread) | 337 | // Signal _all_ still running threads to exit (including the timer thread) |
| @@ -391,7 +397,7 @@ void Universe::terminateFreeRunningLanes(lua_State* L_, lua_Duration shutdownTim | |||
| 391 | // ################################################################################################# | 397 | // ################################################################################################# |
| 392 | 398 | ||
| 393 | // process end: cancel any still free-running threads | 399 | // process end: cancel any still free-running threads |
| 394 | int universe_gc(lua_State* L_) | 400 | LUAG_FUNC(universe_gc) |
| 395 | { | 401 | { |
| 396 | lua_Duration const _shutdown_timeout{ lua_tonumber(L_, lua_upvalueindex(1)) }; | 402 | lua_Duration const _shutdown_timeout{ lua_tonumber(L_, lua_upvalueindex(1)) }; |
| 397 | std::string_view const _op_string{ lua_tostringview(L_, lua_upvalueindex(2)) }; | 403 | std::string_view const _op_string{ lua_tostringview(L_, lua_upvalueindex(2)) }; |
diff --git a/src/universe.h b/src/universe.h index 4be6a9a..7624fed 100644 --- a/src/universe.h +++ b/src/universe.h | |||
| @@ -108,8 +108,6 @@ class ProtectedAllocator | |||
| 108 | 108 | ||
| 109 | // ################################################################################################# | 109 | // ################################################################################################# |
| 110 | 110 | ||
| 111 | // xxh64 of string "kUniverseFullRegKey" generated at https://www.pelock.com/products/hash-calculator | ||
| 112 | static constexpr RegistryUniqueKey kUniverseFullRegKey{ 0x1C2D76870DD9DD9Full }; | ||
| 113 | // xxh64 of string "kUniverseLightRegKey" generated at https://www.pelock.com/products/hash-calculator | 111 | // xxh64 of string "kUniverseLightRegKey" generated at https://www.pelock.com/products/hash-calculator |
| 114 | static constexpr RegistryUniqueKey kUniverseLightRegKey{ 0x48BBE9CEAB0BA04Full }; | 112 | static constexpr RegistryUniqueKey kUniverseLightRegKey{ 0x48BBE9CEAB0BA04Full }; |
| 115 | 113 | ||
| @@ -172,6 +170,11 @@ class Universe | |||
| 172 | // The terminal desinit sequence should wait for all such processing to terminate before force-killing threads | 170 | // The terminal desinit sequence should wait for all such processing to terminate before force-killing threads |
| 173 | std::atomic<int> selfdestructingCount{ 0 }; | 171 | std::atomic<int> selfdestructingCount{ 0 }; |
| 174 | 172 | ||
| 173 | public: | ||
| 174 | [[nodiscard]] static void* operator new([[maybe_unused]] size_t size_, lua_State* L_) noexcept { return lua_newuserdatauv<Universe>(L_, 0); }; | ||
| 175 | // can't actually delete the operator because the compiler generates stack unwinding code that could call it in case of exception | ||
| 176 | static void operator delete([[maybe_unused]] void* p_, [[maybe_unused]] lua_State* L_) {} // nothing to do, as nothing is allocated independently | ||
| 177 | |||
| 175 | Universe(); | 178 | Universe(); |
| 176 | ~Universe() = default; | 179 | ~Universe() = default; |
| 177 | // non-copyable, non-movable | 180 | // non-copyable, non-movable |
| @@ -181,21 +184,18 @@ class Universe | |||
| 181 | Universe& operator=(Universe&&) = delete; | 184 | Universe& operator=(Universe&&) = delete; |
| 182 | 185 | ||
| 183 | void closeKeepers(); | 186 | void closeKeepers(); |
| 187 | [[nodiscard]] static Universe* Create(lua_State* L_); | ||
| 188 | [[nodiscard]] static inline Universe* Get(lua_State* L_); | ||
| 184 | void initializeAllocatorFunction(lua_State* L_); | 189 | void initializeAllocatorFunction(lua_State* L_); |
| 185 | static int InitializeFinalizer(lua_State* L_); | 190 | static int InitializeFinalizer(lua_State* L_); |
| 186 | void initializeKeepers(lua_State* L_); | 191 | void initializeKeepers(lua_State* L_); |
| 192 | static inline void Store(lua_State* L_, Universe* U_); | ||
| 187 | void terminateFreeRunningLanes(lua_State* L_, lua_Duration shutdownTimeout_, CancelOp op_); | 193 | void terminateFreeRunningLanes(lua_State* L_, lua_Duration shutdownTimeout_, CancelOp op_); |
| 188 | }; | 194 | }; |
| 189 | 195 | ||
| 190 | // ################################################################################################# | 196 | // ################################################################################################# |
| 191 | 197 | ||
| 192 | [[nodiscard]] Universe* universe_get(lua_State* L_); | 198 | inline Universe* Universe::Get(lua_State* L_) |
| 193 | [[nodiscard]] Universe* universe_create(lua_State* L_); | ||
| 194 | void universe_store(lua_State* L_, Universe* U_); | ||
| 195 | |||
| 196 | // ################################################################################################# | ||
| 197 | |||
| 198 | [[nodiscard]] inline Universe* universe_get(lua_State* L_) | ||
| 199 | { | 199 | { |
| 200 | STACK_CHECK_START_REL(L_, 0); | 200 | STACK_CHECK_START_REL(L_, 0); |
| 201 | Universe* const _universe{ kUniverseLightRegKey.readLightUserDataValue<Universe>(L_) }; | 201 | Universe* const _universe{ kUniverseLightRegKey.readLightUserDataValue<Universe>(L_) }; |
| @@ -205,9 +205,10 @@ void universe_store(lua_State* L_, Universe* U_); | |||
| 205 | 205 | ||
| 206 | // ################################################################################################# | 206 | // ################################################################################################# |
| 207 | 207 | ||
| 208 | inline void universe_store(lua_State* L_, Universe* U_) | 208 | inline void Universe::Store(lua_State* L_, Universe* U_) |
| 209 | { | 209 | { |
| 210 | LUA_ASSERT(L_, !U_ || universe_get(L_) == nullptr); | 210 | // TODO: check if we actually ever call Store with a null universe |
| 211 | LUA_ASSERT(L_, !U_ || Universe::Get(L_) == nullptr); | ||
| 211 | STACK_CHECK_START_REL(L_, 0); | 212 | STACK_CHECK_START_REL(L_, 0); |
| 212 | kUniverseLightRegKey.setValue(L_, [U = U_](lua_State* L_) { U ? lua_pushlightuserdata(L_, U) : lua_pushnil(L_); }); | 213 | kUniverseLightRegKey.setValue(L_, [U = U_](lua_State* L_) { U ? lua_pushlightuserdata(L_, U) : lua_pushnil(L_); }); |
| 213 | STACK_CHECK(L_, 0); | 214 | STACK_CHECK(L_, 0); |
| @@ -215,4 +216,4 @@ inline void universe_store(lua_State* L_, Universe* U_) | |||
| 215 | 216 | ||
| 216 | // ################################################################################################# | 217 | // ################################################################################################# |
| 217 | 218 | ||
| 218 | int universe_gc(lua_State* L_); | 219 | LUAG_FUNC(universe_gc); |
diff --git a/tests/keeper.lua b/tests/keeper.lua index e485018..e758b54 100644 --- a/tests/keeper.lua +++ b/tests/keeper.lua | |||
| @@ -3,7 +3,7 @@ | |||
| 3 | -- | 3 | -- |
| 4 | -- Test program for Lua Lanes | 4 | -- Test program for Lua Lanes |
| 5 | -- | 5 | -- |
| 6 | 6 | -- TODO: there is a random crash when nb_keepers > 1. Will have to investigate | |
| 7 | local lanes = require "lanes".configure{ with_timers = false, nb_keepers = 1, keepers_gc_threshold = 500} | 7 | local lanes = require "lanes".configure{ with_timers = false, nb_keepers = 1, keepers_gc_threshold = 500} |
| 8 | 8 | ||
| 9 | do | 9 | do |
