aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorBenoit Germain <benoit.germain@ubisoft.com>2024-05-29 17:31:45 +0200
committerBenoit Germain <benoit.germain@ubisoft.com>2024-05-29 17:31:45 +0200
commita156aaeb07fada043b308409dcffcae1726eec0b (patch)
treef15a5d60cda30607260d896598ea33f8619af53a /src
parentd47758d58d532a9716ad4fd85cc806704df13735 (diff)
downloadlanes-a156aaeb07fada043b308409dcffcae1726eec0b.tar.gz
lanes-a156aaeb07fada043b308409dcffcae1726eec0b.tar.bz2
lanes-a156aaeb07fada043b308409dcffcae1726eec0b.zip
Fix clang-tidy issues (most notably Microsoft-specific explicit constructor calls)
Diffstat (limited to 'src')
-rw-r--r--src/deep.h18
-rw-r--r--src/intercopycontext.cpp5
-rw-r--r--src/lane.cpp2
-rw-r--r--src/lanes.cpp18
-rw-r--r--src/lanes.lua4
-rw-r--r--src/linda.cpp2
-rw-r--r--src/lindafactory.cpp2
-rw-r--r--src/macros_and_utils.h2
-rw-r--r--src/state.cpp4
-rw-r--r--src/tools.cpp10
-rw-r--r--src/universe.cpp40
-rw-r--r--src/universe.h25
12 files changed, 70 insertions, 62 deletions
diff --git a/src/deep.h b/src/deep.h
index 17d3491..1710aba 100644
--- a/src/deep.h
+++ b/src/deep.h
@@ -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
511LUAG_FUNC(threads) 511LUAG_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
115local param_checkers = 115local 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
44static constexpr RegistryUniqueKey kUniverseFullRegKey{ 0x1C2D76870DD9DD9Full };
45
46// #################################################################################################
47
43Universe::Universe() 48Universe::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
89extern "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?
152void Universe::initializeAllocatorFunction(lua_State* L_) 157void 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
201int Universe::InitializeFinalizer(lua_State* L_) 206int 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 */
233void Universe::initializeKeepers(lua_State* L_) 238void 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
328void Universe::terminateFreeRunningLanes(lua_State* L_, lua_Duration shutdownTimeout_, CancelOp op_) 334void 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
394int universe_gc(lua_State* L_) 400LUAG_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
112static 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
114static constexpr RegistryUniqueKey kUniverseLightRegKey{ 0x48BBE9CEAB0BA04Full }; 112static 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_); 198inline Universe* Universe::Get(lua_State* L_)
193[[nodiscard]] Universe* universe_create(lua_State* L_);
194void 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
208inline void universe_store(lua_State* L_, Universe* U_) 208inline 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
218int universe_gc(lua_State* L_); 219LUAG_FUNC(universe_gc);