aboutsummaryrefslogtreecommitdiff
path: root/src/universe.cpp
diff options
context:
space:
mode:
authorBenoit Germain <benoit.germain@ubisoft.com>2024-10-08 18:42:39 +0200
committerBenoit Germain <benoit.germain@ubisoft.com>2024-10-08 18:42:39 +0200
commit16b5070c0cd56e10c5074eb9903dbc3ae4e15a61 (patch)
treef6d5cdb74b505e13aa3261f7ab6192da0133b7b9 /src/universe.cpp
parente939e5e6a894a042d3301e47faa05264445f27f6 (diff)
downloadlanes-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.cpp47
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_)
300void Universe::initializeOnStateCreate(lua_State* const L_) 299void 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) {