aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorBenoit Germain <benoit.germain@ubisoft.com>2026-03-02 18:12:39 +0100
committerBenoit Germain <benoit.germain@ubisoft.com>2026-03-02 18:12:39 +0100
commit4a8f8d2cd6a9726767b2a113e6885a4c2ac663a0 (patch)
tree0b50dfc070260d285baeae6f12b78e1e8a4d6811 /src
parenta225b7808dd1d672f3e74ae5ac0af0f9f9322314 (diff)
downloadlanes-4a8f8d2cd6a9726767b2a113e6885a4c2ac663a0.tar.gz
lanes-4a8f8d2cd6a9726767b2a113e6885a4c2ac663a0.tar.bz2
lanes-4a8f8d2cd6a9726767b2a113e6885a4c2ac663a0.zip
lane_new internal code cleanup step 3: RequireModulesInLane
Diffstat (limited to 'src')
-rw-r--r--src/lanes.cpp95
1 files changed, 51 insertions, 44 deletions
diff --git a/src/lanes.cpp b/src/lanes.cpp
index cdf5f5a..edcc556 100644
--- a/src/lanes.cpp
+++ b/src/lanes.cpp
@@ -293,6 +293,55 @@ namespace {
293 [[maybe_unused]] InterCopyResult const _ret{ _c.interCopyPackage() }; 293 [[maybe_unused]] InterCopyResult const _ret{ _c.interCopyPackage() };
294 LUA_ASSERT(L_, _ret == InterCopyResult::Success); // either all went well, or we should not even get here 294 LUA_ASSERT(L_, _ret == InterCopyResult::Success); // either all went well, or we should not even get here
295 } 295 }
296
297 // require() each module listed in requiredIdx_ inside the lane state, then register its
298 // exported functions in the lookup table. No-op when requiredIdx_ is nil/none.
299 static void RequireModulesInLane(Universe* const U_, lua_State* const L_, lua_State* const L2_, StackIndex const requiredIdx_)
300 {
301 if (lua_isnoneornil(L_, requiredIdx_)) {
302 return;
303 }
304 DEBUGSPEW_CODE(DebugSpew(U_) << "lane_new: process 'required' list" << std::endl);
305 DEBUGSPEW_CODE(DebugSpewIndentScope _scope{ U_ });
306 // should not happen, was checked in lanes.lua before calling lane_new()
307 if (luaW_type(L_, requiredIdx_) != LuaType::TABLE) {
308 raise_luaL_error(L_, "expected required module list as a table, got %s", luaL_typename(L_, requiredIdx_));
309 }
310
311 int _nbRequired{ 1 };
312 lua_pushnil(L_); // L_: [fixed] args... nil L2:
313 while (lua_next(L_, requiredIdx_) != 0) { // L_: [fixed] args... n "modname" L2:
314 if (luaW_type(L_, kIdxTop) != LuaType::STRING || luaW_type(L_, StackIndex{ -2 }) != LuaType::NUMBER || lua_tonumber(L_, -2) != _nbRequired) {
315 raise_luaL_error(L_, "required module list should be a list of strings");
316 } else {
317 // require the module in the target state, and populate the lookup table there too
318 std::string_view const _name{ luaW_tostring(L_, kIdxTop) };
319 DEBUGSPEW_CODE(DebugSpew(U_) << "lane_new: require '" << _name << "'" << std::endl);
320
321 // require the module in the target lane
322 lua_getglobal(L2_, "require"); // L_: [fixed] args... n "modname" L2: require()?
323 if (lua_isnil(L2_, -1)) {
324 lua_pop(L2_, 1); // L_: [fixed] args... n "modname" L2:
325 raise_luaL_error(L_, "cannot pre-require modules without loading 'package' library first");
326 } else {
327 luaW_pushstring(L2_, _name); // L_: [fixed] args... n "modname" L2: require() name
328 LuaError const _rc{ lua_pcall(L2_, 1, 1, 0) }; // L_: [fixed] args... n "modname" L2: ret/errcode
329 if (_rc != LuaError::OK) {
330 // propagate error to main state if any
331 InterCopyContext _c{ U_, DestState{ L_ }, SourceState{ L2_ }, {}, {}, {}, {}, {} };
332 std::ignore = _c.interMove(1); // L_: [fixed] args... n "modname" error L2:
333 raise_lua_error(L_);
334 }
335 // here the module was successfully required // L_: [fixed] args... n "modname" L2: ret
336 // after requiring the module, register the functions it exported in our name<->function database
337 tools::PopulateFuncLookupTable(L2_, kIdxTop, _name);
338 lua_pop(L2_, 1); // L_: [fixed] args... n "modname" L2:
339 }
340 }
341 lua_pop(L_, 1); // L_: [fixed] args... n L2:
342 ++_nbRequired;
343 } // L_: [fixed] args...
344 }
296 } // namespace local 345 } // namespace local
297} // namespace 346} // namespace
298 347
@@ -336,7 +385,7 @@ LUAG_FUNC(lane_new)
336 DEBUGSPEW_CODE(DebugSpew(_U) << "lane_new: setup" << std::endl); 385 DEBUGSPEW_CODE(DebugSpew(_U) << "lane_new: setup" << std::endl);
337 386
338 std::optional<std::string_view> _libs_str{ lua_isnil(L_, kLibsIdx) ? std::nullopt : std::make_optional(luaW_tostring(L_, kLibsIdx)) }; 387 std::optional<std::string_view> _libs_str{ lua_isnil(L_, kLibsIdx) ? std::nullopt : std::make_optional(luaW_tostring(L_, kLibsIdx)) };
339 lua_State* const _S{ state::NewLaneState(_U, SourceState{ L_ }, _libs_str) }; // L_: [fixed] ... L2: 388 lua_State* const _S{ state::NewLaneState(_U, SourceState{ L_ }, _libs_str) }; // L_: [fixed] ... L2:
340 STACK_CHECK_START_REL(_S, 0); 389 STACK_CHECK_START_REL(_S, 0);
341 390
342 // 'lane' is allocated from heap, not Lua, since its life span may surpass the handle's (if free running thread) 391 // 'lane' is allocated from heap, not Lua, since its life span may surpass the handle's (if free running thread)
@@ -478,49 +527,7 @@ LUAG_FUNC(lane_new)
478 STACK_CHECK(_L2, 0); 527 STACK_CHECK(_L2, 0);
479 528
480 // modules to require in the target lane *before* the function is transfered! 529 // modules to require in the target lane *before* the function is transfered!
481 StackIndex const _required_idx{ lua_isnoneornil(L_, kRequIdx) ? kIdxNone : kRequIdx }; 530 local::RequireModulesInLane(_U, L_, _L2, kRequIdx);
482 if (_required_idx != 0) {
483 int _nbRequired{ 1 };
484 DEBUGSPEW_CODE(DebugSpew(_U) << "lane_new: process 'required' list" << std::endl);
485 DEBUGSPEW_CODE(DebugSpewIndentScope _scope{ _U });
486 // should not happen, was checked in lanes.lua before calling lane_new()
487 if (luaW_type(L_, _required_idx) != LuaType::TABLE) {
488 raise_luaL_error(L_, "expected required module list as a table, got %s", luaL_typename(L_, _required_idx));
489 }
490
491 lua_pushnil(L_); // L_: [fixed] args... nil L2:
492 while (lua_next(L_, _required_idx) != 0) { // L_: [fixed] args... n "modname" L2:
493 if (luaW_type(L_, kIdxTop) != LuaType::STRING || luaW_type(L_, StackIndex{ -2 }) != LuaType::NUMBER || lua_tonumber(L_, -2) != _nbRequired) {
494 raise_luaL_error(L_, "required module list should be a list of strings");
495 } else {
496 // require the module in the target state, and populate the lookup table there too
497 std::string_view const _name{ luaW_tostring(L_, kIdxTop) };
498 DEBUGSPEW_CODE(DebugSpew(_U) << "lane_new: require '" << _name << "'" << std::endl);
499
500 // require the module in the target lane
501 lua_getglobal(_L2, "require"); // L_: [fixed] args... n "modname" L2: require()?
502 if (lua_isnil(_L2, -1)) {
503 lua_pop(_L2, 1); // L_: [fixed] args... n "modname" L2:
504 raise_luaL_error(L_, "cannot pre-require modules without loading 'package' library first");
505 } else {
506 luaW_pushstring(_L2, _name); // L_: [fixed] args... n "modname" L2: require() name
507 LuaError const _rc{ lua_pcall(_L2, 1, 1, 0) }; // L_: [fixed] args... n "modname" L2: ret/errcode
508 if (_rc != LuaError::OK) {
509 // propagate error to main state if any
510 InterCopyContext _c{ _U, DestState{ L_ }, SourceState{ _L2 }, {}, {}, {}, {}, {} };
511 std::ignore = _c.interMove(1); // L_: [fixed] args... n "modname" error L2:
512 raise_lua_error(L_);
513 }
514 // here the module was successfully required // L_: [fixed] args... n "modname" L2: ret
515 // after requiring the module, register the functions it exported in our name<->function database
516 tools::PopulateFuncLookupTable(_L2, kIdxTop, _name);
517 lua_pop(_L2, 1); // L_: [fixed] args... n "modname" L2:
518 }
519 }
520 lua_pop(L_, 1); // L_: [fixed] args... n L2:
521 ++_nbRequired;
522 } // L_: [fixed] args...
523 }
524 STACK_CHECK(L_, 0); 531 STACK_CHECK(L_, 0);
525 STACK_CHECK(_L2, 0); // L_: [fixed] args... L2: 532 STACK_CHECK(_L2, 0); // L_: [fixed] args... L2:
526 533