diff options
author | Benoit Germain <benoit.germain@ubisoft.com> | 2024-10-08 18:42:39 +0200 |
---|---|---|
committer | Benoit Germain <benoit.germain@ubisoft.com> | 2024-10-08 18:42:39 +0200 |
commit | 16b5070c0cd56e10c5074eb9903dbc3ae4e15a61 (patch) | |
tree | f6d5cdb74b505e13aa3261f7ab6192da0133b7b9 /src/universe.cpp | |
parent | e939e5e6a894a042d3301e47faa05264445f27f6 (diff) | |
download | lanes-16b5070c0cd56e10c5074eb9903dbc3ae4e15a61.tar.gz lanes-16b5070c0cd56e10c5074eb9903dbc3ae4e15a61.tar.bz2 lanes-16b5070c0cd56e10c5074eb9903dbc3ae4e15a61.zip |
Sprinkling StackIndex all over the place
Diffstat (limited to 'src/universe.cpp')
-rw-r--r-- | src/universe.cpp | 47 |
1 files changed, 23 insertions, 24 deletions
diff --git a/src/universe.cpp b/src/universe.cpp index 3800dbb..c435dad 100644 --- a/src/universe.cpp +++ b/src/universe.cpp | |||
@@ -100,7 +100,7 @@ void Universe::callOnStateCreate(lua_State* const L_, lua_State* const from_, Lo | |||
100 | } | 100 | } |
101 | kConfigRegKey.pushValue(L_); // L_: config | 101 | kConfigRegKey.pushValue(L_); // L_: config |
102 | STACK_CHECK(L_, 1); | 102 | STACK_CHECK(L_, 1); |
103 | LuaType const _funcType{ luaG_getfield(L_, -1, kOnStateCreate) }; // L_: config on_state_create() | 103 | LuaType const _funcType{ luaG_getfield(L_, kIdxTop, kOnStateCreate) }; // L_: config on_state_create() |
104 | if (_funcType != LuaType::FUNCTION) { | 104 | if (_funcType != LuaType::FUNCTION) { |
105 | raise_luaL_error(L_, "INTERNAL ERROR: %s is a %s, not a function", kOnStateCreate.data(), luaG_typename(L_, _funcType).data()); | 105 | raise_luaL_error(L_, "INTERNAL ERROR: %s is a %s, not a function", kOnStateCreate.data(), luaG_typename(L_, _funcType).data()); |
106 | } | 106 | } |
@@ -111,29 +111,28 @@ void Universe::callOnStateCreate(lua_State* const L_, lua_State* const from_, Lo | |||
111 | std::string_view const _stateType{ mode_ == LookupMode::LaneBody ? "lane" : "keeper" }; | 111 | std::string_view const _stateType{ mode_ == LookupMode::LaneBody ? "lane" : "keeper" }; |
112 | luaG_pushstring(L_, _stateType); // L_: on_state_create() "<type>" | 112 | luaG_pushstring(L_, _stateType); // L_: on_state_create() "<type>" |
113 | if (lua_pcall(L_, 1, 0, 0) != LUA_OK) { | 113 | if (lua_pcall(L_, 1, 0, 0) != LUA_OK) { |
114 | raise_luaL_error(from_, "%s failed in %s: \"%s\"", kOnStateCreate.data(), _stateType.data(), lua_isstring(L_, -1) ? luaG_tostring(L_, -1).data() : luaG_typename(L_, -1).data()); | 114 | raise_luaL_error(from_, "%s failed in %s: \"%s\"", kOnStateCreate.data(), _stateType.data(), lua_isstring(L_, -1) ? luaG_tostring(L_, kIdxTop).data() : luaG_typename(L_, kIdxTop).data()); |
115 | } | 115 | } |
116 | STACK_CHECK(L_, 0); | 116 | STACK_CHECK(L_, 0); |
117 | } | 117 | } |
118 | 118 | ||
119 | |||
120 | |||
121 | // ################################################################################################# | 119 | // ################################################################################################# |
122 | 120 | ||
123 | // only called from the master state | 121 | // only called from the master state |
124 | [[nodiscard]] Universe* Universe::Create(lua_State* const L_) | 122 | [[nodiscard]] Universe* Universe::Create(lua_State* const L_) |
125 | { | 123 | { |
126 | LUA_ASSERT(L_, Universe::Get(L_) == nullptr); | 124 | LUA_ASSERT(L_, Universe::Get(L_) == nullptr); |
125 | static constexpr StackIndex kIdxSettings{ 1 }; | ||
127 | LUA_ASSERT(L_, lua_gettop(L_) == 1 && lua_istable(L_, 1)); | 126 | LUA_ASSERT(L_, lua_gettop(L_) == 1 && lua_istable(L_, 1)); |
128 | STACK_CHECK_START_REL(L_, 0); // L_: settings | 127 | STACK_CHECK_START_REL(L_, 0); // L_: settings |
129 | std::ignore = luaG_getfield(L_, 1, "nb_user_keepers"); // L_: settings nb_user_keepers | 128 | std::ignore = luaG_getfield(L_, kIdxSettings, "nb_user_keepers"); // L_: settings nb_user_keepers |
130 | int const _nbUserKeepers{ static_cast<int>(lua_tointeger(L_, -1)) + 1}; | 129 | int const _nbUserKeepers{ static_cast<int>(lua_tointeger(L_, -1)) + 1}; |
131 | lua_pop(L_, 1); // L_: settings | 130 | lua_pop(L_, 1); // L_: settings |
132 | if (_nbUserKeepers < 1) { | 131 | if (_nbUserKeepers < 1) { |
133 | raise_luaL_error(L_, "Bad number of additional keepers (%d)", _nbUserKeepers); | 132 | raise_luaL_error(L_, "Bad number of additional keepers (%d)", _nbUserKeepers); |
134 | } | 133 | } |
135 | STACK_CHECK(L_, 0); | 134 | STACK_CHECK(L_, 0); |
136 | std::ignore = luaG_getfield(L_, 1, "keepers_gc_threshold"); // L_: settings keepers_gc_threshold | 135 | std::ignore = luaG_getfield(L_, kIdxSettings, "keepers_gc_threshold"); // L_: settings keepers_gc_threshold |
137 | int const _keepers_gc_threshold{ static_cast<int>(lua_tointeger(L_, -1)) }; | 136 | int const _keepers_gc_threshold{ static_cast<int>(lua_tointeger(L_, -1)) }; |
138 | lua_pop(L_, 1); // L_: settings | 137 | lua_pop(L_, 1); // L_: settings |
139 | STACK_CHECK(L_, 0); | 138 | STACK_CHECK(L_, 0); |
@@ -146,22 +145,22 @@ void Universe::callOnStateCreate(lua_State* const L_, lua_State* const from_, Lo | |||
146 | 145 | ||
147 | DEBUGSPEW_CODE(DebugSpewIndentScope _scope{ _U }); | 146 | DEBUGSPEW_CODE(DebugSpewIndentScope _scope{ _U }); |
148 | lua_createtable(L_, 0, 1); // L_: settings universe {mt} | 147 | lua_createtable(L_, 0, 1); // L_: settings universe {mt} |
149 | std::ignore = luaG_getfield(L_, 1, "shutdown_timeout"); // L_: settings universe {mt} shutdown_timeout | 148 | std::ignore = luaG_getfield(L_, kIdxSettings, "shutdown_timeout"); // L_: settings universe {mt} shutdown_timeout |
150 | lua_pushcclosure(L_, LG_universe_gc, 1); // L_: settings universe {mt} LG_universe_gc | 149 | lua_pushcclosure(L_, LG_universe_gc, 1); // L_: settings universe {mt} LG_universe_gc |
151 | lua_setfield(L_, -2, "__gc"); // L_: settings universe {mt} | 150 | lua_setfield(L_, -2, "__gc"); // L_: settings universe {mt} |
152 | lua_setmetatable(L_, -2); // L_: settings universe | 151 | lua_setmetatable(L_, -2); // L_: settings universe |
153 | lua_pop(L_, 1); // L_: settings | 152 | lua_pop(L_, 1); // L_: settings |
154 | 153 | ||
155 | std::ignore = luaG_getfield(L_, 1, "strip_functions"); // L_: settings strip_functions | 154 | std::ignore = luaG_getfield(L_, kIdxSettings, "strip_functions"); // L_: settings strip_functions |
156 | _U->stripFunctions = lua_toboolean(L_, -1) ? true : false; | 155 | _U->stripFunctions = lua_toboolean(L_, -1) ? true : false; |
157 | lua_pop(L_, 1); // L_: settings | 156 | lua_pop(L_, 1); // L_: settings |
158 | 157 | ||
159 | std::ignore = luaG_getfield(L_, 1, "verbose_errors"); // L_: settings verbose_errors | 158 | std::ignore = luaG_getfield(L_, kIdxSettings, "verbose_errors"); // L_: settings verbose_errors |
160 | _U->verboseErrors = lua_toboolean(L_, -1) ? true : false; | 159 | _U->verboseErrors = lua_toboolean(L_, -1) ? true : false; |
161 | lua_pop(L_, 1); // L_: settings | 160 | lua_pop(L_, 1); // L_: settings |
162 | 161 | ||
163 | // tracking | 162 | // tracking |
164 | std::ignore = luaG_getfield(L_, 1, "track_lanes"); // L_: settings track_lanes | 163 | std::ignore = luaG_getfield(L_, kIdxSettings, "track_lanes"); // L_: settings track_lanes |
165 | if (lua_toboolean(L_, -1)) { | 164 | if (lua_toboolean(L_, -1)) { |
166 | _U->tracker.activate(); | 165 | _U->tracker.activate(); |
167 | } | 166 | } |
@@ -182,7 +181,7 @@ void Universe::callOnStateCreate(lua_State* const L_, lua_State* const from_, Lo | |||
182 | STACK_CHECK(L_, 1); | 181 | STACK_CHECK(L_, 1); |
183 | 182 | ||
184 | // Proxy userdata contents is only a 'DeepPrelude*' pointer | 183 | // Proxy userdata contents is only a 'DeepPrelude*' pointer |
185 | _U->timerLinda = *luaG_tofulluserdata<DeepPrelude*>(L_, -1); | 184 | _U->timerLinda = *luaG_tofulluserdata<DeepPrelude*>(L_, kIdxTop); |
186 | // increment refcount so that this linda remains alive as long as the universe exists. | 185 | // increment refcount so that this linda remains alive as long as the universe exists. |
187 | _U->timerLinda->refcount.fetch_add(1, std::memory_order_relaxed); | 186 | _U->timerLinda->refcount.fetch_add(1, std::memory_order_relaxed); |
188 | lua_pop(L_, 1); // L_: settings | 187 | lua_pop(L_, 1); // L_: settings |
@@ -224,13 +223,13 @@ void Universe::initializeAllocatorFunction(lua_State* const L_) | |||
224 | // start by just grabbing whatever allocator was provided to the master state | 223 | // start by just grabbing whatever allocator was provided to the master state |
225 | protectedAllocator.initFrom(L_); | 224 | protectedAllocator.initFrom(L_); |
226 | STACK_CHECK_START_REL(L_, 1); // L_: settings | 225 | STACK_CHECK_START_REL(L_, 1); // L_: settings |
227 | switch (luaG_getfield(L_, -1, "allocator")) { // L_: settings allocator|nil|"protected" | 226 | switch (luaG_getfield(L_, kIdxTop, "allocator")) { // L_: settings allocator|nil|"protected" |
228 | case LuaType::NIL: | 227 | case LuaType::NIL: |
229 | // nothing else to do | 228 | // nothing else to do |
230 | break; | 229 | break; |
231 | 230 | ||
232 | case LuaType::STRING: | 231 | case LuaType::STRING: |
233 | LUA_ASSERT(L_, luaG_tostring(L_, -1) == "protected"); | 232 | LUA_ASSERT(L_, luaG_tostring(L_, kIdxTop) == "protected"); |
234 | // set the original allocator to call from inside protection by the mutex | 233 | // set the original allocator to call from inside protection by the mutex |
235 | protectedAllocator.installIn(L_); | 234 | protectedAllocator.installIn(L_); |
236 | // before a state is created, this function will be called to obtain the allocator | 235 | // before a state is created, this function will be called to obtain the allocator |
@@ -255,14 +254,14 @@ void Universe::initializeAllocatorFunction(lua_State* const L_) | |||
255 | break; | 254 | break; |
256 | 255 | ||
257 | default: // should be filtered out in lanes.lua | 256 | default: // should be filtered out in lanes.lua |
258 | raise_luaL_error(L_, "Bad config.allocator type %s", luaG_typename(L_, -1).data()); | 257 | raise_luaL_error(L_, "Bad config.allocator type %s", luaG_typename(L_, kIdxTop).data()); |
259 | } | 258 | } |
260 | lua_pop(L_, 1); // L_: settings | 259 | lua_pop(L_, 1); // L_: settings |
261 | STACK_CHECK(L_, 1); | 260 | STACK_CHECK(L_, 1); |
262 | 261 | ||
263 | std::ignore = luaG_getfield(L_, -1, "internal_allocator"); // L_: settings "libc"|"allocator" | 262 | std::ignore = luaG_getfield(L_, kIdxTop, "internal_allocator"); // L_: settings "libc"|"allocator" |
264 | LUA_ASSERT(L_, lua_isstring(L_, -1)); // should be the case due to lanes.lua parameter validation | 263 | LUA_ASSERT(L_, lua_isstring(L_, kIdxTop)); // should be the case due to lanes.lua parameter validation |
265 | std::string_view const _allocator{ luaG_tostring(L_, -1) }; | 264 | std::string_view const _allocator{ luaG_tostring(L_, kIdxTop) }; |
266 | if (_allocator == "libc") { | 265 | if (_allocator == "libc") { |
267 | internalAllocator = lanes::AllocatorDefinition{ lanes::AllocatorDefinition::kAllocatorVersion, libc_lua_Alloc, nullptr }; | 266 | internalAllocator = lanes::AllocatorDefinition{ lanes::AllocatorDefinition::kAllocatorVersion, libc_lua_Alloc, nullptr }; |
268 | } else { | 267 | } else { |
@@ -284,7 +283,7 @@ int Universe::InitializeFinalizer(lua_State* const L_) | |||
284 | 283 | ||
285 | // make sure we are only called from the Master Lua State! | 284 | // make sure we are only called from the Master Lua State! |
286 | kUniverseFullRegKey.pushValue(L_); // L_: f U | 285 | kUniverseFullRegKey.pushValue(L_); // L_: f U |
287 | if (luaG_type(L_, -1) != LuaType::USERDATA) { | 286 | if (luaG_type(L_, kIdxTop) != LuaType::USERDATA) { |
288 | raise_luaL_error(L_, "lanes.%s called from inside a lane", kFinally); | 287 | raise_luaL_error(L_, "lanes.%s called from inside a lane", kFinally); |
289 | } | 288 | } |
290 | lua_pop(L_, 1); // L_: f | 289 | lua_pop(L_, 1); // L_: f |
@@ -300,8 +299,8 @@ int Universe::InitializeFinalizer(lua_State* const L_) | |||
300 | void Universe::initializeOnStateCreate(lua_State* const L_) | 299 | void Universe::initializeOnStateCreate(lua_State* const L_) |
301 | { | 300 | { |
302 | STACK_CHECK_START_REL(L_, 0); // L_: settings | 301 | STACK_CHECK_START_REL(L_, 0); // L_: settings |
303 | if (luaG_getfield(L_, -1, kOnStateCreate) != LuaType::NIL) { // L_: settings on_state_create|nil | 302 | if (luaG_getfield(L_, kIdxTop, kOnStateCreate) != LuaType::NIL) { // L_: settings on_state_create|nil |
304 | LUA_ASSERT(L_, luaG_type(L_, -1) == LuaType::FUNCTION); // ensured by lanes.lua parameter validation | 303 | LUA_ASSERT(L_, luaG_type(L_, kIdxTop) == LuaType::FUNCTION); // ensured by lanes.lua parameter validation |
305 | // store C function pointer in an internal variable | 304 | // store C function pointer in an internal variable |
306 | lua_CFunction const _func{ lua_tocfunction(L_, -1) }; // L_: settings on_state_create | 305 | lua_CFunction const _func{ lua_tocfunction(L_, -1) }; // L_: settings on_state_create |
307 | if (_func) { | 306 | if (_func) { |
@@ -314,7 +313,7 @@ void Universe::initializeOnStateCreate(lua_State* const L_) | |||
314 | // remove this C function from the config table so that it doesn't cause problems | 313 | // remove this C function from the config table so that it doesn't cause problems |
315 | // when we transfer the config table in newly created Lua states | 314 | // when we transfer the config table in newly created Lua states |
316 | lua_pushnil(L_); // L_: settings on_state_create nil | 315 | lua_pushnil(L_); // L_: settings on_state_create nil |
317 | luaG_setfield(L_, -3, kOnStateCreate); // L_: settings on_state_create | 316 | luaG_setfield(L_, StackIndex{ -3 }, kOnStateCreate); // L_: settings on_state_create |
318 | } else { | 317 | } else { |
319 | // the function is still in the config table. we indicate this with the uintptr_t alternative (actual value is irrelevant) | 318 | // the function is still in the config table. we indicate this with the uintptr_t alternative (actual value is irrelevant) |
320 | onStateCreateFunc.emplace<uintptr_t>(std::bit_cast<uintptr_t>(kOnStateCreate.data())); | 319 | onStateCreateFunc.emplace<uintptr_t>(std::bit_cast<uintptr_t>(kOnStateCreate.data())); |
@@ -339,7 +338,7 @@ lanes::AllocatorDefinition Universe::resolveAllocator(lua_State* const L_, std:: | |||
339 | lua_pushcclosure(L_, provideAllocator, 0); // L_: provideAllocator() | 338 | lua_pushcclosure(L_, provideAllocator, 0); // L_: provideAllocator() |
340 | luaG_pushstring(L_, hint_); // L_: provideAllocator() "<hint>" | 339 | luaG_pushstring(L_, hint_); // L_: provideAllocator() "<hint>" |
341 | lua_call(L_, 1, 1); // L_: result | 340 | lua_call(L_, 1, 1); // L_: result |
342 | lanes::AllocatorDefinition* const _def{ luaG_tofulluserdata<lanes::AllocatorDefinition>(L_, -1) }; | 341 | lanes::AllocatorDefinition* const _def{ luaG_tofulluserdata<lanes::AllocatorDefinition>(L_, kIdxTop) }; |
343 | if (!_def || _def->version != lanes::AllocatorDefinition::kAllocatorVersion) { | 342 | if (!_def || _def->version != lanes::AllocatorDefinition::kAllocatorVersion) { |
344 | raise_luaL_error(L_, "Bad config.allocator function, must provide a valid AllocatorDefinition"); | 343 | raise_luaL_error(L_, "Bad config.allocator function, must provide a valid AllocatorDefinition"); |
345 | } | 344 | } |
@@ -414,7 +413,7 @@ LUAG_FUNC(universe_gc) | |||
414 | { | 413 | { |
415 | lua_Duration const _shutdown_timeout{ lua_tonumber(L_, lua_upvalueindex(1)) }; | 414 | lua_Duration const _shutdown_timeout{ lua_tonumber(L_, lua_upvalueindex(1)) }; |
416 | STACK_CHECK_START_ABS(L_, 1); | 415 | STACK_CHECK_START_ABS(L_, 1); |
417 | Universe* const _U{ luaG_tofulluserdata<Universe>(L_, 1) }; // L_: U | 416 | Universe* const _U{ luaG_tofulluserdata<Universe>(L_, StackIndex{ 1 }) }; // L_: U |
418 | 417 | ||
419 | // attempt to terminate all lanes with increasingly stronger cancel methods | 418 | // attempt to terminate all lanes with increasingly stronger cancel methods |
420 | bool const _allLanesTerminated{ | 419 | bool const _allLanesTerminated{ |
@@ -433,7 +432,7 @@ LUAG_FUNC(universe_gc) | |||
433 | STACK_CHECK(L_, 2); | 432 | STACK_CHECK(L_, 2); |
434 | 433 | ||
435 | // if some lanes are still running here, we have no other choice than crashing or freezing and let the client figure out what's wrong | 434 | // if some lanes are still running here, we have no other choice than crashing or freezing and let the client figure out what's wrong |
436 | bool const _throw{ luaG_tostring(L_, -1) == "throw" }; | 435 | bool const _throw{ luaG_tostring(L_, kIdxTop) == "throw" }; |
437 | lua_pop(L_, 1); // L_: U | 436 | lua_pop(L_, 1); // L_: U |
438 | 437 | ||
439 | while (_U->selfdestructFirst != SELFDESTRUCT_END) { | 438 | while (_U->selfdestructFirst != SELFDESTRUCT_END) { |